OK
This commit is contained in:
81
src/lib/geometry.ts
Normal file
81
src/lib/geometry.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user