@genart-dev/plugin-construction 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +263 -0
- package/dist/index.cjs +2900 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +211 -0
- package/dist/index.d.ts +211 -0
- package/dist/index.js +2842 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/shared.ts","../src/math/rotation.ts","../src/math/ellipse.ts","../src/forms/box.ts","../src/forms/cylinder.ts","../src/forms/sphere.ts","../src/forms/cone.ts","../src/forms/wedge.ts","../src/forms/egg.ts","../src/form-layer.ts","../src/cross-contour-layer.ts","../src/math/shadow.ts","../src/value-shapes-layer.ts","../src/math/envelope.ts","../src/envelope-layer.ts","../src/math/intersection.ts","../src/intersection-layer.ts","../src/construction-tools.ts"],"sourcesContent":["import type { DesignPlugin, PluginContext } from \"@genart-dev/core\";\nimport { formLayerType } from \"./form-layer.js\";\nimport { crossContourLayerType } from \"./cross-contour-layer.js\";\nimport { valueShapesLayerType } from \"./value-shapes-layer.js\";\nimport { envelopeLayerType } from \"./envelope-layer.js\";\nimport { intersectionLayerType } from \"./intersection-layer.js\";\nimport { constructionMcpTools } from \"./construction-tools.js\";\n\nconst constructionPlugin: DesignPlugin = {\n id: \"construction\",\n name: \"Construction Guides\",\n version: \"0.1.0\",\n tier: \"free\",\n description:\n \"Drawing construction guides: 3D form primitives, cross-contour lines, value/shadow studies, envelope block-ins, and form intersections.\",\n\n layerTypes: [\n formLayerType,\n crossContourLayerType,\n valueShapesLayerType,\n envelopeLayerType,\n intersectionLayerType,\n ],\n tools: [],\n exportHandlers: [],\n mcpTools: constructionMcpTools,\n\n async initialize(_context: PluginContext): Promise<void> {\n // No async setup needed\n },\n\n dispose(): void {\n // No resources to release\n },\n};\n\nexport default constructionPlugin;\nexport { formLayerType } from \"./form-layer.js\";\nexport { crossContourLayerType } from \"./cross-contour-layer.js\";\nexport { valueShapesLayerType } from \"./value-shapes-layer.js\";\nexport { envelopeLayerType } from \"./envelope-layer.js\";\nexport { intersectionLayerType } from \"./intersection-layer.js\";\nexport { constructionMcpTools } from \"./construction-tools.js\";\nexport {\n rotationMatrix,\n rotate3D,\n project,\n transformPoint,\n transformedNormalZ,\n identityMatrix,\n multiplyMat3,\n normalize3,\n dot3,\n cross3,\n clamp,\n} from \"./math/rotation.js\";\nexport {\n projectedEllipse,\n drawEllipse,\n drawEllipseWithHidden,\n ellipsePoints,\n} from \"./math/ellipse.js\";\nexport {\n lightDirection,\n lightDirection2D,\n sphereTerminator,\n castShadow,\n sphereValueZones,\n} from \"./math/shadow.js\";\nexport {\n computeEnvelope,\n envelopeAngles,\n plumbLine,\n levelLine,\n comparativeMeasure,\n} from \"./math/envelope.js\";\nexport { approximateIntersection } from \"./math/intersection.js\";\n","import type { LayerPropertySchema } from \"@genart-dev/core\";\nimport type { Vec2, Vec3 } from \"./math/rotation.js\";\n\n// ---------------------------------------------------------------------------\n// Form types\n// ---------------------------------------------------------------------------\n\nexport type FormType = \"box\" | \"cylinder\" | \"sphere\" | \"cone\" | \"wedge\" | \"egg\";\n\nexport interface FormDefinition {\n type: FormType;\n position: Vec3;\n size: Vec3; // width, height, depth\n rotation: Vec3; // Euler angles (degrees)\n}\n\nexport interface ProjectedForm {\n type: FormType;\n center: Vec2;\n bounds: { x: number; y: number; width: number; height: number };\n vertices: Vec2[];\n silhouette: Vec2[];\n}\n\n// ---------------------------------------------------------------------------\n// Common guide properties (matches plugin-perspective pattern)\n// ---------------------------------------------------------------------------\n\nexport const COMMON_GUIDE_PROPERTIES: LayerPropertySchema[] = [\n {\n key: \"guideColor\",\n label: \"Guide Color\",\n type: \"color\",\n default: \"rgba(0,200,255,0.5)\",\n group: \"style\",\n },\n {\n key: \"lineWidth\",\n label: \"Line Width\",\n type: \"number\",\n default: 1,\n min: 0.5,\n max: 5,\n step: 0.5,\n group: \"style\",\n },\n {\n key: \"dashPattern\",\n label: \"Dash Pattern\",\n type: \"string\",\n default: \"6,4\",\n group: \"style\",\n },\n];\n\n// ---------------------------------------------------------------------------\n// Drawing helpers\n// ---------------------------------------------------------------------------\n\nexport function setupGuideStyle(\n ctx: CanvasRenderingContext2D,\n color: string,\n lineWidth: number,\n dashPattern: string,\n): void {\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth;\n const dashes = dashPattern\n .split(\",\")\n .map(Number)\n .filter((n) => !isNaN(n) && n > 0);\n ctx.setLineDash(dashes.length > 0 ? dashes : [6, 4]);\n}\n\nexport function drawLine(\n ctx: CanvasRenderingContext2D,\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): void {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n}\n\nexport function drawDashedLine(\n ctx: CanvasRenderingContext2D,\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n dash: number[],\n): void {\n const saved = ctx.getLineDash();\n ctx.setLineDash(dash);\n drawLine(ctx, x1, y1, x2, y2);\n ctx.setLineDash(saved);\n}\n\nexport function drawPolyline(ctx: CanvasRenderingContext2D, points: Vec2[], close = false): void {\n if (points.length < 2) return;\n ctx.beginPath();\n ctx.moveTo(points[0]!.x, points[0]!.y);\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i]!.x, points[i]!.y);\n }\n if (close) ctx.closePath();\n ctx.stroke();\n}\n\nexport function fillPolyline(ctx: CanvasRenderingContext2D, points: Vec2[], fillStyle: string): void {\n if (points.length < 3) return;\n ctx.beginPath();\n ctx.moveTo(points[0]!.x, points[0]!.y);\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i]!.x, points[i]!.y);\n }\n ctx.closePath();\n ctx.fillStyle = fillStyle;\n ctx.fill();\n}\n\n/** Draw text label at a position. */\nexport function drawLabel(\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n color: string,\n fontSize = 10,\n): void {\n ctx.fillStyle = color;\n ctx.font = `${fontSize}px sans-serif`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n ctx.fillText(text, x, y);\n}\n\n// ---------------------------------------------------------------------------\n// Coordinate helpers\n// ---------------------------------------------------------------------------\n\n/** Convert normalized [0,1] position to pixel position within bounds. */\nexport function toPixel(\n norm: { x: number; y: number },\n bounds: { x: number; y: number; width: number; height: number },\n): Vec2 {\n return {\n x: bounds.x + norm.x * bounds.width,\n y: bounds.y + norm.y * bounds.height,\n };\n}\n\n/** Convert pixel position to normalized [0,1] within bounds. */\nexport function toNorm(\n px: Vec2,\n bounds: { x: number; y: number; width: number; height: number },\n): Vec2 {\n return {\n x: (px.x - bounds.x) / bounds.width,\n y: (px.y - bounds.y) / bounds.height,\n };\n}\n\n/** Parse a JSON string safely, returning fallback on error. */\nexport function parseJSON<T>(json: string, fallback: T): T {\n try {\n return JSON.parse(json) as T;\n } catch {\n return fallback;\n }\n}\n\n/** Parse a comma-separated color list. */\nexport function parseCSVColors(csv: string, count: number): string[] {\n const parts = csv.split(\",\").map((s) => s.trim());\n const result: string[] = [];\n const defaults = [\"red\", \"green\", \"blue\"];\n for (let i = 0; i < count; i++) {\n result.push(parts[i] || defaults[i % defaults.length]!);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Hidden edge styles\n// ---------------------------------------------------------------------------\n\nexport type HiddenEdgeStyle = \"dashed\" | \"dotted\" | \"faint\" | \"hidden\";\n\nexport function applyHiddenEdgeStyle(\n ctx: CanvasRenderingContext2D,\n style: HiddenEdgeStyle,\n alpha: number,\n): void {\n switch (style) {\n case \"dashed\":\n ctx.setLineDash([6, 4]);\n ctx.globalAlpha = alpha;\n break;\n case \"dotted\":\n ctx.setLineDash([2, 3]);\n ctx.globalAlpha = alpha;\n break;\n case \"faint\":\n ctx.setLineDash([]);\n ctx.globalAlpha = alpha * 0.5;\n break;\n case \"hidden\":\n ctx.globalAlpha = 0;\n break;\n }\n}\n\nexport function resetEdgeStyle(\n ctx: CanvasRenderingContext2D,\n savedAlpha: number,\n): void {\n ctx.setLineDash([]);\n ctx.globalAlpha = savedAlpha;\n}\n","/** 3D vector. */\nexport interface Vec3 {\n x: number;\n y: number;\n z: number;\n}\n\n/** 2D vector. */\nexport interface Vec2 {\n x: number;\n y: number;\n}\n\n/** 3x3 matrix stored as row-major flat array. */\nexport type Mat3 = [\n number, number, number,\n number, number, number,\n number, number, number,\n];\n\nconst DEG2RAD = Math.PI / 180;\n\n/** Clamp a value to [min, max]. */\nexport function clamp(v: number, min: number, max: number): number {\n return v < min ? min : v > max ? max : v;\n}\n\n/**\n * Build a ZYX Euler rotation matrix from angles in degrees.\n * rotationX is clamped to [-90, 90] to avoid gimbal lock.\n *\n * R = Rz * Ry * Rx\n */\nexport function rotationMatrix(rxDeg: number, ryDeg: number, rzDeg: number): Mat3 {\n const rx = clamp(rxDeg, -90, 90) * DEG2RAD;\n const ry = ryDeg * DEG2RAD;\n const rz = rzDeg * DEG2RAD;\n\n const cx = Math.cos(rx), sx = Math.sin(rx);\n const cy = Math.cos(ry), sy = Math.sin(ry);\n const cz = Math.cos(rz), sz = Math.sin(rz);\n\n // Rz * Ry * Rx (row-major)\n return [\n cz * cy, cz * sy * sx - sz * cx, cz * sy * cx + sz * sx,\n sz * cy, sz * sy * sx + cz * cx, sz * sy * cx - cz * sx,\n -sy, cy * sx, cy * cx,\n ];\n}\n\n/** Multiply a Mat3 by a Vec3, returning a new Vec3. */\nexport function rotate3D(point: Vec3, m: Mat3): Vec3 {\n return {\n x: m[0] * point.x + m[1] * point.y + m[2] * point.z,\n y: m[3] * point.x + m[4] * point.y + m[5] * point.z,\n z: m[6] * point.x + m[7] * point.y + m[8] * point.z,\n };\n}\n\n/**\n * Project a 3D point to 2D.\n *\n * - \"orthographic\": drops Z (screen.x = point.x, screen.y = point.y)\n * - \"weak-perspective\": mild foreshortening based on Z depth\n * scale = focalLength / (focalLength + point.z)\n */\nexport function project(\n point: Vec3,\n projection: \"orthographic\" | \"weak-perspective\" = \"orthographic\",\n focalLength = 5,\n): Vec2 {\n if (projection === \"weak-perspective\") {\n const scale = focalLength / (focalLength + point.z);\n return { x: point.x * scale, y: point.y * scale };\n }\n return { x: point.x, y: point.y };\n}\n\n/**\n * Convenience: rotate a 3D point then project to 2D.\n * rotationX is clamped to [-90, 90].\n */\nexport function transformPoint(\n point: Vec3,\n rxDeg: number,\n ryDeg: number,\n rzDeg: number,\n projection: \"orthographic\" | \"weak-perspective\" = \"orthographic\",\n focalLength = 5,\n): Vec2 {\n const m = rotationMatrix(rxDeg, ryDeg, rzDeg);\n const rotated = rotate3D(point, m);\n return project(rotated, projection, focalLength);\n}\n\n/** Transform a 3D normal vector and return the Z component (for face visibility). */\nexport function transformedNormalZ(normal: Vec3, m: Mat3): number {\n return m[6] * normal.x + m[7] * normal.y + m[8] * normal.z;\n}\n\n/** Compute the identity matrix. */\nexport function identityMatrix(): Mat3 {\n return [1, 0, 0, 0, 1, 0, 0, 0, 1];\n}\n\n/** Multiply two Mat3 matrices: result = a * b. */\nexport function multiplyMat3(a: Mat3, b: Mat3): Mat3 {\n return [\n a[0]*b[0] + a[1]*b[3] + a[2]*b[6], a[0]*b[1] + a[1]*b[4] + a[2]*b[7], a[0]*b[2] + a[1]*b[5] + a[2]*b[8],\n a[3]*b[0] + a[4]*b[3] + a[5]*b[6], a[3]*b[1] + a[4]*b[4] + a[5]*b[7], a[3]*b[2] + a[4]*b[5] + a[5]*b[8],\n a[6]*b[0] + a[7]*b[3] + a[8]*b[6], a[6]*b[1] + a[7]*b[4] + a[8]*b[7], a[6]*b[2] + a[7]*b[5] + a[8]*b[8],\n ];\n}\n\n/** Normalize a Vec3 to unit length. Returns zero vector if length is ~0. */\nexport function normalize3(v: Vec3): Vec3 {\n const len = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);\n if (len < 1e-10) return { x: 0, y: 0, z: 0 };\n return { x: v.x / len, y: v.y / len, z: v.z / len };\n}\n\n/** Dot product of two Vec3. */\nexport function dot3(a: Vec3, b: Vec3): number {\n return a.x * b.x + a.y * b.y + a.z * b.z;\n}\n\n/** Cross product of two Vec3. */\nexport function cross3(a: Vec3, b: Vec3): Vec3 {\n return {\n x: a.y * b.z - a.z * b.y,\n y: a.z * b.x - a.x * b.z,\n z: a.x * b.y - a.y * b.x,\n };\n}\n\n/** Distance between two Vec2 points. */\nexport function dist2(a: Vec2, b: Vec2): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/** Lerp between two Vec2 points. */\nexport function lerp2(a: Vec2, b: Vec2, t: number): Vec2 {\n return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };\n}\n\n/** Lerp between two Vec3 points. */\nexport function lerp3(a: Vec3, b: Vec3, t: number): Vec3 {\n return {\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n z: a.z + (b.z - a.z) * t,\n };\n}\n","import type { Vec2 } from \"./rotation.js\";\n\nexport interface EllipseParams {\n cx: number;\n cy: number;\n rx: number;\n ry: number;\n rotation: number; // radians\n}\n\nconst DEG2RAD = Math.PI / 180;\n\n/**\n * Compute ellipse parameters from a circle viewed at an angle.\n *\n * A circle of `radius` whose normal is tilted by `normalTilt` degrees from\n * the viewer becomes an ellipse with:\n * - major axis = radius (unchanged)\n * - minor axis = radius * |cos(normalTilt)|\n *\n * `axisRotation` is the rotation of the ellipse's major axis on the 2D plane (degrees).\n */\nexport function projectedEllipse(\n center: Vec2,\n radius: number,\n normalTilt: number,\n axisRotation: number,\n): EllipseParams {\n const tiltRad = normalTilt * DEG2RAD;\n const minor = radius * Math.abs(Math.cos(tiltRad));\n return {\n cx: center.x,\n cy: center.y,\n rx: radius,\n ry: minor,\n rotation: axisRotation * DEG2RAD,\n };\n}\n\n/**\n * Draw an ellipse (or partial arc) on a Canvas2D context.\n * Strokes the path — caller should set strokeStyle/lineWidth beforehand.\n *\n * @param startAngle - Arc start in radians (default 0)\n * @param endAngle - Arc end in radians (default 2π)\n * @param counterclockwise - Direction of arc (default false)\n */\nexport function drawEllipse(\n ctx: CanvasRenderingContext2D,\n cx: number,\n cy: number,\n rx: number,\n ry: number,\n rotation: number,\n startAngle = 0,\n endAngle = Math.PI * 2,\n counterclockwise = false,\n): void {\n ctx.beginPath();\n ctx.ellipse(cx, cy, Math.abs(rx), Math.abs(ry), rotation, startAngle, endAngle, counterclockwise);\n ctx.stroke();\n}\n\n/**\n * Draw an ellipse with separate visible and hidden arcs.\n * The \"front\" half (facing viewer) is drawn solid;\n * the \"back\" half is drawn with the provided hidden style.\n *\n * @param frontHalf - Angle range in radians for the visible portion [start, end]\n * @param hiddenAlpha - Alpha for hidden portion\n * @param hiddenDash - Dash pattern for hidden portion\n */\nexport function drawEllipseWithHidden(\n ctx: CanvasRenderingContext2D,\n params: EllipseParams,\n frontHalf: [number, number],\n hiddenAlpha: number,\n hiddenDash: number[],\n): void {\n const { cx, cy, rx, ry, rotation } = params;\n if (rx < 0.5 || ry < 0.5) return;\n\n const savedAlpha = ctx.globalAlpha;\n const savedDash = ctx.getLineDash();\n\n // Draw visible arc\n ctx.beginPath();\n ctx.ellipse(cx, cy, rx, ry, rotation, frontHalf[0], frontHalf[1], false);\n ctx.stroke();\n\n // Draw hidden arc\n ctx.globalAlpha = hiddenAlpha;\n ctx.setLineDash(hiddenDash);\n ctx.beginPath();\n ctx.ellipse(cx, cy, rx, ry, rotation, frontHalf[1], frontHalf[0] + Math.PI * 2, false);\n ctx.stroke();\n\n // Restore\n ctx.globalAlpha = savedAlpha;\n ctx.setLineDash(savedDash);\n}\n\n/**\n * Compute points along an ellipse for use in path construction.\n */\nexport function ellipsePoints(\n params: EllipseParams,\n segments: number,\n startAngle = 0,\n endAngle = Math.PI * 2,\n): Vec2[] {\n const { cx, cy, rx, ry, rotation } = params;\n const cos = Math.cos(rotation);\n const sin = Math.sin(rotation);\n const points: Vec2[] = [];\n\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n const angle = startAngle + (endAngle - startAngle) * t;\n const px = rx * Math.cos(angle);\n const py = ry * Math.sin(angle);\n points.push({\n x: cx + px * cos - py * sin,\n y: cy + px * sin + py * cos,\n });\n }\n return points;\n}\n\n/**\n * Compute the tangent points where lines from an external point touch an ellipse.\n * Returns two angles on the ellipse (approximate — uses sampling).\n */\nexport function ellipseTangentAngles(\n params: EllipseParams,\n externalPoint: Vec2,\n samples = 72,\n): [number, number] {\n const points = ellipsePoints(params, samples);\n let bestLeft = 0;\n let bestRight = 0;\n let maxCross = -Infinity;\n let minCross = Infinity;\n\n for (let i = 0; i < points.length; i++) {\n const p = points[i]!;\n const dx = p.x - externalPoint.x;\n const dy = p.y - externalPoint.y;\n // Cross product with reference direction (from external to center)\n const refDx = params.cx - externalPoint.x;\n const refDy = params.cy - externalPoint.y;\n const cross = dx * refDy - dy * refDx;\n if (cross > maxCross) {\n maxCross = cross;\n bestLeft = i;\n }\n if (cross < minCross) {\n minCross = cross;\n bestRight = i;\n }\n }\n\n const step = (Math.PI * 2) / samples;\n return [bestLeft * step, bestRight * step];\n}\n","import type { Vec2, Vec3, Mat3 } from \"../math/rotation.js\";\nimport { rotate3D, transformedNormalZ } from \"../math/rotation.js\";\nimport { project } from \"../math/rotation.js\";\nimport { drawLine, applyHiddenEdgeStyle, resetEdgeStyle, type HiddenEdgeStyle } from \"../shared.js\";\n\n/** A 3D box edge: two vertex indices + the two face normals it borders. */\ninterface BoxEdge {\n a: number;\n b: number;\n faces: [number, number]; // Indices into FACE_NORMALS\n}\n\n// Box has 8 vertices at ±0.5 on each axis\nconst BOX_VERTICES: Vec3[] = [\n { x: -0.5, y: -0.5, z: -0.5 }, // 0: left-bottom-back\n { x: 0.5, y: -0.5, z: -0.5 }, // 1: right-bottom-back\n { x: 0.5, y: 0.5, z: -0.5 }, // 2: right-top-back\n { x: -0.5, y: 0.5, z: -0.5 }, // 3: left-top-back\n { x: -0.5, y: -0.5, z: 0.5 }, // 4: left-bottom-front\n { x: 0.5, y: -0.5, z: 0.5 }, // 5: right-bottom-front\n { x: 0.5, y: 0.5, z: 0.5 }, // 6: right-top-front\n { x: -0.5, y: 0.5, z: 0.5 }, // 7: left-top-front\n];\n\n// 6 face outward normals\nconst FACE_NORMALS: Vec3[] = [\n { x: 0, y: 0, z: 1 }, // 0: front\n { x: 0, y: 0, z: -1 }, // 1: back\n { x: 1, y: 0, z: 0 }, // 2: right\n { x: -1, y: 0, z: 0 }, // 3: left\n { x: 0, y: 1, z: 0 }, // 4: top\n { x: 0, y: -1, z: 0 }, // 5: bottom\n];\n\n// 12 edges with their two bordering faces\nconst BOX_EDGES: BoxEdge[] = [\n // Front face edges\n { a: 4, b: 5, faces: [0, 5] }, // front-bottom\n { a: 5, b: 6, faces: [0, 2] }, // front-right\n { a: 6, b: 7, faces: [0, 4] }, // front-top\n { a: 7, b: 4, faces: [0, 3] }, // front-left\n // Back face edges\n { a: 0, b: 1, faces: [1, 5] }, // back-bottom\n { a: 1, b: 2, faces: [1, 2] }, // back-right\n { a: 2, b: 3, faces: [1, 4] }, // back-top\n { a: 3, b: 0, faces: [1, 3] }, // back-left\n // Connecting edges (front-to-back)\n { a: 4, b: 0, faces: [3, 5] }, // left-bottom\n { a: 5, b: 1, faces: [2, 5] }, // right-bottom\n { a: 6, b: 2, faces: [2, 4] }, // right-top\n { a: 7, b: 3, faces: [3, 4] }, // left-top\n];\n\nexport interface BoxRenderOptions {\n center: Vec2;\n scale: number;\n sizeX: number;\n sizeY: number;\n sizeZ: number;\n matrix: Mat3;\n projection: \"orthographic\" | \"weak-perspective\";\n focalLength: number;\n showHidden: boolean;\n hiddenStyle: HiddenEdgeStyle;\n hiddenAlpha: number;\n edgeColor: string;\n}\n\n/** Classify an edge as front-facing if at least one of its bordering faces is front-facing. */\nfunction isEdgeFrontFacing(edge: BoxEdge, faceVisibility: boolean[]): boolean {\n return faceVisibility[edge.faces[0]]! || faceVisibility[edge.faces[1]]!;\n}\n\nexport function renderBox(ctx: CanvasRenderingContext2D, opts: BoxRenderOptions): Vec2[] {\n const { center, scale, sizeX, sizeY, sizeZ, matrix, projection, focalLength, showHidden, hiddenStyle, hiddenAlpha, edgeColor } = opts;\n\n // Transform vertices\n const projected: Vec2[] = BOX_VERTICES.map((v) => {\n const scaled: Vec3 = { x: v.x * sizeX, y: v.y * sizeY, z: v.z * sizeZ };\n const rotated = rotate3D(scaled, matrix);\n const p = project(rotated, projection, focalLength);\n return { x: center.x + p.x * scale, y: center.y - p.y * scale }; // flip Y for screen\n });\n\n // Compute face visibility (face is visible if its transformed normal points toward viewer, i.e. Z > 0)\n const faceVisibility = FACE_NORMALS.map((n) => transformedNormalZ(n, matrix) > 0);\n\n ctx.strokeStyle = edgeColor;\n const savedAlpha = ctx.globalAlpha;\n\n // Draw back edges first (if showing hidden)\n if (showHidden) {\n applyHiddenEdgeStyle(ctx, hiddenStyle, hiddenAlpha);\n for (const edge of BOX_EDGES) {\n if (!isEdgeFrontFacing(edge, faceVisibility)) {\n const pa = projected[edge.a]!;\n const pb = projected[edge.b]!;\n drawLine(ctx, pa.x, pa.y, pb.x, pb.y);\n }\n }\n resetEdgeStyle(ctx, savedAlpha);\n }\n\n // Draw front edges\n ctx.setLineDash([]);\n ctx.globalAlpha = savedAlpha;\n for (const edge of BOX_EDGES) {\n if (isEdgeFrontFacing(edge, faceVisibility)) {\n const pa = projected[edge.a]!;\n const pb = projected[edge.b]!;\n drawLine(ctx, pa.x, pa.y, pb.x, pb.y);\n }\n }\n\n return projected;\n}\n\n/** Get cross-contour lines for visible box faces (parallel lines on each visible face). */\nexport function boxCrossContours(\n opts: BoxRenderOptions,\n count: number,\n): { front: Vec2[][]; hidden: Vec2[][] } {\n const { center, scale, sizeX, sizeY, sizeZ, matrix, projection, focalLength } = opts;\n const faceVisibility = FACE_NORMALS.map((n) => transformedNormalZ(n, matrix) > 0);\n\n const front: Vec2[][] = [];\n const hidden: Vec2[][] = [];\n\n // Cross-contours on each face: lines perpendicular to the face's primary axis\n const faceContours: { faceIdx: number; generate: () => Vec3[][] }[] = [\n // Front/back faces: horizontal lines\n { faceIdx: 0, generate: () => generateFaceContours(sizeX, sizeY, 0.5 * sizeZ, \"xy\", count) },\n { faceIdx: 1, generate: () => generateFaceContours(sizeX, sizeY, -0.5 * sizeZ, \"xy\", count) },\n // Right/left faces: horizontal lines\n { faceIdx: 2, generate: () => generateFaceContours(sizeZ, sizeY, 0.5 * sizeX, \"zy-right\", count) },\n { faceIdx: 3, generate: () => generateFaceContours(sizeZ, sizeY, -0.5 * sizeX, \"zy-left\", count) },\n // Top/bottom faces: depth lines\n { faceIdx: 4, generate: () => generateFaceContours(sizeX, sizeZ, 0.5 * sizeY, \"xz-top\", count) },\n { faceIdx: 5, generate: () => generateFaceContours(sizeX, sizeZ, -0.5 * sizeY, \"xz-bottom\", count) },\n ];\n\n for (const fc of faceContours) {\n const lines3D = fc.generate();\n const lines2D = lines3D.map((line) =>\n line.map((p) => {\n const rotated = rotate3D(p, matrix);\n const proj = project(rotated, projection, focalLength);\n return { x: center.x + proj.x * scale, y: center.y - proj.y * scale };\n }),\n );\n\n if (faceVisibility[fc.faceIdx]) {\n front.push(...lines2D);\n } else {\n hidden.push(...lines2D);\n }\n }\n\n return { front, hidden };\n}\n\nfunction generateFaceContours(\n width: number,\n height: number,\n fixedCoord: number,\n plane: string,\n count: number,\n): Vec3[][] {\n const lines: Vec3[][] = [];\n for (let i = 1; i < count; i++) {\n const t = i / count - 0.5;\n const line: Vec3[] = [];\n switch (plane) {\n case \"xy\":\n line.push({ x: -width / 2, y: t * height, z: fixedCoord });\n line.push({ x: width / 2, y: t * height, z: fixedCoord });\n break;\n case \"zy-right\":\n line.push({ x: fixedCoord, y: t * height, z: -width / 2 });\n line.push({ x: fixedCoord, y: t * height, z: width / 2 });\n break;\n case \"zy-left\":\n line.push({ x: fixedCoord, y: t * height, z: -width / 2 });\n line.push({ x: fixedCoord, y: t * height, z: width / 2 });\n break;\n case \"xz-top\":\n line.push({ x: -width / 2, y: fixedCoord, z: t * height });\n line.push({ x: width / 2, y: fixedCoord, z: t * height });\n break;\n case \"xz-bottom\":\n line.push({ x: -width / 2, y: fixedCoord, z: t * height });\n line.push({ x: width / 2, y: fixedCoord, z: t * height });\n break;\n }\n lines.push(line);\n }\n return lines;\n}\n","import type { Vec2, Vec3, Mat3 } from \"../math/rotation.js\";\nimport { rotate3D, project, normalize3, cross3 } from \"../math/rotation.js\";\nimport { drawEllipseWithHidden, type EllipseParams } from \"../math/ellipse.js\";\nimport { drawLine, applyHiddenEdgeStyle, resetEdgeStyle, type HiddenEdgeStyle } from \"../shared.js\";\n\nexport interface CylinderRenderOptions {\n center: Vec2;\n scale: number;\n sizeX: number; // radius multiplier\n sizeY: number; // height\n sizeZ: number; // radius multiplier (depth)\n matrix: Mat3;\n projection: \"orthographic\" | \"weak-perspective\";\n focalLength: number;\n showHidden: boolean;\n hiddenStyle: HiddenEdgeStyle;\n hiddenAlpha: number;\n edgeColor: string;\n}\n\nfunction projectVertex(v: Vec3, opts: CylinderRenderOptions): Vec2 {\n const rotated = rotate3D(v, opts.matrix);\n const p = project(rotated, opts.projection, opts.focalLength);\n return { x: opts.center.x + p.x * opts.scale, y: opts.center.y - p.y * opts.scale };\n}\n\n/**\n * Compute the 2D ellipse for a circle at a given height along the cylinder axis.\n * The cylinder axis is Y in local space. The circle lies in the XZ plane.\n */\nfunction cylinderEllipseAt(\n yPos: number,\n opts: CylinderRenderOptions,\n): { params: EllipseParams; axisDir: Vec2; topSideVisible: boolean } {\n const { matrix, center, scale, sizeX, sizeZ } = opts;\n\n // Center of the ellipse\n const center3D: Vec3 = { x: 0, y: yPos, z: 0 };\n const center2D = projectVertex(center3D, opts);\n\n // The circle normal is the Y axis in local space; transform it\n const yAxisRotated = rotate3D({ x: 0, y: 1, z: 0 }, matrix);\n const topSideVisible = yAxisRotated.z > 0; // Z > 0 means normal points toward viewer\n\n // The radius in X and Z determines the ellipse axes\n // We compute by transforming two points on the circle\n const px = projectVertex({ x: sizeX * 0.5, y: yPos, z: 0 }, opts);\n const pz = projectVertex({ x: 0, y: yPos, z: sizeZ * 0.5 }, opts);\n\n // Ellipse semi-axes from center to these projected points\n const ax = Math.sqrt((px.x - center2D.x) ** 2 + (px.y - center2D.y) ** 2);\n const az = Math.sqrt((pz.x - center2D.x) ** 2 + (pz.y - center2D.y) ** 2);\n\n // Rotation angle of the ellipse on screen\n const angle = Math.atan2(px.y - center2D.y, px.x - center2D.x);\n\n // Axis direction in 2D (for tangent lines)\n const topP = projectVertex({ x: 0, y: opts.sizeY / 2, z: 0 }, opts);\n const botP = projectVertex({ x: 0, y: -opts.sizeY / 2, z: 0 }, opts);\n const axisDir: Vec2 = {\n x: topP.x - botP.x,\n y: topP.y - botP.y,\n };\n\n return {\n params: { cx: center2D.x, cy: center2D.y, rx: Math.max(ax, az), ry: Math.min(ax, az), rotation: angle },\n axisDir,\n topSideVisible,\n };\n}\n\nexport function renderCylinder(ctx: CanvasRenderingContext2D, opts: CylinderRenderOptions): void {\n const { showHidden, hiddenStyle, hiddenAlpha, edgeColor, sizeY } = opts;\n const halfH = sizeY / 2;\n\n ctx.strokeStyle = edgeColor;\n const savedAlpha = ctx.globalAlpha;\n\n // Top and bottom ellipses\n const topEllipse = cylinderEllipseAt(halfH, opts);\n const botEllipse = cylinderEllipseAt(-halfH, opts);\n\n const hiddenDash = hiddenStyle === \"dotted\" ? [2, 3] : [6, 4];\n\n // Determine which half of each ellipse is visible\n // Top ellipse: if viewer can see the top, the near half is front-facing\n const topFront: [number, number] = topEllipse.topSideVisible ? [0, Math.PI] : [Math.PI, Math.PI * 2];\n const botFront: [number, number] = !botEllipse.topSideVisible ? [0, Math.PI] : [Math.PI, Math.PI * 2];\n\n // Draw tangent lines connecting top and bottom ellipses\n // Use the leftmost and rightmost points of the ellipses\n const topLeft = ellipsePointAt(topEllipse.params, Math.PI);\n const topRight = ellipsePointAt(topEllipse.params, 0);\n const botLeft = ellipsePointAt(botEllipse.params, Math.PI);\n const botRight = ellipsePointAt(botEllipse.params, 0);\n\n ctx.setLineDash([]);\n ctx.globalAlpha = savedAlpha;\n drawLine(ctx, topLeft.x, topLeft.y, botLeft.x, botLeft.y);\n drawLine(ctx, topRight.x, topRight.y, botRight.x, botRight.y);\n\n // Draw ellipses with hidden portions\n if (showHidden) {\n drawEllipseWithHidden(ctx, topEllipse.params, topFront, hiddenAlpha, hiddenDash);\n drawEllipseWithHidden(ctx, botEllipse.params, botFront, hiddenAlpha, hiddenDash);\n } else {\n // Only draw visible arcs\n ctx.beginPath();\n ctx.ellipse(\n topEllipse.params.cx, topEllipse.params.cy,\n topEllipse.params.rx, topEllipse.params.ry,\n topEllipse.params.rotation, topFront[0], topFront[1],\n );\n ctx.stroke();\n ctx.beginPath();\n ctx.ellipse(\n botEllipse.params.cx, botEllipse.params.cy,\n botEllipse.params.rx, botEllipse.params.ry,\n botEllipse.params.rotation, botFront[0], botFront[1],\n );\n ctx.stroke();\n }\n}\n\n/** Get cross-contour ellipses along the cylinder axis. */\nexport function cylinderCrossContours(\n opts: CylinderRenderOptions,\n count: number,\n): { params: EllipseParams; frontHalf: [number, number] }[] {\n const halfH = opts.sizeY / 2;\n const contours: { params: EllipseParams; frontHalf: [number, number] }[] = [];\n\n for (let i = 1; i < count; i++) {\n const t = i / count;\n const y = -halfH + t * opts.sizeY;\n const ellipse = cylinderEllipseAt(y, opts);\n const frontHalf: [number, number] = ellipse.topSideVisible ? [0, Math.PI] : [Math.PI, Math.PI * 2];\n contours.push({ params: ellipse.params, frontHalf });\n }\n\n return contours;\n}\n\nfunction ellipsePointAt(params: EllipseParams, angle: number): Vec2 {\n const cos = Math.cos(params.rotation);\n const sin = Math.sin(params.rotation);\n const px = params.rx * Math.cos(angle);\n const py = params.ry * Math.sin(angle);\n return {\n x: params.cx + px * cos - py * sin,\n y: params.cy + px * sin + py * cos,\n };\n}\n","import type { Vec2, Vec3, Mat3 } from \"../math/rotation.js\";\nimport { rotate3D, project } from \"../math/rotation.js\";\nimport { drawEllipseWithHidden, type EllipseParams } from \"../math/ellipse.js\";\nimport type { HiddenEdgeStyle } from \"../shared.js\";\n\nexport interface SphereRenderOptions {\n center: Vec2;\n scale: number;\n radius: number;\n matrix: Mat3;\n projection: \"orthographic\" | \"weak-perspective\";\n focalLength: number;\n showHidden: boolean;\n hiddenStyle: HiddenEdgeStyle;\n hiddenAlpha: number;\n edgeColor: string;\n}\n\nfunction projectVertex(v: Vec3, opts: SphereRenderOptions): Vec2 {\n const rotated = rotate3D(v, opts.matrix);\n const p = project(rotated, opts.projection, opts.focalLength);\n return { x: opts.center.x + p.x * opts.scale, y: opts.center.y - p.y * opts.scale };\n}\n\nexport function renderSphere(ctx: CanvasRenderingContext2D, opts: SphereRenderOptions): void {\n const { center, scale, radius, edgeColor } = opts;\n const screenRadius = radius * scale;\n\n ctx.strokeStyle = edgeColor;\n\n // Outline circle (always circular in orthographic projection)\n ctx.beginPath();\n ctx.arc(center.x, center.y, screenRadius, 0, Math.PI * 2);\n ctx.stroke();\n}\n\n/**\n * Generate cross-contour ellipses for a sphere.\n * Produces latitude lines (horizontal cross-sections) and longitude lines (vertical slices).\n */\nexport function sphereCrossContours(\n opts: SphereRenderOptions,\n latCount: number,\n lonCount: number,\n): { params: EllipseParams; frontHalf: [number, number] }[] {\n const { center, scale, radius, matrix, projection, focalLength } = opts;\n const contours: { params: EllipseParams; frontHalf: [number, number] }[] = [];\n const r = radius;\n\n // Latitude lines (circles in XZ plane at different Y heights)\n for (let i = 1; i < latCount; i++) {\n const t = i / latCount;\n const y = -r + t * 2 * r;\n const circleRadius = Math.sqrt(r * r - y * y);\n\n // Project the circle center and a point on the circle\n const circleCenter: Vec3 = { x: 0, y, z: 0 };\n const cc2D = projectVertex(circleCenter, opts);\n\n // Project two points on the circle to get ellipse axes\n const px = projectVertex({ x: circleRadius, y, z: 0 }, opts);\n const pz = projectVertex({ x: 0, y, z: circleRadius }, opts);\n\n const ax = Math.sqrt((px.x - cc2D.x) ** 2 + (px.y - cc2D.y) ** 2);\n const az = Math.sqrt((pz.x - cc2D.x) ** 2 + (pz.y - cc2D.y) ** 2);\n const angle = Math.atan2(px.y - cc2D.y, px.x - cc2D.x);\n\n // The circle's normal (Y axis) transformed — Z component determines visibility\n const normalZ = rotate3D({ x: 0, y: 1, z: 0 }, matrix).z;\n const topVisible = normalZ > 0;\n\n // For latitude lines above equator: front-facing depends on tilt\n const isAboveEquator = y > 0;\n const frontHalf: [number, number] = (isAboveEquator === topVisible)\n ? [0, Math.PI]\n : [Math.PI, Math.PI * 2];\n\n contours.push({\n params: { cx: cc2D.x, cy: cc2D.y, rx: Math.max(ax, az), ry: Math.min(ax, az), rotation: angle },\n frontHalf,\n });\n }\n\n // Longitude lines (circles in XY plane at different Z angles)\n for (let i = 0; i < lonCount; i++) {\n const angle = (i / lonCount) * Math.PI;\n\n // Circle lies in a plane defined by Y axis and a direction in XZ\n const nx = Math.cos(angle);\n const nz = Math.sin(angle);\n\n // Project two points on this great circle\n const p1 = projectVertex({ x: nx * r, y: 0, z: nz * r }, opts);\n const p2 = projectVertex({ x: -nx * r, y: 0, z: -nz * r }, opts);\n const pTop = projectVertex({ x: 0, y: r, z: 0 }, opts);\n const pBot = projectVertex({ x: 0, y: -r, z: 0 }, opts);\n\n // The great circle center is sphere center\n const cc2D = { x: center.x, y: center.y };\n\n // Compute axes from projected points\n const ax1 = Math.sqrt((p1.x - cc2D.x) ** 2 + (p1.y - cc2D.y) ** 2);\n const ax2 = Math.sqrt((pTop.x - cc2D.x) ** 2 + (pTop.y - cc2D.y) ** 2);\n const rot = Math.atan2(p1.y - cc2D.y, p1.x - cc2D.x);\n\n // Normal to this slice is perpendicular in XZ plane\n const sliceNormalZ = rotate3D({ x: -nz, y: 0, z: nx }, matrix).z;\n const frontHalf: [number, number] = sliceNormalZ > 0\n ? [0, Math.PI]\n : [Math.PI, Math.PI * 2];\n\n contours.push({\n params: { cx: cc2D.x, cy: cc2D.y, rx: Math.max(ax1, ax2), ry: Math.min(ax1, ax2), rotation: rot },\n frontHalf,\n });\n }\n\n return contours;\n}\n","import type { Vec2, Vec3, Mat3 } from \"../math/rotation.js\";\nimport { rotate3D, project } from \"../math/rotation.js\";\nimport { drawEllipseWithHidden, type EllipseParams } from \"../math/ellipse.js\";\nimport { drawLine, applyHiddenEdgeStyle, resetEdgeStyle, type HiddenEdgeStyle } from \"../shared.js\";\n\nexport interface ConeRenderOptions {\n center: Vec2;\n scale: number;\n sizeX: number; // base radius X\n sizeY: number; // height\n sizeZ: number; // base radius Z\n matrix: Mat3;\n projection: \"orthographic\" | \"weak-perspective\";\n focalLength: number;\n showHidden: boolean;\n hiddenStyle: HiddenEdgeStyle;\n hiddenAlpha: number;\n edgeColor: string;\n}\n\nfunction projectVertex(v: Vec3, opts: ConeRenderOptions): Vec2 {\n const rotated = rotate3D(v, opts.matrix);\n const p = project(rotated, opts.projection, opts.focalLength);\n return { x: opts.center.x + p.x * opts.scale, y: opts.center.y - p.y * opts.scale };\n}\n\nexport function renderCone(ctx: CanvasRenderingContext2D, opts: ConeRenderOptions): void {\n const { sizeX, sizeY, sizeZ, edgeColor, showHidden, hiddenStyle, hiddenAlpha, matrix } = opts;\n const halfH = sizeY / 2;\n\n ctx.strokeStyle = edgeColor;\n const savedAlpha = ctx.globalAlpha;\n\n // Apex at top\n const apex = projectVertex({ x: 0, y: halfH, z: 0 }, opts);\n\n // Base ellipse at bottom\n const baseCenter = projectVertex({ x: 0, y: -halfH, z: 0 }, opts);\n const basePx = projectVertex({ x: sizeX * 0.5, y: -halfH, z: 0 }, opts);\n const basePz = projectVertex({ x: 0, y: -halfH, z: sizeZ * 0.5 }, opts);\n\n const ax = Math.sqrt((basePx.x - baseCenter.x) ** 2 + (basePx.y - baseCenter.y) ** 2);\n const az = Math.sqrt((basePz.x - baseCenter.x) ** 2 + (basePz.y - baseCenter.y) ** 2);\n const angle = Math.atan2(basePx.y - baseCenter.y, basePx.x - baseCenter.x);\n\n const baseEllipse: EllipseParams = {\n cx: baseCenter.x,\n cy: baseCenter.y,\n rx: Math.max(ax, az),\n ry: Math.min(ax, az),\n rotation: angle,\n };\n\n // Base visibility: bottom normal\n const bottomNormalZ = rotate3D({ x: 0, y: -1, z: 0 }, matrix).z;\n const baseVisible = bottomNormalZ > 0;\n const baseFront: [number, number] = baseVisible ? [0, Math.PI] : [Math.PI, Math.PI * 2];\n\n const hiddenDash = hiddenStyle === \"dotted\" ? [2, 3] : [6, 4];\n\n // Draw tangent lines from apex to base ellipse edges\n const leftPoint = ellipsePointAt(baseEllipse, Math.PI);\n const rightPoint = ellipsePointAt(baseEllipse, 0);\n\n ctx.setLineDash([]);\n ctx.globalAlpha = savedAlpha;\n drawLine(ctx, apex.x, apex.y, leftPoint.x, leftPoint.y);\n drawLine(ctx, apex.x, apex.y, rightPoint.x, rightPoint.y);\n\n // Draw base ellipse with hidden portions\n if (showHidden) {\n drawEllipseWithHidden(ctx, baseEllipse, baseFront, hiddenAlpha, hiddenDash);\n } else {\n ctx.beginPath();\n ctx.ellipse(\n baseEllipse.cx, baseEllipse.cy,\n baseEllipse.rx, baseEllipse.ry,\n baseEllipse.rotation, baseFront[0], baseFront[1],\n );\n ctx.stroke();\n }\n}\n\n/** Cross-contour ellipses tapering from base toward apex. */\nexport function coneCrossContours(\n opts: ConeRenderOptions,\n count: number,\n): { params: EllipseParams; frontHalf: [number, number] }[] {\n const { sizeX, sizeY, sizeZ, matrix } = opts;\n const halfH = sizeY / 2;\n const contours: { params: EllipseParams; frontHalf: [number, number] }[] = [];\n\n for (let i = 1; i < count; i++) {\n const t = i / count;\n const y = -halfH + t * sizeY;\n // Radius tapers linearly from base to apex\n const taper = 1 - (y + halfH) / sizeY;\n const rx = sizeX * 0.5 * taper;\n const rz = sizeZ * 0.5 * taper;\n\n if (rx < 0.001 || rz < 0.001) continue;\n\n const cc = projectVertex({ x: 0, y, z: 0 }, opts);\n const px = projectVertex({ x: rx, y, z: 0 }, opts);\n const pz = projectVertex({ x: 0, y, z: rz }, opts);\n\n const ax = Math.sqrt((px.x - cc.x) ** 2 + (px.y - cc.y) ** 2);\n const az = Math.sqrt((pz.x - cc.x) ** 2 + (pz.y - cc.y) ** 2);\n const angle = Math.atan2(px.y - cc.y, px.x - cc.x);\n\n const normalZ = rotate3D({ x: 0, y: 1, z: 0 }, matrix).z;\n const frontHalf: [number, number] = normalZ > 0 ? [0, Math.PI] : [Math.PI, Math.PI * 2];\n\n contours.push({\n params: { cx: cc.x, cy: cc.y, rx: Math.max(ax, az), ry: Math.min(ax, az), rotation: angle },\n frontHalf,\n });\n }\n\n return contours;\n}\n\nfunction ellipsePointAt(params: EllipseParams, angle: number): Vec2 {\n const cos = Math.cos(params.rotation);\n const sin = Math.sin(params.rotation);\n const px = params.rx * Math.cos(angle);\n const py = params.ry * Math.sin(angle);\n return {\n x: params.cx + px * cos - py * sin,\n y: params.cy + px * sin + py * cos,\n };\n}\n","import type { Vec2, Vec3, Mat3 } from \"../math/rotation.js\";\nimport { rotate3D, project, transformedNormalZ } from \"../math/rotation.js\";\nimport { drawLine, applyHiddenEdgeStyle, resetEdgeStyle, type HiddenEdgeStyle } from \"../shared.js\";\n\nexport interface WedgeRenderOptions {\n center: Vec2;\n scale: number;\n sizeX: number;\n sizeY: number;\n sizeZ: number;\n matrix: Mat3;\n projection: \"orthographic\" | \"weak-perspective\";\n focalLength: number;\n showHidden: boolean;\n hiddenStyle: HiddenEdgeStyle;\n hiddenAlpha: number;\n edgeColor: string;\n}\n\n// Wedge: triangular cross-section in XY, extruded along Z\n// Front triangle: 3 vertices, back triangle: 3 vertices = 6 total\n//\n// 2(top) 5(top-back)\n// / \\ / \\\n// / \\ / \\\n// 0-----1 3-----4\n// front-left-right back-left-right\n\nconst WEDGE_VERTICES: Vec3[] = [\n { x: -0.5, y: -0.5, z: 0.5 }, // 0: front-left-bottom\n { x: 0.5, y: -0.5, z: 0.5 }, // 1: front-right-bottom\n { x: 0, y: 0.5, z: 0.5 }, // 2: front-top\n { x: -0.5, y: -0.5, z: -0.5 }, // 3: back-left-bottom\n { x: 0.5, y: -0.5, z: -0.5 }, // 4: back-right-bottom\n { x: 0, y: 0.5, z: -0.5 }, // 5: back-top\n];\n\n// 5 faces with normals\nconst FACE_NORMALS: Vec3[] = [\n { x: 0, y: 0, z: 1 }, // 0: front (triangle 0,1,2)\n { x: 0, y: 0, z: -1 }, // 1: back (triangle 3,4,5)\n { x: 0, y: -1, z: 0 }, // 2: bottom (quad 0,1,4,3)\n { x: -0.894, y: 0.447, z: 0 }, // 3: left slope (quad 0,2,5,3) normalized(-1, 0.5, 0)\n { x: 0.894, y: 0.447, z: 0 }, // 4: right slope (quad 1,2,5,4) normalized(1, 0.5, 0)\n];\n\ninterface WedgeEdge {\n a: number;\n b: number;\n faces: [number, number];\n}\n\nconst WEDGE_EDGES: WedgeEdge[] = [\n // Front triangle\n { a: 0, b: 1, faces: [0, 2] },\n { a: 1, b: 2, faces: [0, 4] },\n { a: 2, b: 0, faces: [0, 3] },\n // Back triangle\n { a: 3, b: 4, faces: [1, 2] },\n { a: 4, b: 5, faces: [1, 4] },\n { a: 5, b: 3, faces: [1, 3] },\n // Connecting edges\n { a: 0, b: 3, faces: [2, 3] },\n { a: 1, b: 4, faces: [2, 4] },\n { a: 2, b: 5, faces: [3, 4] },\n];\n\nfunction projectVertex(v: Vec3, opts: WedgeRenderOptions): Vec2 {\n const scaled: Vec3 = { x: v.x * opts.sizeX, y: v.y * opts.sizeY, z: v.z * opts.sizeZ };\n const rotated = rotate3D(scaled, opts.matrix);\n const p = project(rotated, opts.projection, opts.focalLength);\n return { x: opts.center.x + p.x * opts.scale, y: opts.center.y - p.y * opts.scale };\n}\n\nexport function renderWedge(ctx: CanvasRenderingContext2D, opts: WedgeRenderOptions): void {\n const { showHidden, hiddenStyle, hiddenAlpha, edgeColor, matrix } = opts;\n\n const projected = WEDGE_VERTICES.map((v) => projectVertex(v, opts));\n const faceVisibility = FACE_NORMALS.map((n) => transformedNormalZ(n, matrix) > 0);\n\n ctx.strokeStyle = edgeColor;\n const savedAlpha = ctx.globalAlpha;\n\n // Draw hidden edges first\n if (showHidden) {\n applyHiddenEdgeStyle(ctx, hiddenStyle, hiddenAlpha);\n for (const edge of WEDGE_EDGES) {\n if (!(faceVisibility[edge.faces[0]]! || faceVisibility[edge.faces[1]]!)) {\n const pa = projected[edge.a]!;\n const pb = projected[edge.b]!;\n drawLine(ctx, pa.x, pa.y, pb.x, pb.y);\n }\n }\n resetEdgeStyle(ctx, savedAlpha);\n }\n\n // Draw front edges\n ctx.setLineDash([]);\n ctx.globalAlpha = savedAlpha;\n for (const edge of WEDGE_EDGES) {\n if (faceVisibility[edge.faces[0]]! || faceVisibility[edge.faces[1]]!) {\n const pa = projected[edge.a]!;\n const pb = projected[edge.b]!;\n drawLine(ctx, pa.x, pa.y, pb.x, pb.y);\n }\n }\n}\n","import type { Vec2, Vec3, Mat3 } from \"../math/rotation.js\";\nimport { rotate3D, project } from \"../math/rotation.js\";\nimport { drawEllipseWithHidden, type EllipseParams } from \"../math/ellipse.js\";\nimport type { HiddenEdgeStyle } from \"../shared.js\";\n\nexport interface EggRenderOptions {\n center: Vec2;\n scale: number;\n sizeX: number;\n sizeY: number;\n sizeZ: number;\n matrix: Mat3;\n projection: \"orthographic\" | \"weak-perspective\";\n focalLength: number;\n showHidden: boolean;\n hiddenStyle: HiddenEdgeStyle;\n hiddenAlpha: number;\n edgeColor: string;\n}\n\nfunction projectVertex(v: Vec3, opts: EggRenderOptions): Vec2 {\n const rotated = rotate3D(v, opts.matrix);\n const p = project(rotated, opts.projection, opts.focalLength);\n return { x: opts.center.x + p.x * opts.scale, y: opts.center.y - p.y * opts.scale };\n}\n\n/**\n * Egg radius at a given height along the Y axis.\n * Wider at bottom (y=-0.5), narrower at top (y=0.5).\n * Uses a cosine profile with asymmetric scaling.\n */\nfunction eggRadius(t: number): number {\n // t in [0,1], 0=bottom, 1=top\n // Bottom half is wider, top half is narrower\n const base = Math.sin(t * Math.PI); // 0 at top and bottom, 1 at middle\n const asymmetry = 1 - t * 0.3; // Wider at bottom\n return base * asymmetry;\n}\n\n/**\n * Render an egg/ovoid outline using a series of projected points.\n */\nexport function renderEgg(ctx: CanvasRenderingContext2D, opts: EggRenderOptions): void {\n const { center, scale, sizeX, sizeY, sizeZ, matrix, projection, focalLength, edgeColor } = opts;\n const segments = 48;\n\n ctx.strokeStyle = edgeColor;\n\n // Generate egg outline by sweeping around the Y axis\n const outlinePoints: Vec2[] = [];\n for (let i = 0; i <= segments; i++) {\n const angle = (i / segments) * Math.PI * 2;\n // For each angle around Y, compute the egg profile at each height\n // We trace the silhouette in 3D then project\n const t = (Math.sin(angle) + 1) / 2; // 0 to 1 for bottom to top\n const y = (t - 0.5) * sizeY;\n const r = eggRadius(t);\n const x = Math.cos(angle) * r * sizeX * 0.5;\n const z = 0; // Silhouette lies in the XY plane initially\n\n const rotated = rotate3D({ x, y, z }, matrix);\n const p = project(rotated, projection, focalLength);\n outlinePoints.push({ x: center.x + p.x * scale, y: center.y - p.y * scale });\n }\n\n // Generate full 3D egg surface points for a proper silhouette\n // Sample the surface and find the outermost points at each screen-Y\n const surfacePoints: Vec2[] = [];\n const ySteps = 32;\n const aSteps = 24;\n\n for (let yi = 0; yi <= ySteps; yi++) {\n const t = yi / ySteps;\n const y = (t - 0.5) * sizeY;\n const r = eggRadius(t);\n\n let leftmost = Infinity;\n let rightmost = -Infinity;\n let leftP: Vec2 = { x: 0, y: 0 };\n let rightP: Vec2 = { x: 0, y: 0 };\n\n for (let ai = 0; ai <= aSteps; ai++) {\n const a = (ai / aSteps) * Math.PI * 2;\n const x3d = Math.cos(a) * r * sizeX * 0.5;\n const z3d = Math.sin(a) * r * sizeZ * 0.5;\n const p3d: Vec3 = { x: x3d, y, z: z3d };\n const rotated = rotate3D(p3d, matrix);\n const p = project(rotated, projection, focalLength);\n const sx = center.x + p.x * scale;\n const sy = center.y - p.y * scale;\n\n if (sx < leftmost) { leftmost = sx; leftP = { x: sx, y: sy }; }\n if (sx > rightmost) { rightmost = sx; rightP = { x: sx, y: sy }; }\n }\n\n surfacePoints.push(leftP, rightP);\n }\n\n // Build left and right silhouette paths\n const leftPath: Vec2[] = [];\n const rightPath: Vec2[] = [];\n for (let i = 0; i < surfacePoints.length; i += 2) {\n leftPath.push(surfacePoints[i]!);\n rightPath.push(surfacePoints[i + 1]!);\n }\n\n // Draw the silhouette as a smooth curve\n ctx.beginPath();\n if (leftPath.length > 1) {\n ctx.moveTo(leftPath[0]!.x, leftPath[0]!.y);\n for (let i = 1; i < leftPath.length; i++) {\n ctx.lineTo(leftPath[i]!.x, leftPath[i]!.y);\n }\n }\n // Continue with right path in reverse\n for (let i = rightPath.length - 1; i >= 0; i--) {\n ctx.lineTo(rightPath[i]!.x, rightPath[i]!.y);\n }\n ctx.closePath();\n ctx.stroke();\n}\n\n/** Cross-contour ellipses for egg — similar to sphere but with varying radius. */\nexport function eggCrossContours(\n opts: EggRenderOptions,\n count: number,\n): { params: EllipseParams; frontHalf: [number, number] }[] {\n const { center, scale, sizeX, sizeY, sizeZ, matrix, projection, focalLength } = opts;\n const contours: { params: EllipseParams; frontHalf: [number, number] }[] = [];\n\n for (let i = 1; i < count; i++) {\n const t = i / count;\n const y = (t - 0.5) * sizeY;\n const r = eggRadius(t);\n const rx = r * sizeX * 0.5;\n const rz = r * sizeZ * 0.5;\n\n if (rx < 0.001 || rz < 0.001) continue;\n\n const cc = projectVertex({ x: 0, y, z: 0 }, opts);\n const px = projectVertex({ x: rx, y, z: 0 }, opts);\n const pz = projectVertex({ x: 0, y, z: rz }, opts);\n\n const ax = Math.sqrt((px.x - cc.x) ** 2 + (px.y - cc.y) ** 2);\n const az = Math.sqrt((pz.x - cc.x) ** 2 + (pz.y - cc.y) ** 2);\n const angle = Math.atan2(px.y - cc.y, px.x - cc.x);\n\n const normalZ = rotate3D({ x: 0, y: 1, z: 0 }, matrix).z;\n const topVisible = normalZ > 0;\n const isAboveCenter = t > 0.5;\n const frontHalf: [number, number] = (isAboveCenter === topVisible)\n ? [0, Math.PI]\n : [Math.PI, Math.PI * 2];\n\n contours.push({\n params: { cx: cc.x, cy: cc.y, rx: Math.max(ax, az), ry: Math.min(ax, az), rotation: angle },\n frontHalf,\n });\n }\n\n return contours;\n}\n","import type {\n LayerTypeDefinition,\n LayerPropertySchema,\n LayerProperties,\n LayerBounds,\n RenderResources,\n ValidationError,\n} from \"@genart-dev/core\";\nimport {\n COMMON_GUIDE_PROPERTIES,\n setupGuideStyle,\n toPixel,\n parseCSVColors,\n drawLine,\n drawDashedLine,\n drawPolyline,\n type HiddenEdgeStyle,\n type FormType,\n} from \"./shared.js\";\nimport { rotationMatrix, rotate3D, project as project3D, type Mat3 } from \"./math/rotation.js\";\nimport { drawEllipseWithHidden } from \"./math/ellipse.js\";\nimport { renderBox, boxCrossContours } from \"./forms/box.js\";\nimport { renderCylinder, cylinderCrossContours } from \"./forms/cylinder.js\";\nimport { renderSphere, sphereCrossContours } from \"./forms/sphere.js\";\nimport { renderCone, coneCrossContours } from \"./forms/cone.js\";\nimport { renderWedge } from \"./forms/wedge.js\";\nimport { renderEgg, eggCrossContours } from \"./forms/egg.js\";\n\nconst FORM_PROPERTIES: LayerPropertySchema[] = [\n {\n key: \"formType\",\n label: \"Form Type\",\n type: \"select\",\n default: \"box\",\n options: [\n { value: \"box\", label: \"Box\" },\n { value: \"cylinder\", label: \"Cylinder\" },\n { value: \"sphere\", label: \"Sphere\" },\n { value: \"cone\", label: \"Cone\" },\n { value: \"wedge\", label: \"Wedge\" },\n { value: \"egg\", label: \"Egg / Ovoid\" },\n ],\n group: \"form\",\n },\n {\n key: \"position\",\n label: \"Position\",\n type: \"point\",\n default: { x: 0.5, y: 0.5 },\n group: \"form\",\n },\n {\n key: \"formSize\",\n label: \"Size\",\n type: \"number\",\n default: 0.25,\n min: 0.05,\n max: 0.6,\n step: 0.01,\n group: \"form\",\n },\n {\n key: \"sizeX\",\n label: \"Width Scale\",\n type: \"number\",\n default: 1.0,\n min: 0.2,\n max: 3.0,\n step: 0.1,\n group: \"form\",\n },\n {\n key: \"sizeY\",\n label: \"Height Scale\",\n type: \"number\",\n default: 1.0,\n min: 0.2,\n max: 3.0,\n step: 0.1,\n group: \"form\",\n },\n {\n key: \"sizeZ\",\n label: \"Depth Scale\",\n type: \"number\",\n default: 1.0,\n min: 0.2,\n max: 3.0,\n step: 0.1,\n group: \"form\",\n },\n {\n key: \"rotationX\",\n label: \"Rotation X\",\n type: \"number\",\n default: 15,\n min: -90,\n max: 90,\n step: 5,\n group: \"rotation\",\n },\n {\n key: \"rotationY\",\n label: \"Rotation Y\",\n type: \"number\",\n default: 30,\n min: -180,\n max: 180,\n step: 5,\n group: \"rotation\",\n },\n {\n key: \"rotationZ\",\n label: \"Rotation Z\",\n type: \"number\",\n default: 0,\n min: -180,\n max: 180,\n step: 5,\n group: \"rotation\",\n },\n {\n key: \"projection\",\n label: \"Projection\",\n type: \"select\",\n default: \"orthographic\",\n options: [\n { value: \"orthographic\", label: \"Orthographic\" },\n { value: \"weak-perspective\", label: \"Weak Perspective\" },\n ],\n group: \"projection\",\n },\n {\n key: \"showCrossContours\",\n label: \"Show Cross-Contours\",\n type: \"boolean\",\n default: true,\n group: \"contours\",\n },\n {\n key: \"crossContourCount\",\n label: \"Cross-Contour Count\",\n type: \"number\",\n default: 5,\n min: 1,\n max: 12,\n step: 1,\n group: \"contours\",\n },\n {\n key: \"showAxes\",\n label: \"Show Axes\",\n type: \"boolean\",\n default: true,\n group: \"display\",\n },\n {\n key: \"axisLength\",\n label: \"Axis Length\",\n type: \"number\",\n default: 1.2,\n min: 0.5,\n max: 2.0,\n step: 0.1,\n group: \"display\",\n },\n {\n key: \"showHiddenEdges\",\n label: \"Show Hidden Edges\",\n type: \"boolean\",\n default: true,\n group: \"display\",\n },\n {\n key: \"hiddenEdgeStyle\",\n label: \"Hidden Edge Style\",\n type: \"select\",\n default: \"dashed\",\n options: [\n { value: \"dashed\", label: \"Dashed\" },\n { value: \"dotted\", label: \"Dotted\" },\n { value: \"faint\", label: \"Faint\" },\n { value: \"hidden\", label: \"Hidden\" },\n ],\n group: \"display\",\n },\n {\n key: \"hiddenEdgeAlpha\",\n label: \"Hidden Edge Alpha\",\n type: \"number\",\n default: 0.3,\n min: 0,\n max: 0.8,\n step: 0.05,\n group: \"display\",\n },\n {\n key: \"edgeColor\",\n label: \"Edge Color\",\n type: \"color\",\n default: \"rgba(0,200,255,0.7)\",\n group: \"style\",\n },\n {\n key: \"contourColor\",\n label: \"Contour Color\",\n type: \"color\",\n default: \"rgba(100,255,100,0.5)\",\n group: \"style\",\n },\n {\n key: \"axisColors\",\n label: \"Axis Colors (X,Y,Z)\",\n type: \"string\",\n default: \"red,green,blue\",\n group: \"style\",\n },\n ...COMMON_GUIDE_PROPERTIES,\n];\n\nexport const formLayerType: LayerTypeDefinition = {\n typeId: \"construction:form\",\n displayName: \"Construction Form\",\n icon: \"cube\",\n category: \"guide\",\n properties: FORM_PROPERTIES,\n propertyEditorId: \"construction:form-editor\",\n\n createDefault(): LayerProperties {\n const props: LayerProperties = {};\n for (const schema of FORM_PROPERTIES) {\n props[schema.key] = schema.default;\n }\n return props;\n },\n\n render(\n properties: LayerProperties,\n ctx: CanvasRenderingContext2D,\n bounds: LayerBounds,\n ): void {\n const formType = (properties.formType as FormType) ?? \"box\";\n const pos = properties.position as { x: number; y: number } | undefined;\n const center = toPixel(pos ?? { x: 0.5, y: 0.5 }, bounds);\n const formSize = (properties.formSize as number) ?? 0.25;\n const sizeX = (properties.sizeX as number) ?? 1.0;\n const sizeY = (properties.sizeY as number) ?? 1.0;\n const sizeZ = (properties.sizeZ as number) ?? 1.0;\n const rxDeg = (properties.rotationX as number) ?? 15;\n const ryDeg = (properties.rotationY as number) ?? 30;\n const rzDeg = (properties.rotationZ as number) ?? 0;\n const proj = (properties.projection as \"orthographic\" | \"weak-perspective\") ?? \"orthographic\";\n const showContours = (properties.showCrossContours as boolean) ?? true;\n const contourCount = (properties.crossContourCount as number) ?? 5;\n const showAxes = (properties.showAxes as boolean) ?? true;\n const axisLen = (properties.axisLength as number) ?? 1.2;\n const showHidden = (properties.showHiddenEdges as boolean) ?? true;\n const hiddenStyle = (properties.hiddenEdgeStyle as HiddenEdgeStyle) ?? \"dashed\";\n const hiddenAlpha = (properties.hiddenEdgeAlpha as number) ?? 0.3;\n const edgeColor = (properties.edgeColor as string) ?? \"rgba(0,200,255,0.7)\";\n const contourColor = (properties.contourColor as string) ?? \"rgba(100,255,100,0.5)\";\n const axisColorsCSV = (properties.axisColors as string) ?? \"red,green,blue\";\n\n const scale = Math.min(bounds.width, bounds.height) * formSize;\n const matrix = rotationMatrix(rxDeg, ryDeg, rzDeg);\n const focalLength = 5;\n\n ctx.save();\n\n const baseOpts = {\n center,\n scale,\n sizeX,\n sizeY,\n sizeZ,\n matrix,\n projection: proj,\n focalLength,\n showHidden,\n hiddenStyle,\n hiddenAlpha,\n edgeColor,\n };\n\n // Render the form\n switch (formType) {\n case \"box\":\n renderBox(ctx, baseOpts);\n break;\n case \"cylinder\":\n renderCylinder(ctx, baseOpts);\n break;\n case \"sphere\":\n renderSphere(ctx, { ...baseOpts, radius: 0.5 });\n break;\n case \"cone\":\n renderCone(ctx, baseOpts);\n break;\n case \"wedge\":\n renderWedge(ctx, baseOpts);\n break;\n case \"egg\":\n renderEgg(ctx, baseOpts);\n break;\n }\n\n // Draw cross-contours\n if (showContours) {\n ctx.strokeStyle = contourColor;\n ctx.lineWidth = 0.75;\n const hiddenDash = hiddenStyle === \"dotted\" ? [2, 3] : [6, 4];\n\n switch (formType) {\n case \"box\": {\n const contours = boxCrossContours(baseOpts, contourCount);\n for (const line of contours.front) {\n drawPolyline(ctx, line);\n }\n if (showHidden) {\n ctx.globalAlpha = hiddenAlpha;\n ctx.setLineDash(hiddenDash);\n for (const line of contours.hidden) {\n drawPolyline(ctx, line);\n }\n ctx.globalAlpha = 1;\n ctx.setLineDash([]);\n }\n break;\n }\n case \"cylinder\": {\n const contours = cylinderCrossContours(baseOpts, contourCount + 1);\n for (const c of contours) {\n drawEllipseWithHidden(ctx, c.params, c.frontHalf, hiddenAlpha, hiddenDash);\n }\n break;\n }\n case \"sphere\": {\n const latCount = Math.ceil(contourCount / 2);\n const lonCount = Math.floor(contourCount / 2);\n const contours = sphereCrossContours({ ...baseOpts, radius: 0.5 }, latCount + 1, lonCount);\n for (const c of contours) {\n drawEllipseWithHidden(ctx, c.params, c.frontHalf, hiddenAlpha, hiddenDash);\n }\n break;\n }\n case \"cone\": {\n const contours = coneCrossContours(baseOpts, contourCount + 1);\n for (const c of contours) {\n drawEllipseWithHidden(ctx, c.params, c.frontHalf, hiddenAlpha, hiddenDash);\n }\n break;\n }\n case \"egg\": {\n const contours = eggCrossContours(baseOpts, contourCount + 1);\n for (const c of contours) {\n drawEllipseWithHidden(ctx, c.params, c.frontHalf, hiddenAlpha, hiddenDash);\n }\n break;\n }\n // wedge: no elliptical contours (uses parallel lines like box)\n }\n }\n\n // Draw axes\n if (showAxes) {\n const axisColors = parseCSVColors(axisColorsCSV, 3);\n const axisScale = scale * axisLen;\n\n const axes = [\n { dir: { x: 1, y: 0, z: 0 } as const, color: axisColors[0]! },\n { dir: { x: 0, y: 1, z: 0 } as const, color: axisColors[1]! },\n { dir: { x: 0, y: 0, z: 1 } as const, color: axisColors[2]! },\n ];\n\n for (const axis of axes) {\n const rotated = rotate3D(axis.dir, matrix);\n const p = project3D(rotated, proj, focalLength);\n const endX = center.x + p.x * axisScale;\n const endY = center.y - p.y * axisScale;\n\n ctx.strokeStyle = axis.color;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([]);\n drawLine(ctx, center.x, center.y, endX, endY);\n }\n }\n\n ctx.restore();\n },\n\n validate(properties: LayerProperties): ValidationError[] | null {\n const errors: ValidationError[] = [];\n const formType = properties.formType as string;\n if (![\"box\", \"cylinder\", \"sphere\", \"cone\", \"wedge\", \"egg\"].includes(formType)) {\n errors.push({ property: \"formType\", message: \"Invalid form type\" });\n }\n const rx = properties.rotationX;\n if (typeof rx === \"number\" && (rx < -90 || rx > 90)) {\n errors.push({ property: \"rotationX\", message: \"Must be -90 to 90\" });\n }\n return errors.length > 0 ? errors : null;\n },\n};\n","import type {\n LayerTypeDefinition,\n LayerPropertySchema,\n LayerProperties,\n LayerBounds,\n RenderResources,\n ValidationError,\n} from \"@genart-dev/core\";\nimport {\n COMMON_GUIDE_PROPERTIES,\n setupGuideStyle,\n drawPolyline,\n parseJSON,\n} from \"./shared.js\";\nimport type { Vec2 } from \"./math/rotation.js\";\nimport { dist2, lerp2 } from \"./math/rotation.js\";\n\nconst CROSS_CONTOUR_PROPERTIES: LayerPropertySchema[] = [\n { key: \"outline\", label: \"Outline Points (JSON)\", type: \"string\", default: \"[]\", group: \"shape\" },\n { key: \"axis\", label: \"Axis Points (JSON)\", type: \"string\", default: \"[]\", group: \"shape\" },\n { key: \"contourCount\", label: \"Contour Count\", type: \"number\", default: 8, min: 2, max: 20, step: 1, group: \"contours\" },\n { key: \"curvature\", label: \"Curvature\", type: \"number\", default: 0.5, min: 0, max: 1, step: 0.05, group: \"contours\" },\n { key: \"curvatureVariation\", label: \"Curvature Variation (JSON)\", type: \"string\", default: \"[]\", group: \"contours\" },\n {\n key: \"contourStyle\", label: \"Contour Style\", type: \"select\", default: \"elliptical\",\n options: [\n { value: \"elliptical\", label: \"Elliptical\" },\n { value: \"angular\", label: \"Angular\" },\n { value: \"organic\", label: \"Organic\" },\n ],\n group: \"contours\",\n },\n { key: \"showAxis\", label: \"Show Axis\", type: \"boolean\", default: true, group: \"display\" },\n { key: \"showOutline\", label: \"Show Outline\", type: \"boolean\", default: true, group: \"display\" },\n {\n key: \"wrapDirection\", label: \"Wrap Direction\", type: \"select\", default: \"perpendicular\",\n options: [{ value: \"perpendicular\", label: \"Perpendicular\" }, { value: \"custom\", label: \"Custom\" }],\n group: \"contours\",\n },\n {\n key: \"contourSpacing\", label: \"Contour Spacing\", type: \"select\", default: \"even\",\n options: [{ value: \"even\", label: \"Even\" }, { value: \"perspective\", label: \"Perspective\" }],\n group: \"contours\",\n },\n ...COMMON_GUIDE_PROPERTIES,\n];\n\nexport const crossContourLayerType: LayerTypeDefinition = {\n typeId: \"construction:cross-contour\",\n displayName: \"Cross-Contour Lines\",\n icon: \"waves\",\n category: \"guide\",\n properties: CROSS_CONTOUR_PROPERTIES,\n propertyEditorId: \"construction:cross-contour-editor\",\n\n createDefault(): LayerProperties {\n const props: LayerProperties = {};\n for (const schema of CROSS_CONTOUR_PROPERTIES) {\n props[schema.key] = schema.default;\n }\n return props;\n },\n\n render(\n properties: LayerProperties,\n ctx: CanvasRenderingContext2D,\n bounds: LayerBounds,\n ): void {\n const outlineNorm = parseJSON<Vec2[]>((properties.outline as string) ?? \"[]\", []);\n const axisNorm = parseJSON<Vec2[]>((properties.axis as string) ?? \"[]\", []);\n if (axisNorm.length < 2) return;\n\n const contourCount = (properties.contourCount as number) ?? 8;\n const curvature = (properties.curvature as number) ?? 0.5;\n const curvatureVar = parseJSON<number[]>((properties.curvatureVariation as string) ?? \"[]\", []);\n const contourStyle = (properties.contourStyle as string) ?? \"elliptical\";\n const showAxis = (properties.showAxis as boolean) ?? true;\n const showOutline = (properties.showOutline as boolean) ?? true;\n const spacing = (properties.contourSpacing as string) ?? \"even\";\n const color = (properties.guideColor as string) ?? \"rgba(0,200,255,0.5)\";\n const lineWidth = (properties.lineWidth as number) ?? 1;\n\n const toPixelPt = (p: Vec2): Vec2 => ({\n x: bounds.x + p.x * bounds.width,\n y: bounds.y + p.y * bounds.height,\n });\n\n const outline = outlineNorm.map(toPixelPt);\n const axis = axisNorm.map(toPixelPt);\n\n ctx.save();\n\n if (showOutline && outline.length >= 2) {\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth * 0.7;\n ctx.globalAlpha = 0.5;\n ctx.setLineDash([4, 3]);\n drawPolyline(ctx, outline, true);\n ctx.globalAlpha = 1;\n }\n\n if (showAxis && axis.length >= 2) {\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth * 0.5;\n ctx.setLineDash([3, 5]);\n ctx.globalAlpha = 0.4;\n drawPolyline(ctx, axis);\n ctx.globalAlpha = 1;\n }\n\n const axisPoints = interpolatePolyline(axis, 200);\n\n setupGuideStyle(ctx, color, lineWidth, \"\");\n ctx.setLineDash([]);\n\n for (let i = 0; i < contourCount; i++) {\n let t: number;\n if (spacing === \"perspective\") {\n const raw = (i + 1) / (contourCount + 1);\n t = 0.5 + (raw - 0.5) * Math.sqrt(Math.abs(raw - 0.5) * 2) * Math.sign(raw - 0.5);\n } else {\n t = (i + 1) / (contourCount + 1);\n }\n\n const axisIdx = Math.floor(t * (axisPoints.length - 1));\n const axisPoint = axisPoints[Math.min(axisIdx, axisPoints.length - 1)]!;\n\n const prevIdx = Math.max(0, axisIdx - 1);\n const nextIdx = Math.min(axisPoints.length - 1, axisIdx + 1);\n const tangent = {\n x: axisPoints[nextIdx]!.x - axisPoints[prevIdx]!.x,\n y: axisPoints[nextIdx]!.y - axisPoints[prevIdx]!.y,\n };\n const tangentLen = Math.sqrt(tangent.x ** 2 + tangent.y ** 2);\n if (tangentLen < 0.001) continue;\n\n const perpX = -tangent.y / tangentLen;\n const perpY = tangent.x / tangentLen;\n\n const leftEdge = findOutlineIntersection(axisPoint, { x: perpX, y: perpY }, outline);\n const rightEdge = findOutlineIntersection(axisPoint, { x: -perpX, y: -perpY }, outline);\n if (!leftEdge || !rightEdge) continue;\n\n const curv = curvatureVar[i] ?? curvature;\n const contourLine = generateContourLine(leftEdge, rightEdge, axisPoint, curv, contourStyle);\n drawPolyline(ctx, contourLine);\n }\n\n ctx.restore();\n },\n\n validate(properties: LayerProperties): ValidationError[] | null {\n const errors: ValidationError[] = [];\n const count = properties.contourCount;\n if (typeof count === \"number\" && (count < 2 || count > 20)) {\n errors.push({ property: \"contourCount\", message: \"Must be 2-20\" });\n }\n return errors.length > 0 ? errors : null;\n },\n};\n\nfunction polylineLength(points: Vec2[]): number {\n let len = 0;\n for (let i = 1; i < points.length; i++) len += dist2(points[i - 1]!, points[i]!);\n return len;\n}\n\nfunction interpolatePolyline(points: Vec2[], targetCount: number): Vec2[] {\n if (points.length < 2) return points;\n const totalLen = polylineLength(points);\n if (totalLen < 0.001) return points;\n\n const result: Vec2[] = [];\n const step = totalLen / (targetCount - 1);\n let segIdx = 0;\n let segStart = 0;\n\n for (let i = 0; i < targetCount; i++) {\n const target = i * step;\n while (segIdx < points.length - 2) {\n const segLen = dist2(points[segIdx]!, points[segIdx + 1]!);\n if (segStart + segLen >= target) break;\n segStart += segLen;\n segIdx++;\n }\n const segLen = dist2(points[segIdx]!, points[segIdx + 1]!);\n const t = segLen > 0 ? (target - segStart) / segLen : 0;\n result.push(lerp2(points[segIdx]!, points[segIdx + 1]!, Math.min(1, Math.max(0, t))));\n }\n return result;\n}\n\nfunction findOutlineIntersection(origin: Vec2, direction: Vec2, outline: Vec2[]): Vec2 | null {\n let bestT = Infinity;\n let bestPoint: Vec2 | null = null;\n\n for (let i = 0; i < outline.length; i++) {\n const a = outline[i]!;\n const b = outline[(i + 1) % outline.length]!;\n const dx = b.x - a.x, dy = b.y - a.y;\n const denom = direction.x * dy - direction.y * dx;\n if (Math.abs(denom) < 1e-10) continue;\n\n const t = ((a.x - origin.x) * dy - (a.y - origin.y) * dx) / denom;\n const u = ((a.x - origin.x) * direction.y - (a.y - origin.y) * direction.x) / denom;\n\n if (t > 0 && u >= 0 && u <= 1 && t < bestT) {\n bestT = t;\n bestPoint = { x: origin.x + direction.x * t, y: origin.y + direction.y * t };\n }\n }\n return bestPoint;\n}\n\nfunction generateContourLine(\n left: Vec2, right: Vec2, axisPoint: Vec2, curvature: number, style: string,\n): Vec2[] {\n const segments = 20;\n const points: Vec2[] = [];\n const lrDx = right.x - left.x, lrDy = right.y - left.y;\n const lrLen = Math.sqrt(lrDx * lrDx + lrDy * lrDy);\n\n if (lrLen < 0.001) return [left, right];\n\n const perpX = -lrDy / lrLen, perpY = lrDx / lrLen;\n const toAxisX = axisPoint.x - (left.x + right.x) / 2;\n const toAxisY = axisPoint.y - (left.y + right.y) / 2;\n const sign = (perpX * toAxisX + perpY * toAxisY) > 0 ? 1 : -1;\n\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n const baseX = left.x + (right.x - left.x) * t;\n const baseY = left.y + (right.y - left.y) * t;\n\n let offset: number;\n if (style === \"angular\") {\n offset = curvature * (1 - Math.abs(t - 0.5) * 2) * lrLen * 0.3 * sign;\n } else {\n offset = curvature * Math.sin(t * Math.PI) * lrLen * 0.3 * sign;\n }\n points.push({ x: baseX + perpX * offset, y: baseY + perpY * offset });\n }\n return points;\n}\n","import type { Vec2, Vec3, Mat3 } from \"./rotation.js\";\nimport { normalize3, dot3, rotate3D, project } from \"./rotation.js\";\nimport type { EllipseParams } from \"./ellipse.js\";\nimport type { FormType } from \"../shared.js\";\n\nconst DEG2RAD = Math.PI / 180;\n\n// ---------------------------------------------------------------------------\n// Light source\n// ---------------------------------------------------------------------------\n\nexport interface LightSource {\n azimuth: number; // 0-360 degrees (0=right, 90=bottom, 180=left, 270=top)\n elevation: number; // 10-80 degrees above horizon\n intensity: number; // 0-1\n}\n\n/**\n * Compute a 3D light direction vector from azimuth and elevation.\n * Returns a unit vector pointing FROM the light TOWARD the scene.\n */\nexport function lightDirection(light: LightSource): Vec3 {\n const az = light.azimuth * DEG2RAD;\n const el = light.elevation * DEG2RAD;\n const cosEl = Math.cos(el);\n return normalize3({\n x: -Math.cos(az) * cosEl,\n y: -Math.sin(el),\n z: -Math.sin(az) * cosEl,\n });\n}\n\n/**\n * Compute the light direction as a 2D vector for rendering indicators.\n * Points from center toward where light is coming from.\n */\nexport function lightDirection2D(light: LightSource): Vec2 {\n const az = light.azimuth * DEG2RAD;\n return { x: Math.cos(az), y: Math.sin(az) };\n}\n\n// ---------------------------------------------------------------------------\n// Sphere terminator\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the terminator ellipse on a sphere.\n * The terminator is a great circle perpendicular to the light direction.\n */\nexport function sphereTerminator(\n center: Vec2,\n radius: number,\n light: LightSource,\n matrix: Mat3,\n): { terminatorEllipse: EllipseParams; lightSide: Vec2 } {\n const ld = lightDirection(light);\n\n // The terminator plane normal is the light direction\n // In screen space, project the light direction\n const rotatedLD = rotate3D(ld, matrix);\n const ldScreen = { x: rotatedLD.x, y: -rotatedLD.y }; // flip Y for screen\n\n // The terminator ellipse has its major axis perpendicular to the projected light direction\n const perpAngle = Math.atan2(ldScreen.y, ldScreen.x) + Math.PI / 2;\n\n // Minor axis = radius * |sin(angle between light and view direction)|\n // Since we view along Z, the angle is acos(|rotatedLD.z|)\n const viewAngle = Math.acos(Math.min(1, Math.abs(rotatedLD.z)));\n const minorRadius = radius * Math.sin(viewAngle);\n\n return {\n terminatorEllipse: {\n cx: center.x,\n cy: center.y,\n rx: radius,\n ry: minorRadius,\n rotation: perpAngle,\n },\n lightSide: { x: -ldScreen.x, y: -ldScreen.y },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Cast shadow\n// ---------------------------------------------------------------------------\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Compute a simple cast shadow polygon on the ground plane.\n * Projects the form's bottom silhouette along the light direction.\n */\nexport function castShadow(\n center: Vec2,\n radius: number,\n light: LightSource,\n groundY: number,\n): Vec2[] {\n const ld = lightDirection(light);\n const ld2d = lightDirection2D(light);\n\n // Shadow extends from the base of the form along the ground\n const shadowLength = radius * (1 / Math.tan(light.elevation * DEG2RAD));\n const shadowDirX = -ld2d.x;\n const shadowDirY = 0; // shadow lies on ground\n\n // Approximate as an ellipse stretched along shadow direction\n const points: Vec2[] = [];\n const segments = 24;\n for (let i = 0; i <= segments; i++) {\n const angle = (i / segments) * Math.PI * 2;\n const bx = Math.cos(angle) * radius;\n const by = Math.sin(angle) * radius * 0.3; // flatten\n\n // Offset along shadow direction\n const sx = center.x + bx + shadowDirX * shadowLength * 0.5;\n const sy = groundY + by;\n points.push({ x: sx, y: sy });\n }\n return points;\n}\n\n// ---------------------------------------------------------------------------\n// Value zones\n// ---------------------------------------------------------------------------\n\nexport type ValueGrouping = \"two-value\" | \"three-value\" | \"five-value\";\n\nexport interface ValueZone {\n type: \"highlight\" | \"light\" | \"halftone\" | \"core-shadow\" | \"reflected-light\" | \"cast-shadow\" | \"occlusion-shadow\";\n path: Vec2[];\n value: number; // 0 (darkest) to 1 (lightest)\n label: string;\n}\n\n/**\n * Compute value zones for a sphere at a given position.\n * Returns an array of zones with polygon paths and values.\n */\nexport function sphereValueZones(\n center: Vec2,\n radius: number,\n light: LightSource,\n matrix: Mat3,\n grouping: ValueGrouping,\n): ValueZone[] {\n const zones: ValueZone[] = [];\n const ld = lightDirection(light);\n const rotatedLD = rotate3D(ld, matrix);\n const ldScreen = { x: -rotatedLD.x, y: rotatedLD.y }; // direction light comes FROM\n\n // Generate semicircular paths for light/shadow division\n const terminatorAngle = Math.atan2(ldScreen.y, ldScreen.x);\n const segments = 32;\n\n if (grouping === \"two-value\") {\n // Light side\n zones.push({\n type: \"light\",\n path: generateArcPath(center, radius, terminatorAngle - Math.PI / 2, terminatorAngle + Math.PI / 2, segments),\n value: 0.8,\n label: \"Light\",\n });\n // Shadow side\n zones.push({\n type: \"core-shadow\",\n path: generateArcPath(center, radius, terminatorAngle + Math.PI / 2, terminatorAngle + Math.PI * 1.5, segments),\n value: 0.2,\n label: \"Shadow\",\n });\n } else if (grouping === \"three-value\") {\n // Light\n zones.push({\n type: \"light\",\n path: generateArcPath(center, radius, terminatorAngle - Math.PI / 2, terminatorAngle, segments),\n value: 0.85,\n label: \"Light\",\n });\n // Halftone\n zones.push({\n type: \"halftone\",\n path: generateArcPath(center, radius, terminatorAngle, terminatorAngle + Math.PI / 3, segments),\n value: 0.5,\n label: \"Halftone\",\n });\n // Shadow\n zones.push({\n type: \"core-shadow\",\n path: generateArcPath(center, radius, terminatorAngle + Math.PI / 3, terminatorAngle + Math.PI * 1.5, segments),\n value: 0.15,\n label: \"Shadow\",\n });\n } else {\n // Five-value\n const lightEnd = terminatorAngle - Math.PI / 6;\n const highlightEnd = terminatorAngle - Math.PI / 3;\n\n zones.push({\n type: \"highlight\",\n path: generateArcPath(center, radius, terminatorAngle - Math.PI / 2, highlightEnd, segments),\n value: 0.95,\n label: \"Highlight\",\n });\n zones.push({\n type: \"light\",\n path: generateArcPath(center, radius, highlightEnd, lightEnd, segments),\n value: 0.8,\n label: \"Light\",\n });\n zones.push({\n type: \"halftone\",\n path: generateArcPath(center, radius, lightEnd, terminatorAngle + Math.PI / 6, segments),\n value: 0.5,\n label: \"Halftone\",\n });\n zones.push({\n type: \"core-shadow\",\n path: generateArcPath(center, radius, terminatorAngle + Math.PI / 6, terminatorAngle + Math.PI * 0.6, segments),\n value: 0.1,\n label: \"Core Shadow\",\n });\n zones.push({\n type: \"reflected-light\",\n path: generateArcPath(center, radius, terminatorAngle + Math.PI * 0.6, terminatorAngle + Math.PI * 1.5, segments),\n value: 0.3,\n label: \"Reflected Light\",\n });\n }\n\n return zones;\n}\n\nfunction generateArcPath(\n center: Vec2,\n radius: number,\n startAngle: number,\n endAngle: number,\n segments: number,\n): Vec2[] {\n const points: Vec2[] = [{ x: center.x, y: center.y }];\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n const angle = startAngle + (endAngle - startAngle) * t;\n points.push({\n x: center.x + Math.cos(angle) * radius,\n y: center.y + Math.sin(angle) * radius,\n });\n }\n return points;\n}\n","import type {\n LayerTypeDefinition,\n LayerPropertySchema,\n LayerProperties,\n LayerBounds,\n RenderResources,\n ValidationError,\n} from \"@genart-dev/core\";\nimport {\n COMMON_GUIDE_PROPERTIES,\n toPixel,\n drawLine,\n drawLabel,\n fillPolyline,\n parseJSON,\n type FormDefinition,\n} from \"./shared.js\";\nimport { rotationMatrix } from \"./math/rotation.js\";\nimport {\n sphereTerminator,\n castShadow,\n sphereValueZones,\n lightDirection2D,\n type LightSource,\n type ValueGrouping,\n} from \"./math/shadow.js\";\nimport { drawEllipse } from \"./math/ellipse.js\";\n\nconst VALUE_SHAPES_PROPERTIES: LayerPropertySchema[] = [\n {\n key: \"formData\",\n label: \"Forms (JSON)\",\n type: \"string\",\n default: \"[]\",\n group: \"forms\",\n },\n {\n key: \"lightAzimuth\",\n label: \"Light Azimuth\",\n type: \"number\",\n default: 315,\n min: 0,\n max: 360,\n step: 15,\n group: \"light\",\n },\n {\n key: \"lightElevation\",\n label: \"Light Elevation\",\n type: \"number\",\n default: 45,\n min: 10,\n max: 80,\n step: 5,\n group: \"light\",\n },\n {\n key: \"lightIntensity\",\n label: \"Light Intensity\",\n type: \"number\",\n default: 0.8,\n min: 0.1,\n max: 1.0,\n step: 0.05,\n group: \"light\",\n },\n {\n key: \"showLightIndicator\",\n label: \"Show Light Indicator\",\n type: \"boolean\",\n default: true,\n group: \"display\",\n },\n {\n key: \"valueGrouping\",\n label: \"Value Grouping\",\n type: \"select\",\n default: \"three-value\",\n options: [\n { value: \"two-value\", label: \"2-Value (Light/Shadow)\" },\n { value: \"three-value\", label: \"3-Value (Light/Half/Shadow)\" },\n { value: \"five-value\", label: \"5-Value (Full Anatomy)\" },\n ],\n group: \"display\",\n },\n {\n key: \"shadowColor\",\n label: \"Shadow Color\",\n type: \"color\",\n default: \"rgba(0,0,0,0.3)\",\n group: \"style\",\n },\n {\n key: \"lightColor\",\n label: \"Light Color\",\n type: \"color\",\n default: \"rgba(255,255,200,0.15)\",\n group: \"style\",\n },\n {\n key: \"halftoneColor\",\n label: \"Halftone Color\",\n type: \"color\",\n default: \"rgba(0,0,0,0.12)\",\n group: \"style\",\n },\n {\n key: \"highlightColor\",\n label: \"Highlight Color\",\n type: \"color\",\n default: \"rgba(255,255,255,0.25)\",\n group: \"style\",\n },\n {\n key: \"reflectedLightColor\",\n label: \"Reflected Light Color\",\n type: \"color\",\n default: \"rgba(100,100,120,0.15)\",\n group: \"style\",\n },\n {\n key: \"showTerminator\",\n label: \"Show Terminator\",\n type: \"boolean\",\n default: true,\n group: \"display\",\n },\n {\n key: \"terminatorWidth\",\n label: \"Terminator Width\",\n type: \"number\",\n default: 2,\n min: 1,\n max: 5,\n step: 0.5,\n group: \"display\",\n },\n {\n key: \"showCastShadow\",\n label: \"Show Cast Shadow\",\n type: \"boolean\",\n default: true,\n group: \"display\",\n },\n {\n key: \"showOcclusionShadow\",\n label: \"Show Occlusion Shadow\",\n type: \"boolean\",\n default: true,\n group: \"display\",\n },\n {\n key: \"showZoneLabels\",\n label: \"Show Zone Labels\",\n type: \"boolean\",\n default: false,\n group: \"display\",\n },\n {\n key: \"groundPlaneY\",\n label: \"Ground Plane Y\",\n type: \"number\",\n default: 0.8,\n min: 0,\n max: 1,\n step: 0.05,\n group: \"light\",\n },\n ...COMMON_GUIDE_PROPERTIES,\n];\n\nexport const valueShapesLayerType: LayerTypeDefinition = {\n typeId: \"construction:value-shapes\",\n displayName: \"Value Shapes Study\",\n icon: \"sun\",\n category: \"guide\",\n properties: VALUE_SHAPES_PROPERTIES,\n propertyEditorId: \"construction:value-shapes-editor\",\n\n createDefault(): LayerProperties {\n const props: LayerProperties = {};\n for (const schema of VALUE_SHAPES_PROPERTIES) {\n props[schema.key] = schema.default;\n }\n return props;\n },\n\n render(\n properties: LayerProperties,\n ctx: CanvasRenderingContext2D,\n bounds: LayerBounds,\n ): void {\n const formDataJSON = (properties.formData as string) ?? \"[]\";\n const forms = parseJSON<FormDefinition[]>(formDataJSON, []);\n\n const lightAzimuth = (properties.lightAzimuth as number) ?? 315;\n const lightElevation = (properties.lightElevation as number) ?? 45;\n const lightIntensity = (properties.lightIntensity as number) ?? 0.8;\n const showIndicator = (properties.showLightIndicator as boolean) ?? true;\n const grouping = (properties.valueGrouping as ValueGrouping) ?? \"three-value\";\n const shadowColor = (properties.shadowColor as string) ?? \"rgba(0,0,0,0.3)\";\n const lightColor = (properties.lightColor as string) ?? \"rgba(255,255,200,0.15)\";\n const halftoneColor = (properties.halftoneColor as string) ?? \"rgba(0,0,0,0.12)\";\n const highlightColor = (properties.highlightColor as string) ?? \"rgba(255,255,255,0.25)\";\n const reflectedLightColor = (properties.reflectedLightColor as string) ?? \"rgba(100,100,120,0.15)\";\n const showTerminator = (properties.showTerminator as boolean) ?? true;\n const terminatorWidth = (properties.terminatorWidth as number) ?? 2;\n const showCastShadow = (properties.showCastShadow as boolean) ?? true;\n const showOcclusion = (properties.showOcclusionShadow as boolean) ?? true;\n const showLabels = (properties.showZoneLabels as boolean) ?? false;\n const groundPlaneY = (properties.groundPlaneY as number) ?? 0.8;\n\n const light: LightSource = {\n azimuth: lightAzimuth,\n elevation: lightElevation,\n intensity: lightIntensity,\n };\n\n ctx.save();\n\n // If no forms provided, use a default sphere\n const effectiveForms = forms.length > 0\n ? forms\n : [{ type: \"sphere\" as const, position: { x: 0, y: 0, z: 0 }, size: { x: 1, y: 1, z: 1 }, rotation: { x: 0, y: 0, z: 0 } }];\n\n for (const form of effectiveForms) {\n const centerNorm = {\n x: 0.5 + form.position.x * 0.3,\n y: 0.5 - form.position.y * 0.3,\n };\n const center = toPixel(centerNorm, bounds);\n const radius = Math.min(bounds.width, bounds.height) * 0.15 * form.size.x;\n const matrix = rotationMatrix(form.rotation.x, form.rotation.y, form.rotation.z);\n const groundPx = bounds.y + groundPlaneY * bounds.height;\n\n // Compute and render value zones\n const zones = sphereValueZones(center, radius, light, matrix, grouping);\n const colorMap: Record<string, string> = {\n \"highlight\": highlightColor,\n \"light\": lightColor,\n \"halftone\": halftoneColor,\n \"core-shadow\": shadowColor,\n \"reflected-light\": reflectedLightColor,\n \"cast-shadow\": shadowColor,\n \"occlusion-shadow\": shadowColor,\n };\n\n for (const zone of zones) {\n fillPolyline(ctx, zone.path, colorMap[zone.type] ?? shadowColor);\n }\n\n // Draw terminator\n if (showTerminator) {\n const term = sphereTerminator(center, radius, light, matrix);\n ctx.strokeStyle = \"rgba(255,100,0,0.6)\";\n ctx.lineWidth = terminatorWidth;\n ctx.setLineDash([]);\n drawEllipse(\n ctx,\n term.terminatorEllipse.cx,\n term.terminatorEllipse.cy,\n term.terminatorEllipse.rx,\n term.terminatorEllipse.ry,\n term.terminatorEllipse.rotation,\n );\n }\n\n // Cast shadow\n if (showCastShadow) {\n const shadow = castShadow(center, radius, light, groundPx);\n fillPolyline(ctx, shadow, \"rgba(0,0,0,0.15)\");\n }\n\n // Occlusion shadow (small dark arc at base)\n if (showOcclusion) {\n const occRadius = radius * 0.15;\n ctx.beginPath();\n ctx.ellipse(center.x, center.y + radius, occRadius * 3, occRadius, 0, 0, Math.PI * 2);\n ctx.fillStyle = \"rgba(0,0,0,0.25)\";\n ctx.fill();\n }\n\n // Zone labels\n if (showLabels) {\n for (const zone of zones) {\n if (zone.path.length > 2) {\n // Label at centroid of zone\n let cx = 0, cy = 0;\n for (const p of zone.path) { cx += p.x; cy += p.y; }\n cx /= zone.path.length;\n cy /= zone.path.length;\n drawLabel(ctx, zone.label, cx, cy, \"rgba(255,255,255,0.8)\", 9);\n }\n }\n }\n\n // Sphere outline\n ctx.strokeStyle = \"rgba(0,200,255,0.5)\";\n ctx.lineWidth = 1;\n ctx.setLineDash([6, 4]);\n ctx.beginPath();\n ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);\n ctx.stroke();\n }\n\n // Light direction indicator\n if (showIndicator) {\n const ld2d = lightDirection2D(light);\n const indX = bounds.x + bounds.width - 30;\n const indY = bounds.y + 30;\n const indLen = 15;\n\n ctx.strokeStyle = \"rgba(255,220,50,0.8)\";\n ctx.lineWidth = 2;\n ctx.setLineDash([]);\n drawLine(ctx, indX, indY, indX + ld2d.x * indLen, indY + ld2d.y * indLen);\n\n // Sun circle\n ctx.beginPath();\n ctx.arc(indX, indY, 6, 0, Math.PI * 2);\n ctx.fillStyle = \"rgba(255,220,50,0.6)\";\n ctx.fill();\n ctx.stroke();\n }\n\n ctx.restore();\n },\n\n validate(properties: LayerProperties): ValidationError[] | null {\n const errors: ValidationError[] = [];\n const el = properties.lightElevation;\n if (typeof el === \"number\" && (el < 10 || el > 80)) {\n errors.push({ property: \"lightElevation\", message: \"Must be 10-80\" });\n }\n return errors.length > 0 ? errors : null;\n },\n};\n","import type { Vec2 } from \"./rotation.js\";\nimport { dist2 } from \"./rotation.js\";\n\n/**\n * Compute a convex hull of the given points (Andrew's monotone chain).\n */\nexport function convexHull(points: Vec2[]): Vec2[] {\n if (points.length < 3) return [...points];\n\n const sorted = [...points].sort((a, b) => a.x - b.x || a.y - b.y);\n const lower: Vec2[] = [];\n for (const p of sorted) {\n while (lower.length >= 2 && cross(lower[lower.length - 2]!, lower[lower.length - 1]!, p) <= 0) {\n lower.pop();\n }\n lower.push(p);\n }\n\n const upper: Vec2[] = [];\n for (let i = sorted.length - 1; i >= 0; i--) {\n const p = sorted[i]!;\n while (upper.length >= 2 && cross(upper[upper.length - 2]!, upper[upper.length - 1]!, p) <= 0) {\n upper.pop();\n }\n upper.push(p);\n }\n\n lower.pop();\n upper.pop();\n return lower.concat(upper);\n}\n\nfunction cross(o: Vec2, a: Vec2, b: Vec2): number {\n return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);\n}\n\n/**\n * Compute envelope from points based on style.\n * - \"tight\": convex hull\n * - \"loose\": convex hull expanded outward\n * - \"fitted\": the original polygon (straight lines connecting input points in order)\n */\nexport function computeEnvelope(\n points: Vec2[],\n style: \"tight\" | \"loose\" | \"fitted\",\n): Vec2[] {\n if (points.length < 3) return [...points];\n\n if (style === \"fitted\") return [...points];\n\n const hull = convexHull(points);\n\n if (style === \"loose\") {\n const cx = hull.reduce((s, p) => s + p.x, 0) / hull.length;\n const cy = hull.reduce((s, p) => s + p.y, 0) / hull.length;\n const expand = 0.05;\n return hull.map((p) => ({\n x: p.x + (p.x - cx) * expand,\n y: p.y + (p.y - cy) * expand,\n }));\n }\n\n return hull;\n}\n\n/**\n * Compute angles at each vertex of an envelope polygon.\n * Returns the interior angle in degrees at each vertex.\n */\nexport function envelopeAngles(vertices: Vec2[]): Array<{ vertex: Vec2; angle: number }> {\n const n = vertices.length;\n if (n < 3) return [];\n\n const result: Array<{ vertex: Vec2; angle: number }> = [];\n for (let i = 0; i < n; i++) {\n const prev = vertices[(i - 1 + n) % n]!;\n const curr = vertices[i]!;\n const next = vertices[(i + 1) % n]!;\n\n const dx1 = prev.x - curr.x, dy1 = prev.y - curr.y;\n const dx2 = next.x - curr.x, dy2 = next.y - curr.y;\n\n const dot = dx1 * dx2 + dy1 * dy2;\n const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);\n const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);\n\n if (len1 < 1e-10 || len2 < 1e-10) {\n result.push({ vertex: curr, angle: 180 });\n continue;\n }\n\n const cosAngle = Math.max(-1, Math.min(1, dot / (len1 * len2)));\n const angle = Math.acos(cosAngle) * (180 / Math.PI);\n result.push({ vertex: curr, angle });\n }\n return result;\n}\n\n/** Vertical plumb line through a reference point, clipped to bounds. */\nexport function plumbLine(\n referencePoint: Vec2,\n bounds: { x: number; y: number; width: number; height: number },\n): [Vec2, Vec2] {\n return [\n { x: referencePoint.x, y: bounds.y },\n { x: referencePoint.x, y: bounds.y + bounds.height },\n ];\n}\n\n/** Horizontal level line through a reference point, clipped to bounds. */\nexport function levelLine(\n referencePoint: Vec2,\n bounds: { x: number; y: number; width: number; height: number },\n): [Vec2, Vec2] {\n return [\n { x: bounds.x, y: referencePoint.y },\n { x: bounds.x + bounds.width, y: referencePoint.y },\n ];\n}\n\n/** Comparative measurement between two segments. Returns ratio and label. */\nexport function comparativeMeasure(\n segment1: [Vec2, Vec2],\n segment2: [Vec2, Vec2],\n): { ratio: number; label: string } {\n const len1 = dist2(segment1[0], segment1[1]);\n const len2 = dist2(segment2[0], segment2[1]);\n if (len2 < 1e-10) return { ratio: Infinity, label: \"∞\" };\n const ratio = len1 / len2;\n return { ratio, label: `1 : ${ratio.toFixed(2)}` };\n}\n","import type {\n LayerTypeDefinition,\n LayerPropertySchema,\n LayerProperties,\n LayerBounds,\n RenderResources,\n ValidationError,\n} from \"@genart-dev/core\";\nimport {\n COMMON_GUIDE_PROPERTIES,\n drawLine,\n drawDashedLine,\n drawPolyline,\n drawLabel,\n parseJSON,\n} from \"./shared.js\";\nimport type { Vec2 } from \"./math/rotation.js\";\nimport { dist2 } from \"./math/rotation.js\";\nimport {\n computeEnvelope,\n envelopeAngles,\n plumbLine,\n levelLine,\n comparativeMeasure,\n} from \"./math/envelope.js\";\n\nconst ENVELOPE_PROPERTIES: LayerPropertySchema[] = [\n { key: \"envelopePath\", label: \"Envelope Points (JSON)\", type: \"string\", default: \"[]\", group: \"envelope\" },\n {\n key: \"envelopeStyle\", label: \"Envelope Style\", type: \"select\", default: \"tight\",\n options: [\n { value: \"tight\", label: \"Tight (Convex Hull)\" },\n { value: \"loose\", label: \"Loose (Expanded)\" },\n { value: \"fitted\", label: \"Fitted (As Given)\" },\n ],\n group: \"envelope\",\n },\n { key: \"showAngles\", label: \"Show Angles\", type: \"boolean\", default: true, group: \"display\" },\n { key: \"angleThreshold\", label: \"Angle Threshold\", type: \"number\", default: 10, min: 5, max: 45, step: 5, group: \"display\" },\n { key: \"showPlumbLine\", label: \"Show Plumb Line\", type: \"boolean\", default: true, group: \"display\" },\n { key: \"plumbLinePoint\", label: \"Plumb Line Point\", type: \"point\", default: { x: 0.5, y: 0 }, group: \"display\" },\n { key: \"showLevelLines\", label: \"Show Level Lines\", type: \"boolean\", default: false, group: \"display\" },\n { key: \"levelLinePoints\", label: \"Level Line Y Positions (JSON)\", type: \"string\", default: \"[]\", group: \"display\" },\n { key: \"showMeasurements\", label: \"Show Measurements\", type: \"boolean\", default: false, group: \"display\" },\n { key: \"measurementPairs\", label: \"Measurement Pairs (JSON)\", type: \"string\", default: \"[]\", group: \"display\" },\n { key: \"showSubdivisions\", label: \"Show Subdivisions\", type: \"boolean\", default: false, group: \"display\" },\n { key: \"subdivisionDepth\", label: \"Subdivision Depth\", type: \"number\", default: 1, min: 0, max: 3, step: 1, group: \"display\" },\n { key: \"envelopeColor\", label: \"Envelope Color\", type: \"color\", default: \"rgba(255,200,0,0.6)\", group: \"style\" },\n { key: \"plumbColor\", label: \"Plumb Color\", type: \"color\", default: \"rgba(0,255,0,0.4)\", group: \"style\" },\n { key: \"measureColor\", label: \"Measure Color\", type: \"color\", default: \"rgba(255,100,100,0.5)\", group: \"style\" },\n ...COMMON_GUIDE_PROPERTIES,\n];\n\nexport const envelopeLayerType: LayerTypeDefinition = {\n typeId: \"construction:envelope\",\n displayName: \"Envelope Block-In\",\n icon: \"pentagon\",\n category: \"guide\",\n properties: ENVELOPE_PROPERTIES,\n propertyEditorId: \"construction:envelope-editor\",\n\n createDefault(): LayerProperties {\n const props: LayerProperties = {};\n for (const schema of ENVELOPE_PROPERTIES) {\n props[schema.key] = schema.default;\n }\n return props;\n },\n\n render(\n properties: LayerProperties,\n ctx: CanvasRenderingContext2D,\n bounds: LayerBounds,\n ): void {\n const pathNorm = parseJSON<Vec2[]>((properties.envelopePath as string) ?? \"[]\", []);\n if (pathNorm.length < 3) return;\n\n const style = (properties.envelopeStyle as \"tight\" | \"loose\" | \"fitted\") ?? \"tight\";\n const showAngles = (properties.showAngles as boolean) ?? true;\n const angleThreshold = (properties.angleThreshold as number) ?? 10;\n const showPlumb = (properties.showPlumbLine as boolean) ?? true;\n const plumbPt = properties.plumbLinePoint as { x: number; y: number } | undefined;\n const showLevel = (properties.showLevelLines as boolean) ?? false;\n const levelPts = parseJSON<{ y: number }[]>((properties.levelLinePoints as string) ?? \"[]\", []);\n const showMeasure = (properties.showMeasurements as boolean) ?? false;\n const measurePairs = parseJSON<{ from: Vec2; to: Vec2 }[]>((properties.measurementPairs as string) ?? \"[]\", []);\n const showSub = (properties.showSubdivisions as boolean) ?? false;\n const subDepth = (properties.subdivisionDepth as number) ?? 1;\n const envColor = (properties.envelopeColor as string) ?? \"rgba(255,200,0,0.6)\";\n const plumbColor = (properties.plumbColor as string) ?? \"rgba(0,255,0,0.4)\";\n const measureColor = (properties.measureColor as string) ?? \"rgba(255,100,100,0.5)\";\n const lineWidth = (properties.lineWidth as number) ?? 1;\n\n const toPixelPt = (p: Vec2): Vec2 => ({\n x: bounds.x + p.x * bounds.width,\n y: bounds.y + p.y * bounds.height,\n });\n\n const pixelPath = pathNorm.map(toPixelPt);\n const envelope = computeEnvelope(pixelPath, style);\n\n ctx.save();\n\n // Draw envelope\n ctx.strokeStyle = envColor;\n ctx.lineWidth = lineWidth * 1.5;\n ctx.setLineDash([]);\n drawPolyline(ctx, envelope, true);\n\n // Angle annotations\n if (showAngles) {\n const angles = envelopeAngles(envelope);\n for (const { vertex, angle } of angles) {\n if (Math.abs(angle - 180) > angleThreshold) {\n drawLabel(ctx, `${Math.round(angle)}°`, vertex.x + 12, vertex.y - 12, envColor, 9);\n // Small arc indicator\n ctx.beginPath();\n ctx.arc(vertex.x, vertex.y, 8, 0, Math.PI * 2);\n ctx.strokeStyle = envColor;\n ctx.lineWidth = 0.5;\n ctx.stroke();\n }\n }\n }\n\n // Plumb line\n if (showPlumb) {\n const plumbPixel = toPixelPt(plumbPt ?? { x: 0.5, y: 0 });\n const [p1, p2] = plumbLine(plumbPixel, bounds);\n ctx.strokeStyle = plumbColor;\n ctx.lineWidth = 0.75;\n drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, [8, 6]);\n }\n\n // Level lines\n if (showLevel) {\n ctx.strokeStyle = plumbColor;\n ctx.lineWidth = 0.75;\n for (const lp of levelPts) {\n const py = bounds.y + lp.y * bounds.height;\n drawDashedLine(ctx, bounds.x, py, bounds.x + bounds.width, py, [8, 6]);\n }\n }\n\n // Measurement pairs\n if (showMeasure) {\n ctx.strokeStyle = measureColor;\n ctx.lineWidth = 1;\n for (const pair of measurePairs) {\n const from = toPixelPt(pair.from);\n const to = toPixelPt(pair.to);\n drawLine(ctx, from.x, from.y, to.x, to.y);\n const len = dist2(from, to);\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n drawLabel(ctx, `${Math.round(len)}px`, midX, midY - 8, measureColor, 8);\n }\n }\n\n // Subdivisions\n if (showSub && subDepth > 0) {\n ctx.strokeStyle = envColor;\n ctx.globalAlpha = 0.3;\n ctx.lineWidth = 0.5;\n drawSubdivisions(ctx, envelope, subDepth);\n ctx.globalAlpha = 1;\n }\n\n ctx.restore();\n },\n\n validate(properties: LayerProperties): ValidationError[] | null {\n return null;\n },\n};\n\nfunction drawSubdivisions(ctx: CanvasRenderingContext2D, vertices: Vec2[], depth: number): void {\n if (depth <= 0 || vertices.length < 3) return;\n\n // Midpoints of each edge\n const midpoints: Vec2[] = [];\n for (let i = 0; i < vertices.length; i++) {\n const a = vertices[i]!;\n const b = vertices[(i + 1) % vertices.length]!;\n midpoints.push({ x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });\n }\n\n // Draw lines connecting midpoints\n ctx.setLineDash([3, 4]);\n for (let i = 0; i < midpoints.length; i++) {\n const a = midpoints[i]!;\n const b = midpoints[(i + 1) % midpoints.length]!;\n drawLine(ctx, a.x, a.y, b.x, b.y);\n }\n\n if (depth > 1) {\n drawSubdivisions(ctx, midpoints, depth - 1);\n }\n}\n","import type { Vec2, Vec3, Mat3 } from \"./rotation.js\";\nimport { rotate3D, project, rotationMatrix, normalize3 } from \"./rotation.js\";\nimport type { FormDefinition } from \"../shared.js\";\n\n/**\n * Approximate form intersection by sampling both surfaces and finding\n * points where they are equidistant from the camera (same Z depth).\n *\n * Returns a projected 2D polyline approximating the intersection curve.\n */\nexport function approximateIntersection(\n form1: FormDefinition,\n form2: FormDefinition,\n samples = 24,\n): Vec2[] {\n const m1 = rotationMatrix(form1.rotation.x, form1.rotation.y, form1.rotation.z);\n const m2 = rotationMatrix(form2.rotation.x, form2.rotation.y, form2.rotation.z);\n\n // Sample surface points of both forms\n const surf1 = sampleFormSurface(form1, m1, samples);\n const surf2 = sampleFormSurface(form2, m2, samples);\n\n // Find pairs of points that are close to each other in 3D space\n const intersectionPoints: Vec3[] = [];\n const threshold = Math.max(\n form1.size.x, form1.size.y, form1.size.z,\n form2.size.x, form2.size.y, form2.size.z,\n ) * 0.15;\n\n for (const p1 of surf1) {\n for (const p2 of surf2) {\n const dx = p1.x - p2.x;\n const dy = p1.y - p2.y;\n const dz = p1.z - p2.z;\n const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);\n if (dist < threshold) {\n // Midpoint between the two surface points\n intersectionPoints.push({\n x: (p1.x + p2.x) / 2,\n y: (p1.y + p2.y) / 2,\n z: (p1.z + p2.z) / 2,\n });\n }\n }\n }\n\n if (intersectionPoints.length < 2) return [];\n\n // Project to 2D and order the points to form a curve\n const projected = intersectionPoints.map((p) => project(p, \"orthographic\"));\n return orderPointsIntoCurve(projected);\n}\n\n/**\n * Sample the surface of a form in world space.\n */\nfunction sampleFormSurface(form: FormDefinition, matrix: Mat3, samples: number): Vec3[] {\n const points: Vec3[] = [];\n const { x: sx, y: sy, z: sz } = form.size;\n const { x: px, y: py, z: pz } = form.position;\n\n switch (form.type) {\n case \"sphere\": {\n for (let i = 0; i < samples; i++) {\n for (let j = 0; j < samples; j++) {\n const theta = (i / samples) * Math.PI;\n const phi = (j / samples) * Math.PI * 2;\n const local: Vec3 = {\n x: sx * 0.5 * Math.sin(theta) * Math.cos(phi),\n y: sy * 0.5 * Math.cos(theta),\n z: sz * 0.5 * Math.sin(theta) * Math.sin(phi),\n };\n const rotated = rotate3D(local, matrix);\n points.push({ x: rotated.x + px, y: rotated.y + py, z: rotated.z + pz });\n }\n }\n break;\n }\n case \"box\": {\n const half = { x: sx / 2, y: sy / 2, z: sz / 2 };\n // Sample each face\n for (let i = 0; i < samples; i++) {\n for (let j = 0; j < samples; j++) {\n const u = (i / (samples - 1)) * 2 - 1;\n const v = (j / (samples - 1)) * 2 - 1;\n // 6 faces\n const faces: Vec3[] = [\n { x: u * half.x, y: v * half.y, z: half.z },\n { x: u * half.x, y: v * half.y, z: -half.z },\n { x: half.x, y: u * half.y, z: v * half.z },\n { x: -half.x, y: u * half.y, z: v * half.z },\n { x: u * half.x, y: half.y, z: v * half.z },\n { x: u * half.x, y: -half.y, z: v * half.z },\n ];\n for (const local of faces) {\n const rotated = rotate3D(local, matrix);\n points.push({ x: rotated.x + px, y: rotated.y + py, z: rotated.z + pz });\n }\n }\n }\n break;\n }\n case \"cylinder\": {\n for (let i = 0; i < samples; i++) {\n const angle = (i / samples) * Math.PI * 2;\n for (let j = 0; j < samples; j++) {\n const t = (j / (samples - 1)) * 2 - 1;\n const local: Vec3 = {\n x: sx * 0.5 * Math.cos(angle),\n y: sy * 0.5 * t,\n z: sz * 0.5 * Math.sin(angle),\n };\n const rotated = rotate3D(local, matrix);\n points.push({ x: rotated.x + px, y: rotated.y + py, z: rotated.z + pz });\n }\n }\n break;\n }\n case \"cone\": {\n for (let i = 0; i < samples; i++) {\n const angle = (i / samples) * Math.PI * 2;\n for (let j = 0; j < samples; j++) {\n const t = j / (samples - 1); // 0=base, 1=apex\n const radius = 1 - t;\n const local: Vec3 = {\n x: sx * 0.5 * radius * Math.cos(angle),\n y: sy * (t - 0.5),\n z: sz * 0.5 * radius * Math.sin(angle),\n };\n const rotated = rotate3D(local, matrix);\n points.push({ x: rotated.x + px, y: rotated.y + py, z: rotated.z + pz });\n }\n }\n break;\n }\n default: {\n // Fallback: sample as sphere\n for (let i = 0; i < samples; i++) {\n const theta = (i / samples) * Math.PI;\n for (let j = 0; j < samples; j++) {\n const phi = (j / samples) * Math.PI * 2;\n const local: Vec3 = {\n x: sx * 0.5 * Math.sin(theta) * Math.cos(phi),\n y: sy * 0.5 * Math.cos(theta),\n z: sz * 0.5 * Math.sin(theta) * Math.sin(phi),\n };\n const rotated = rotate3D(local, matrix);\n points.push({ x: rotated.x + px, y: rotated.y + py, z: rotated.z + pz });\n }\n }\n }\n }\n\n return points;\n}\n\n/**\n * Order scattered 2D points into a curve by nearest-neighbor traversal.\n */\nfunction orderPointsIntoCurve(points: Vec2[]): Vec2[] {\n if (points.length < 2) return points;\n\n const used = new Set<number>();\n const result: Vec2[] = [];\n\n // Start from the leftmost point\n let currentIdx = 0;\n for (let i = 1; i < points.length; i++) {\n if (points[i]!.x < points[currentIdx]!.x) currentIdx = i;\n }\n\n result.push(points[currentIdx]!);\n used.add(currentIdx);\n\n while (used.size < points.length) {\n let bestIdx = -1;\n let bestDist = Infinity;\n\n for (let i = 0; i < points.length; i++) {\n if (used.has(i)) continue;\n const dx = points[i]!.x - points[currentIdx]!.x;\n const dy = points[i]!.y - points[currentIdx]!.y;\n const d = dx * dx + dy * dy;\n if (d < bestDist) {\n bestDist = d;\n bestIdx = i;\n }\n }\n\n if (bestIdx === -1) break;\n result.push(points[bestIdx]!);\n used.add(bestIdx);\n currentIdx = bestIdx;\n }\n\n return result;\n}\n","import type {\n LayerTypeDefinition,\n LayerPropertySchema,\n LayerProperties,\n LayerBounds,\n RenderResources,\n ValidationError,\n} from \"@genart-dev/core\";\nimport {\n COMMON_GUIDE_PROPERTIES,\n drawPolyline,\n drawLabel,\n parseJSON,\n toPixel,\n type FormDefinition,\n type FormType,\n} from \"./shared.js\";\nimport { rotationMatrix, rotate3D, project as project3D } from \"./math/rotation.js\";\nimport { renderBox } from \"./forms/box.js\";\nimport { renderCylinder } from \"./forms/cylinder.js\";\nimport { renderSphere } from \"./forms/sphere.js\";\nimport { renderCone } from \"./forms/cone.js\";\nimport { renderWedge } from \"./forms/wedge.js\";\nimport { renderEgg } from \"./forms/egg.js\";\nimport { approximateIntersection } from \"./math/intersection.js\";\n\nconst INTERSECTION_PROPERTIES: LayerPropertySchema[] = [\n { key: \"forms\", label: \"Forms (JSON)\", type: \"string\", default: \"[]\", group: \"forms\" },\n { key: \"showForms\", label: \"Show Forms\", type: \"boolean\", default: true, group: \"display\" },\n { key: \"showIntersectionLines\", label: \"Show Intersection Lines\", type: \"boolean\", default: true, group: \"display\" },\n { key: \"intersectionWidth\", label: \"Intersection Width\", type: \"number\", default: 2.5, min: 1, max: 6, step: 0.5, group: \"style\" },\n { key: \"intersectionColor\", label: \"Intersection Color\", type: \"color\", default: \"rgba(255,50,50,0.8)\", group: \"style\" },\n {\n key: \"intersectionStyle\", label: \"Intersection Style\", type: \"select\", default: \"solid\",\n options: [\n { value: \"solid\", label: \"Solid\" },\n { value: \"bold\", label: \"Bold\" },\n { value: \"emphasized\", label: \"Emphasized\" },\n ],\n group: \"style\",\n },\n { key: \"showFormLabels\", label: \"Show Form Labels\", type: \"boolean\", default: false, group: \"display\" },\n {\n key: \"transitionType\", label: \"Transition Type\", type: \"select\", default: \"hard\",\n options: [\n { value: \"hard\", label: \"Hard\" },\n { value: \"soft\", label: \"Soft\" },\n { value: \"mixed\", label: \"Mixed\" },\n ],\n group: \"display\",\n },\n ...COMMON_GUIDE_PROPERTIES,\n];\n\nexport const intersectionLayerType: LayerTypeDefinition = {\n typeId: \"construction:intersection\",\n displayName: \"Form Intersection\",\n icon: \"intersect\",\n category: \"guide\",\n properties: INTERSECTION_PROPERTIES,\n propertyEditorId: \"construction:intersection-editor\",\n\n createDefault(): LayerProperties {\n const props: LayerProperties = {};\n for (const schema of INTERSECTION_PROPERTIES) {\n props[schema.key] = schema.default;\n }\n return props;\n },\n\n render(\n properties: LayerProperties,\n ctx: CanvasRenderingContext2D,\n bounds: LayerBounds,\n ): void {\n const forms = parseJSON<FormDefinition[]>((properties.forms as string) ?? \"[]\", []);\n if (forms.length < 2) return;\n\n const showForms = (properties.showForms as boolean) ?? true;\n const showIntersections = (properties.showIntersectionLines as boolean) ?? true;\n const intWidth = (properties.intersectionWidth as number) ?? 2.5;\n const intColor = (properties.intersectionColor as string) ?? \"rgba(255,50,50,0.8)\";\n const intStyle = (properties.intersectionStyle as string) ?? \"solid\";\n const showLabels = (properties.showFormLabels as boolean) ?? false;\n const transition = (properties.transitionType as string) ?? \"hard\";\n const guideColor = (properties.guideColor as string) ?? \"rgba(0,200,255,0.5)\";\n const lineWidth = (properties.lineWidth as number) ?? 1;\n\n const scale = Math.min(bounds.width, bounds.height) * 0.15;\n\n ctx.save();\n\n // Render each form\n if (showForms) {\n for (let fi = 0; fi < forms.length; fi++) {\n const form = forms[fi]!;\n const centerNorm = {\n x: 0.5 + form.position.x * 0.3,\n y: 0.5 - form.position.y * 0.3,\n };\n const center = toPixel(centerNorm, bounds);\n const matrix = rotationMatrix(form.rotation.x, form.rotation.y, form.rotation.z);\n\n const baseOpts = {\n center,\n scale,\n sizeX: form.size.x,\n sizeY: form.size.y,\n sizeZ: form.size.z,\n matrix,\n projection: \"orthographic\" as const,\n focalLength: 5,\n showHidden: true,\n hiddenStyle: \"dashed\" as const,\n hiddenAlpha: 0.2,\n edgeColor: guideColor,\n };\n\n switch (form.type) {\n case \"box\": renderBox(ctx, baseOpts); break;\n case \"cylinder\": renderCylinder(ctx, baseOpts); break;\n case \"sphere\": renderSphere(ctx, { ...baseOpts, radius: 0.5 }); break;\n case \"cone\": renderCone(ctx, baseOpts); break;\n case \"wedge\": renderWedge(ctx, baseOpts); break;\n case \"egg\": renderEgg(ctx, baseOpts); break;\n }\n\n if (showLabels) {\n const label = String.fromCharCode(65 + fi); // A, B, C...\n drawLabel(ctx, label, center.x, center.y - scale * 0.6, guideColor, 12);\n }\n }\n }\n\n // Compute and render intersection lines between all pairs\n if (showIntersections) {\n ctx.strokeStyle = intColor;\n ctx.lineWidth = intStyle === \"bold\" ? intWidth * 1.5 : intWidth;\n ctx.setLineDash(intStyle === \"emphasized\" ? [2, 0] : []);\n\n for (let i = 0; i < forms.length - 1; i++) {\n for (let j = i + 1; j < forms.length; j++) {\n const curve = approximateIntersection(forms[i]!, forms[j]!, 16);\n if (curve.length < 2) continue;\n\n // Convert from form-local space to screen space\n const screenCurve = curve.map((p) => ({\n x: bounds.x + bounds.width / 2 + p.x * scale,\n y: bounds.y + bounds.height / 2 - p.y * scale,\n }));\n\n if (transition === \"soft\") {\n // Wider, semi-transparent for soft transitions\n ctx.lineWidth = intWidth * 2;\n ctx.globalAlpha = 0.4;\n drawPolyline(ctx, screenCurve);\n ctx.globalAlpha = 1;\n ctx.lineWidth = intWidth;\n }\n\n drawPolyline(ctx, screenCurve);\n }\n }\n }\n\n ctx.restore();\n },\n\n validate(properties: LayerProperties): ValidationError[] | null {\n return null;\n },\n};\n","import type {\n McpToolDefinition,\n McpToolContext,\n McpToolResult,\n JsonSchema,\n DesignLayer,\n LayerTransform,\n LayerProperties,\n} from \"@genart-dev/core\";\nimport { formLayerType } from \"./form-layer.js\";\nimport { crossContourLayerType } from \"./cross-contour-layer.js\";\nimport { valueShapesLayerType } from \"./value-shapes-layer.js\";\nimport { envelopeLayerType } from \"./envelope-layer.js\";\nimport { intersectionLayerType } from \"./intersection-layer.js\";\nimport type { FormType } from \"./shared.js\";\n\nfunction textResult(text: string): McpToolResult {\n return { content: [{ type: \"text\", text }] };\n}\n\nfunction errorResult(text: string): McpToolResult {\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\nfunction generateLayerId(): string {\n return `layer-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction fullCanvasTransform(ctx: McpToolContext): LayerTransform {\n return {\n x: 0, y: 0,\n width: ctx.canvasWidth, height: ctx.canvasHeight,\n rotation: 0, scaleX: 1, scaleY: 1, anchorX: 0, anchorY: 0,\n };\n}\n\nfunction addLayer(context: McpToolContext, layer: DesignLayer): void {\n context.layers.add(layer);\n context.emitChange(\"layer-added\");\n}\n\nconst VALID_FORMS: FormType[] = [\"box\", \"cylinder\", \"sphere\", \"cone\", \"wedge\", \"egg\"];\n\n// ---------------------------------------------------------------------------\n// add_construction_form\n// ---------------------------------------------------------------------------\n\nconst addConstructionFormTool: McpToolDefinition = {\n name: \"add_construction_form\",\n description: \"Add a 3D construction form guide layer. Form types: box, cylinder, sphere, cone, wedge, egg.\",\n inputSchema: {\n type: \"object\",\n properties: {\n formType: {\n type: \"string\",\n enum: VALID_FORMS,\n description: \"The form primitive type.\",\n },\n position: {\n type: \"object\",\n properties: { x: { type: \"number\" }, y: { type: \"number\" } },\n description: \"Normalized position (0-1). Default: {x:0.5, y:0.5}.\",\n },\n size: { type: \"number\", description: \"Overall form size (0.05-0.6). Default: 0.25.\" },\n sizeX: { type: \"number\", description: \"Width scale (0.2-3.0). Default: 1.0.\" },\n sizeY: { type: \"number\", description: \"Height scale (0.2-3.0). Default: 1.0.\" },\n sizeZ: { type: \"number\", description: \"Depth scale (0.2-3.0). Default: 1.0.\" },\n rotationX: { type: \"number\", description: \"X rotation (-90 to 90). Default: 15.\" },\n rotationY: { type: \"number\", description: \"Y rotation (-180 to 180). Default: 30.\" },\n rotationZ: { type: \"number\", description: \"Z rotation (-180 to 180). Default: 0.\" },\n crossContours: { type: \"boolean\", description: \"Show cross-contour lines. Default: true.\" },\n projection: {\n type: \"string\",\n enum: [\"orthographic\", \"weak-perspective\"],\n description: \"Projection type. Default: orthographic.\",\n },\n },\n required: [\"formType\"],\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const formType = input.formType as string;\n if (!VALID_FORMS.includes(formType as FormType)) {\n return errorResult(`Invalid form type '${formType}'. Use: ${VALID_FORMS.join(\", \")}`);\n }\n\n const defaults = formLayerType.createDefault();\n const properties: LayerProperties = { ...defaults, formType };\n\n if (input.position) properties.position = input.position as { x: number; y: number };\n if (input.size !== undefined) properties.formSize = input.size as number;\n if (input.sizeX !== undefined) properties.sizeX = input.sizeX as number;\n if (input.sizeY !== undefined) properties.sizeY = input.sizeY as number;\n if (input.sizeZ !== undefined) properties.sizeZ = input.sizeZ as number;\n if (input.rotationX !== undefined) properties.rotationX = input.rotationX as number;\n if (input.rotationY !== undefined) properties.rotationY = input.rotationY as number;\n if (input.rotationZ !== undefined) properties.rotationZ = input.rotationZ as number;\n if (input.crossContours !== undefined) properties.showCrossContours = input.crossContours as boolean;\n if (input.projection !== undefined) properties.projection = input.projection as string;\n\n const id = generateLayerId();\n addLayer(context, {\n id, type: \"construction:form\", name: `Construction Form (${formType})`,\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n return textResult(`Added ${formType} construction form '${id}'.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// add_construction_scene\n// ---------------------------------------------------------------------------\n\nconst addConstructionSceneTool: McpToolDefinition = {\n name: \"add_construction_scene\",\n description: \"Add multiple 3D construction forms arranged as a scene.\",\n inputSchema: {\n type: \"object\",\n properties: {\n forms: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n type: { type: \"string\", enum: VALID_FORMS },\n position: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" } } },\n size: { type: \"number\" },\n rotation: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" }, z: { type: \"number\" } } },\n },\n required: [\"type\"],\n },\n description: \"Array of form definitions.\",\n },\n showAxes: { type: \"boolean\", description: \"Show axes on all forms. Default: true.\" },\n },\n required: [\"forms\"],\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const formsInput = input.forms as Array<Record<string, unknown>>;\n if (!Array.isArray(formsInput) || formsInput.length === 0) {\n return errorResult(\"'forms' must be a non-empty array.\");\n }\n\n const showAxes = (input.showAxes as boolean) ?? true;\n const ids: string[] = [];\n\n for (const f of formsInput) {\n const formType = f.type as string;\n if (!VALID_FORMS.includes(formType as FormType)) continue;\n\n const defaults = formLayerType.createDefault();\n const properties: LayerProperties = { ...defaults, formType, showAxes };\n\n const pos = f.position as { x: number; y: number } | undefined;\n if (pos) properties.position = pos;\n if (f.size !== undefined) properties.formSize = f.size as number;\n const rot = f.rotation as { x: number; y: number; z: number } | undefined;\n if (rot) {\n properties.rotationX = rot.x ?? 15;\n properties.rotationY = rot.y ?? 30;\n properties.rotationZ = rot.z ?? 0;\n }\n\n const id = generateLayerId();\n ids.push(id);\n addLayer(context, {\n id, type: \"construction:form\", name: `Construction Form (${formType})`,\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n }\n\n return textResult(`Added ${ids.length} construction form(s): ${ids.join(\", \")}.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// add_cross_contours\n// ---------------------------------------------------------------------------\n\nconst addCrossContoursTool: McpToolDefinition = {\n name: \"add_cross_contours\",\n description: \"Add cross-contour lines over an outline + axis path, revealing surface direction on any organic shape.\",\n inputSchema: {\n type: \"object\",\n properties: {\n outline: { type: \"array\", items: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" } } }, description: \"Outline points (normalized 0-1).\" },\n axis: { type: \"array\", items: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" } } }, description: \"Central axis path (normalized 0-1).\" },\n curvature: { type: \"number\", description: \"Curvature 0-1 (0=flat, 0.5=cylindrical, 1=spherical). Default: 0.5.\" },\n count: { type: \"number\", description: \"Number of contour lines (2-20). Default: 8.\" },\n style: { type: \"string\", enum: [\"elliptical\", \"angular\", \"organic\"], description: \"Contour style. Default: elliptical.\" },\n curvatureVariation: { type: \"array\", items: { type: \"number\" }, description: \"Per-contour curvature overrides.\" },\n },\n required: [\"outline\", \"axis\"],\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const outline = input.outline as Array<{ x: number; y: number }>;\n const axis = input.axis as Array<{ x: number; y: number }>;\n if (!Array.isArray(outline) || !Array.isArray(axis) || axis.length < 2) {\n return errorResult(\"'outline' and 'axis' (min 2 points) are required.\");\n }\n\n const defaults = crossContourLayerType.createDefault();\n const properties: LayerProperties = {\n ...defaults,\n outline: JSON.stringify(outline),\n axis: JSON.stringify(axis),\n };\n\n if (input.curvature !== undefined) properties.curvature = input.curvature as number;\n if (input.count !== undefined) properties.contourCount = input.count as number;\n if (input.style !== undefined) properties.contourStyle = input.style as string;\n if (input.curvatureVariation !== undefined) {\n properties.curvatureVariation = JSON.stringify(input.curvatureVariation);\n }\n\n const id = generateLayerId();\n addLayer(context, {\n id, type: \"construction:cross-contour\", name: \"Cross-Contour Lines\",\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n return textResult(`Added cross-contour layer '${id}'.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// add_value_study\n// ---------------------------------------------------------------------------\n\nconst addValueStudyTool: McpToolDefinition = {\n name: \"add_value_study\",\n description: \"Add a light/shadow value study overlay with terminator, cast shadow, and value zones.\",\n inputSchema: {\n type: \"object\",\n properties: {\n lightAzimuth: { type: \"number\", description: \"Light azimuth 0-360 (0=right, 90=bottom). Default: 315.\" },\n lightElevation: { type: \"number\", description: \"Light elevation 10-80 degrees. Default: 45.\" },\n forms: { type: \"array\", description: \"Optional array of FormDefinition objects.\" },\n valueGrouping: { type: \"string\", enum: [\"two-value\", \"three-value\", \"five-value\"], description: \"Value grouping. Default: three-value.\" },\n showTerminator: { type: \"boolean\", description: \"Show terminator line. Default: true.\" },\n },\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const defaults = valueShapesLayerType.createDefault();\n const properties: LayerProperties = { ...defaults };\n\n if (input.lightAzimuth !== undefined) properties.lightAzimuth = input.lightAzimuth as number;\n if (input.lightElevation !== undefined) properties.lightElevation = input.lightElevation as number;\n if (input.forms !== undefined) properties.formData = JSON.stringify(input.forms);\n if (input.valueGrouping !== undefined) properties.valueGrouping = input.valueGrouping as string;\n if (input.showTerminator !== undefined) properties.showTerminator = input.showTerminator as boolean;\n\n const id = generateLayerId();\n addLayer(context, {\n id, type: \"construction:value-shapes\", name: \"Value Study\",\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n return textResult(`Added value study layer '${id}'.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// add_envelope\n// ---------------------------------------------------------------------------\n\nconst addEnvelopeTool: McpToolDefinition = {\n name: \"add_envelope\",\n description: \"Add a straight-line envelope block-in with angle and measurement annotations.\",\n inputSchema: {\n type: \"object\",\n properties: {\n points: { type: \"array\", items: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" } } }, description: \"Envelope vertex points (normalized 0-1).\" },\n style: { type: \"string\", enum: [\"tight\", \"loose\", \"fitted\"], description: \"Envelope style. Default: tight.\" },\n showAngles: { type: \"boolean\", description: \"Show angle annotations. Default: true.\" },\n showPlumbLine: { type: \"boolean\", description: \"Show vertical plumb line. Default: true.\" },\n showMeasurements: { type: \"boolean\", description: \"Show comparative measurements. Default: false.\" },\n },\n required: [\"points\"],\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const points = input.points as Array<{ x: number; y: number }>;\n if (!Array.isArray(points) || points.length < 3) {\n return errorResult(\"'points' must have at least 3 vertices.\");\n }\n\n const defaults = envelopeLayerType.createDefault();\n const properties: LayerProperties = { ...defaults, envelopePath: JSON.stringify(points) };\n\n if (input.style !== undefined) properties.envelopeStyle = input.style as string;\n if (input.showAngles !== undefined) properties.showAngles = input.showAngles as boolean;\n if (input.showPlumbLine !== undefined) properties.showPlumbLine = input.showPlumbLine as boolean;\n if (input.showMeasurements !== undefined) properties.showMeasurements = input.showMeasurements as boolean;\n\n const id = generateLayerId();\n addLayer(context, {\n id, type: \"construction:envelope\", name: \"Envelope Block-In\",\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n return textResult(`Added envelope layer '${id}'.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// add_form_intersection\n// ---------------------------------------------------------------------------\n\nconst addFormIntersectionTool: McpToolDefinition = {\n name: \"add_form_intersection\",\n description: \"Add intersection lines between two or more overlapping 3D forms.\",\n inputSchema: {\n type: \"object\",\n properties: {\n forms: {\n type: \"array\", minItems: 2,\n items: {\n type: \"object\",\n properties: {\n type: { type: \"string\", enum: VALID_FORMS },\n position: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" }, z: { type: \"number\" } } },\n size: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" }, z: { type: \"number\" } } },\n rotation: { type: \"object\", properties: { x: { type: \"number\" }, y: { type: \"number\" }, z: { type: \"number\" } } },\n },\n required: [\"type\"],\n },\n description: \"Array of form definitions (at least 2).\",\n },\n transitionType: { type: \"string\", enum: [\"hard\", \"soft\", \"mixed\"], description: \"Intersection transition type. Default: hard.\" },\n showForms: { type: \"boolean\", description: \"Render the forms alongside intersection lines. Default: true.\" },\n },\n required: [\"forms\"],\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const forms = input.forms as Array<Record<string, unknown>>;\n if (!Array.isArray(forms) || forms.length < 2) {\n return errorResult(\"'forms' must have at least 2 entries.\");\n }\n\n // Normalize form definitions with defaults\n const normalizedForms = forms.map((f) => ({\n type: (f.type as string) || \"box\",\n position: (f.position as { x: number; y: number; z: number }) ?? { x: 0, y: 0, z: 0 },\n size: (f.size as { x: number; y: number; z: number }) ?? { x: 1, y: 1, z: 1 },\n rotation: (f.rotation as { x: number; y: number; z: number }) ?? { x: 0, y: 0, z: 0 },\n }));\n\n const defaults = intersectionLayerType.createDefault();\n const properties: LayerProperties = { ...defaults, forms: JSON.stringify(normalizedForms) };\n\n if (input.transitionType !== undefined) properties.transitionType = input.transitionType as string;\n if (input.showForms !== undefined) properties.showForms = input.showForms as boolean;\n\n const id = generateLayerId();\n addLayer(context, {\n id, type: \"construction:intersection\", name: \"Form Intersection\",\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n return textResult(`Added form intersection layer '${id}'.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// generate_construction_exercise\n// ---------------------------------------------------------------------------\n\nconst generateExerciseTool: McpToolDefinition = {\n name: \"generate_construction_exercise\",\n description: \"Generate a random construction exercise with forms at varying difficulty.\",\n inputSchema: {\n type: \"object\",\n properties: {\n difficulty: { type: \"string\", enum: [\"beginner\", \"intermediate\", \"advanced\"], description: \"Exercise difficulty. Default: beginner.\" },\n formCount: { type: \"number\", description: \"Number of forms (overrides difficulty default).\" },\n seed: { type: \"number\", description: \"Random seed for reproducibility.\" },\n includeValues: { type: \"boolean\", description: \"Include a value study overlay. Default: false.\" },\n includeIntersections: { type: \"boolean\", description: \"Include intersection lines. Default: false.\" },\n },\n } satisfies JsonSchema,\n\n async handler(input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const difficulty = (input.difficulty as string) ?? \"beginner\";\n const seed = (input.seed as number) ?? Date.now();\n const includeValues = (input.includeValues as boolean) ?? false;\n const includeIntersections = (input.includeIntersections as boolean) ?? false;\n\n // Simple seeded random\n let s = seed;\n const rand = () => { s = (s * 1103515245 + 12345) & 0x7fffffff; return s / 0x7fffffff; };\n\n const defaultCounts: Record<string, number> = { beginner: 1, intermediate: 3, advanced: 5 };\n const formCount = (input.formCount as number) ?? defaultCounts[difficulty] ?? 1;\n const ids: string[] = [];\n\n const maxRotation: Record<string, number> = { beginner: 30, intermediate: 60, advanced: 90 };\n const rotLimit = maxRotation[difficulty] ?? 30;\n\n for (let i = 0; i < formCount; i++) {\n const typeIdx = Math.floor(rand() * VALID_FORMS.length);\n const formType = VALID_FORMS[typeIdx]!;\n\n const posSpread = difficulty === \"beginner\" ? 0 : 0.3;\n const defaults = formLayerType.createDefault();\n const properties: LayerProperties = {\n ...defaults,\n formType,\n position: { x: 0.5 + (rand() - 0.5) * posSpread, y: 0.5 + (rand() - 0.5) * posSpread },\n formSize: 0.15 + rand() * 0.15,\n rotationX: Math.round((rand() - 0.5) * 2 * rotLimit / 5) * 5,\n rotationY: Math.round((rand() - 0.5) * 2 * 180 / 5) * 5,\n rotationZ: difficulty === \"advanced\" ? Math.round((rand() - 0.5) * 2 * 45 / 5) * 5 : 0,\n showCrossContours: true,\n showAxes: true,\n };\n\n const id = generateLayerId();\n ids.push(id);\n addLayer(context, {\n id, type: \"construction:form\", name: `Exercise Form ${i + 1} (${formType})`,\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context), properties,\n });\n }\n\n // Optional value study\n if (includeValues) {\n const valDefaults = valueShapesLayerType.createDefault();\n const valId = generateLayerId();\n ids.push(valId);\n addLayer(context, {\n id: valId, type: \"construction:value-shapes\", name: \"Exercise Value Study\",\n visible: true, locked: true, opacity: 1, blendMode: \"normal\",\n transform: fullCanvasTransform(context),\n properties: { ...valDefaults, lightAzimuth: Math.round(rand() * 360 / 15) * 15 },\n });\n }\n\n return textResult(`Generated ${difficulty} exercise with ${formCount} form(s): ${ids.join(\", \")}.`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// clear_construction_guides\n// ---------------------------------------------------------------------------\n\nconst clearConstructionGuidesTool: McpToolDefinition = {\n name: \"clear_construction_guides\",\n description: \"Remove all construction:* layers from the layer stack.\",\n inputSchema: { type: \"object\", properties: {} } satisfies JsonSchema,\n\n async handler(_input: Record<string, unknown>, context: McpToolContext): Promise<McpToolResult> {\n const layers = context.layers.getAll();\n const ids = layers.filter((l) => l.type.startsWith(\"construction:\")).map((l) => l.id);\n\n if (ids.length === 0) return textResult(\"No construction layers to remove.\");\n\n for (const id of ids) context.layers.remove(id);\n context.emitChange(\"layer-removed\");\n return textResult(`Removed ${ids.length} construction layer(s).`);\n },\n};\n\n// ---------------------------------------------------------------------------\n// Export all tools\n// ---------------------------------------------------------------------------\n\nexport const constructionMcpTools: McpToolDefinition[] = [\n addConstructionFormTool,\n addConstructionSceneTool,\n addCrossContoursTool,\n addValueStudyTool,\n addEnvelopeTool,\n addFormIntersectionTool,\n generateExerciseTool,\n clearConstructionGuidesTool,\n];\n"],"mappings":"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","names":["DEG2RAD","projectVertex","projectVertex","ellipsePointAt","FACE_NORMALS","projectVertex","projectVertex","segLen","DEG2RAD"]}
|