@crystaldesign/planner-2d-core
v26.12.4
Published
Browser-free 2D planner core: article SVG parsing, docking logic, dock transform math and collision geometry.
Downloads
10,037
Readme
@crystaldesign/planner-2d-core
Browser-free core of the 2D planner: article SVG parsing, docking logic, dock transform math and collision geometry. No fabric.js, no engine, no catalog API — runs in the browser and in plain Node (backend services, unit tests, agent testbeds).
Extraction concept and phase plan: docs/2d-planner-rework/CONCEPT.md.
The ported logic is a behavior-faithful extraction of web-planner-logic's DockingPointHandler, the fabric-free
SVGUtils methods and the docking math of DivaStandardPlanner.updateWorldPos (phase P1 — web-planner-logic still
carries its own copy until P2 switches it over to this package).
Modules
| Module | Contents |
| --- | --- |
| svg/ | getDockingPointLines, getPolygonPoints, getOltGeometry/getOlfGeometry, removeOlf/removeMask, getMinBorder (DOM-based, Node-safe), pathBoundingBox (full command set M L H V C S Q T A Z incl. Bezier extrema and arcs) |
| stretch/ | stretchArticleSvg — synchronous SAH/SAV stretch engine, behavior-faithful rewrite of the legacy ccCheckStretchAreas (OLT-then-OLF double pass, rounding rules, global-scale mode) with axis-abstracted element/path transformers and a warnings[] report; deviations: unknown path commands survive, unsupported stretch areas are ignored, viewBox scaling is applied exactly once |
| docking/ | DockingPoint, DockingPointHandler (pairing rules, checkDPsDoMatch public), narrow PlannerElement2D interface |
| transform/ | computeDockedTransform — pure world-transform math for a docked element |
| collision/ | segmentsIntersect (fabric parity), polygon intersection/containment, outlinesCollide |
| testbed/ | DockingScene + SimplePlannerElement — SVGs in, docking points/pairings/world positions out |
Node usage
The parser needs a DOM. In the browser nothing is required; in Node a jsdom window is loaded lazily as fallback
(configureDom(new JSDOM('').window) only when a custom DOM should be used):
import { DockingScene } from '@crystaldesign/planner-2d-core';
const scene = new DockingScene();
const sofa = scene.addArticle(sofaSvg, { layer: 20 });
const extension = scene.addArticle(extensionSvg, { layer: 20 });
const result = scene.tryDock(extension, sofa); // -> { docked, dockingType, rotDeg, worldPosCorner }Logging is a no-op by default; inject one via setPlanner2DLogger (e.g. a DivaUtils/diva-backend-commons logger).
Testing
ctra test @crystaldesign/planner-2d-coreThe suites run under testEnvironment: node with explicitly configured jsdom — proving the browser-free contract on every run.
