A web-based parametric 2D CAD editor designed as the front-end for a CNC CAM pipeline.
Draw geometry, add geometric constraints and driving dimensions, then generate G-code — all in the browser, no install required.
Live demo: https://rapidcam.mycnc.app
| Sketch editor | Constraint solver | CAM toolpaths |
|---|---|---|
![]() |
![]() |
![]() |
| Tool | Key | Description |
|---|---|---|
| Select | V |
Click/drag to select; move, resize, or rotate selected entities |
| Line | L |
Click two points; chains automatically |
| Rectangle | R |
Click two corners |
| Circle | C |
Click centre then a point on the circumference |
| Arc | A |
Click centre, start, end |
| Slot | U |
Click two centre points; auto-constrains the two arc caps |
| Polygon | N |
Click centre then a vertex; [/] change side count |
| Polyline | P |
Click vertices; Enter to close; open or closed |
| Bezier | B |
Click four control points (cubic) |
| Text | X |
Click to place; double-click any text entity to edit in place |
| Dimension | D |
Click an entity to annotate; drag the witness line |
| Offset | O |
Click an entity to offset inward or outward |
| Fillet | F |
Click a sharp corner to round it with a user-typed radius |
| Chamfer | — | Click a sharp corner to bevel it with a user-typed distance |
| Trim | T |
Click the segment to remove at an intersection |
| Mirror | M |
Reflect selected entities across a picked axis line |
| Rotate | Q |
Rotate selected entities by angle around a pivot |
| Scale | S |
Scale selected entities by factor around a pivot |
RapidCAM uses a Levenberg-Marquardt solver with Tikhonov regularisation. Non-pinned degrees of freedom are always anchored so that editing a driving dimension produces a minimal-movement solution (no unexpected rotations).
Available constraints (applied from the constraint bar or automatically by tools):
- Coincident — two points share the same location
- Horizontal / Vertical — line is axis-aligned
- Parallel / Perpendicular / Collinear — angular relationships between lines
- Equal — two lengths or radii are equal
- Symmetric — entity mirrored about a line
- Midpoint — point lies at the midpoint of a line
- Fixed — entity is locked to the world frame
- Tangent — circle/arc is tangent to a line or another arc
- Point on Line / Point on Arc / Point on Circle
- Concentric
- Angle — angular constraint between two lines
DOF-based entity colouring: After each solve, every entity is coloured by its constraint status — blue = under-defined (free DOFs remain), normal = fully defined, red = over-constrained or conflicting. The analysis uses RREF null-space decomposition so that mutual dependencies between entities are handled correctly.
Driving dimensions change the geometry when edited (shown in cyan). Reference (driven) dimensions display the measured value in grey, wrapped in parentheses: (50.00 mm). Toggle between the two modes in the dimension inspector.
Named variables (pitch, diameter, …) can be defined in the Variables panel and used in any dimension value field. Expressions like pitch * 2 are evaluated at solve time.
- Linear pattern — copies geometry in an X/Y grid; spacing fields accept variable expressions
- Circular pattern — copies geometry around a centre point; editable count and total angle
- Both patterns store a regeneratable definition; re-opening the dialog lets you update the parameters and regenerate the copies
Entities live on named, coloured, show/hide layers. Construction geometry (dashed) is kept on separate layers and excluded from CAM operations.
| Feature | Details |
|---|---|
| Profile cut | Contour-follows any closed chain; lead-in / lead-out arcs |
| Pocket clearing | Raster or contour strategy; respects islands |
| Tabs / bridges | Automatic tab insertion on profile cuts |
| Tool library | Named tool definitions with diameter, flute count, feed/speed presets |
| G-code export | GRBL and LinuxCNC post-processors |
| WebGL toolpath preview | 3D preview of the cut paths |
- Native project format — JSON snapshot with full document state (undo history preserved across sessions)
- SVG import/export — round-trips clean paths; exported SVG preserves layer colours
- Drag-and-drop — drop an SVG file onto the canvas to import
src/
├── app.ts # Application shell — wires everything together
├── main.ts # Entry point
├── style.css # Dark-theme CSS
│
├── core/ # Pure math utilities
│ ├── vec2.ts # 2-D vector operations
│ ├── units.ts # mm ↔ display-unit conversion
│ ├── expr.ts # Variable expression evaluator
│ ├── transform.ts # Translate / rotate / scale helpers
│ └── fontManager.ts # opentype.js wrapper
│
├── model/ # Document data model (no rendering, no DOM)
│ ├── document.ts # CADDocument class — entities, constraints, dimensions, undo
│ ├── entities.ts # Entity classes (Line, Circle, Arc, Polyline, …)
│ ├── constraints.ts # Constraint definitions and residual functions
│ ├── dimensions.ts # Dimension layout and residuals
│ ├── variables.ts # Named variable evaluation
│ ├── patterns.ts # PatternDef — linear & circular parametric patterns
│ └── history.ts # Snapshot-based undo / redo
│
├── solver/ # Geometric constraint solver
│ ├── solver.ts # Levenberg-Marquardt + DOF status computation
│ └── linalg.ts # Gaussian elimination, RREF, matrixRank
│
├── view/ # Canvas rendering (no model mutation)
│ ├── renderer.ts # Main draw loop — entities, dimensions, constraints
│ ├── viewport.ts # World ↔ screen transform, zoom/pan
│ ├── colors.ts # Central colour palette
│ ├── grid.ts # Adaptive grid
│ └── overlay.ts # Transient visuals (snap, preview, selection rect)
│
├── input/ # User input
│ └── snapping.ts # Snap engine (endpoints, midpoints, intersections, grid)
│
├── tools/ # One file per drawing/editing tool
│ ├── tool.ts # Tool interface + ToolManager
│ ├── selectTool.ts
│ ├── lineTool.ts # … (one file per tool)
│ └── icons.ts # Inline SVG icons (24×24)
│
├── ui/ # UI panels — toolbar, bars, dialogs
│ ├── toolPalette.ts
│ ├── constraintBar.ts
│ ├── camBar.ts
│ ├── statusBar.ts
│ └── …
│
├── cam/ # CAM operations
│ ├── types.ts # CamOperation, ToolDef
│ ├── pocket.ts # Pocket clearing
│ ├── offset.ts # Contour offsetting (via Clipper2)
│ ├── tabs.ts # Tab/bridge insertion
│ ├── gcode.ts # G-code builder
│ ├── toolLibrary.ts
│ └── postprocessors/ # GRBL, LinuxCNC
│
└── io/ # File I/O
├── fileio.ts
├── svgImport.ts
├── svgExport.ts
└── projectManager.ts
Coordinate system: All geometry is stored in millimetres with Y-up (standard mathematical convention). The renderer flips Y when converting to screen space.
Internal units: The solver and all constraint residuals always work in mm. Display units (mm / inch) are applied only at the UI layer.
- Node.js 18 or later
- npm (bundled with Node)
git clone https://github.com/your-org/rapidcam.git
cd rapidcam
npm install
npm run dev # starts Vite dev server at http://localhost:5173npm run typecheck # TypeScript type check (no emit)
npm run build # type check + Vite production build → dist/
npm run preview # serve the dist/ build locallySee CONTRIBUTING.md for the full guide. The short version:
- Fork the repo and create a feature branch.
- Make your changes — keep them focused and minimal.
- Run
npm run typecheckand confirm it passes with no errors. - Open a pull request against
main.
License note: This project is licensed under CC BY-NC-SA 4.0. Contributions are accepted under the same licence. Commercial forks are not permitted without prior written agreement.
RapidCAM is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International licence.
You are free to share and adapt the material for non-commercial purposes, provided you give appropriate credit and distribute your contributions under the same licence.
See LICENSE for the full legal text.



