Files
buboard/src/lib/geometry.ts
2025-12-03 11:36:00 +01:00

84 lines
1.9 KiB
TypeScript

export interface Point {
x: number;
y: number;
}
export function calculateCenterOffset(
corner: string,
deltaWidth: number,
deltaHeight: number,
rotation: number,
): Point {
const rad = (rotation * Math.PI) / 180;
const cos = Math.cos(rad);
const sin = Math.sin(rad);
let localDx = 0;
let localDy = 0;
if (corner.includes('w')) localDx = -deltaWidth / 2;
else if (corner.includes('e')) localDx = deltaWidth / 2;
if (corner.includes('n')) localDy = -deltaHeight / 2;
else if (corner.includes('s')) localDy = deltaHeight / 2;
return {
x: localDx * cos - localDy * sin,
y: localDx * sin + localDy * cos,
};
}
export function constrainToAspectRatio(
newWidth: number,
newHeight: number,
aspectRatio: number,
): { width: number; height: number } {
const newRatio = newWidth / newHeight;
if (newRatio > aspectRatio) {
return { width: newHeight * aspectRatio, height: newHeight };
} else {
return { width: newWidth, height: newWidth / aspectRatio };
}
}
export function detectRotationCorner(
localX: number,
localY: number,
halfWidth: number,
halfHeight: number,
zoneRadius: number,
): string | null {
const corners: Record<string, Point> = {
nw: { x: -halfWidth, y: -halfHeight },
ne: { x: halfWidth, y: -halfHeight },
sw: { x: -halfWidth, y: halfHeight },
se: { x: halfWidth, y: halfHeight },
};
const isInsideBounds =
localX >= -halfWidth &&
localX <= halfWidth &&
localY >= -halfHeight &&
localY <= halfHeight;
if (isInsideBounds) return null;
for (const [name, corner] of Object.entries(corners)) {
const dx = localX - corner.x;
const dy = localY - corner.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist > zoneRadius || dist < 3) continue;
const isOutwardX =
(name.includes('w') && dx < 0) || (name.includes('e') && dx > 0);
const isOutwardY =
(name.includes('n') && dy < 0) || (name.includes('s') && dy > 0);
if (isOutwardX || isOutwardY) return name;
}
return null;
}