openpencil/packages/core/src/geometry.ts
Danila Poyarkov 9784544f1f Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests
- Strip tools/schema.ts from 1831 to 65 lines (remove duplicate tool defs)
- Fix tools/index.ts to export ALL_TOOLS from registry instead of schema
- Fix renderJsx → renderJSX typo in tools/create.ts and structure.ts
- Add geometry.ts with shared rotation/coordinate math utilities
- Add isArrayMixed() helper to use-multi-props.ts, deduplicate FillSection/StrokeSection/EffectsSection
- Fix broken test imports: use @open-pencil/core instead of relative paths into packages/core/src/
- Merge duplicate import statements across all test files
- Export profiler internals and style-run helpers from core index.ts
- Add 6 new test files: color, undo, snap, vector, style-runs, text-editor (98 new tests)
- Update renderer-effects test for renderer/ directory split
2026-03-06 22:33:10 +03:00

74 lines
1.8 KiB
TypeScript

import type { Vector } from './types'
export function degToRad(degrees: number): number {
return (degrees * Math.PI) / 180
}
export function radToDeg(radians: number): number {
return (radians * 180) / Math.PI
}
export function rotatePoint(
px: number,
py: number,
cx: number,
cy: number,
rad: number
): Vector {
const cos = Math.cos(rad)
const sin = Math.sin(rad)
return {
x: cx + (px - cx) * cos - (py - cy) * sin,
y: cy + (px - cx) * sin + (py - cy) * cos
}
}
export function rotatedCorners(
cx: number,
cy: number,
hw: number,
hh: number,
rotationDeg: number
): [Vector, Vector, Vector, Vector] {
const rad = degToRad(rotationDeg)
const cos = Math.cos(rad)
const sin = Math.sin(rad)
return [
{ x: cx + -hw * cos - -hh * sin, y: cy + -hw * sin + -hh * cos },
{ x: cx + hw * cos - -hh * sin, y: cy + hw * sin + -hh * cos },
{ x: cx + hw * cos - hh * sin, y: cy + hw * sin + hh * cos },
{ x: cx + -hw * cos - hh * sin, y: cy + -hw * sin + hh * cos }
]
}
export function rotatedBBox(
x: number,
y: number,
w: number,
h: number,
rotationDeg: number
): { left: number; right: number; top: number; bottom: number; centerX: number; centerY: number } {
if (rotationDeg === 0) {
return {
left: x,
right: x + w,
top: y,
bottom: y + h,
centerX: x + w / 2,
centerY: y + h / 2
}
}
const corners = rotatedCorners(x + w / 2, y + h / 2, w / 2, h / 2, rotationDeg)
let left = Infinity,
right = -Infinity,
top = Infinity,
bottom = -Infinity
for (const c of corners) {
left = Math.min(left, c.x)
right = Math.max(right, c.x)
top = Math.min(top, c.y)
bottom = Math.max(bottom, c.y)
}
return { left, right, top, bottom, centerX: (left + right) / 2, centerY: (top + bottom) / 2 }
}