openpencil/tests/helpers/geometry.ts
Danila Poyarkov d16400b3e6 feat(editor): checkpoint live interaction improvements
Unify preview-aware transforms across scene drawing, labels, selection and input. Give live property and creation edits explicit preview ownership, preserve cancellation and one-step undo, and reuse bounded text preparation resources.

Include retained device-grid handling, worktree HMR coverage, and nested/reflected interaction regressions in this cohesive progress checkpoint.

Validation: full check passes; 734 scoped unit tests and 53 targeted browser tests pass. This is NOT merge-ready: the unchanged exact nested filled-section held/released regression still fails with 63 differing pixels (maximum channel delta 5/255). The browser pass count excludes that separately run failure and the previously classified paint-field-width baseline. Raster-origin investigation and broader acceptance remain outstanding.
2026-09-15 11:36:17 +03:00

60 lines
1.6 KiB
TypeScript

import type { SceneGraph, SceneNode, Vector } from '@open-pencil/scene-graph'
type FixtureNode = Pick<
SceneNode,
'type' | 'name' | 'x' | 'y' | 'width' | 'height' | 'rotation' | 'flipX' | 'flipY'
>
export function nestedGeometryData(flipX = false, flipY = false) {
const section: FixtureNode = {
type: 'SECTION',
name: 'Rotated section',
x: 140,
y: 140,
width: 500,
height: 350,
rotation: 25,
flipX,
flipY: false
}
const frame: FixtureNode = {
type: 'FRAME',
name: 'Nested frame',
x: 100,
y: 100,
width: 220,
height: 120,
rotation: -55,
flipX: false,
flipY
}
return { section, frame }
}
export function nestedGeometryFixture(
graph: SceneGraph,
parentId: string,
flipX = false,
flipY = false
) {
const data = nestedGeometryData(flipX, flipY)
const section = graph.createNode('SECTION', parentId, data.section)
const frame = graph.createNode('FRAME', section.id, data.frame)
return { section, frame }
}
/** Independent scalar oracle, not the production matrix/geometry implementation. */
export function applyFixtureTransform(node: FixtureNode, point: Vector): Vector {
const pivotX = node.type === 'LINE' ? 0 : node.width / 2
const pivotY = node.type === 'LINE' ? 0 : node.height / 2
const x = point.x - pivotX
const y = point.y - pivotY
const angle = (node.rotation * Math.PI) / 180
const rotatedX = pivotX + x * Math.cos(angle) - y * Math.sin(angle)
const rotatedY = pivotY + x * Math.sin(angle) + y * Math.cos(angle)
return {
x: node.x + (node.flipX ? node.width - rotatedX : rotatedX),
y: node.y + (node.flipY ? node.height - rotatedY : rotatedY)
}
}