jet_cad_2d
A pure-Dart 2D CAD engine and document model. It has no Flutter dependency, no FFI and no native build, and runs anywhere Dart runs: the VM, the web (JavaScript and Wasm) and every Flutter platform.
What it holds
- A document: a scene tree of groups, definitions and instances over columnar entity and geometry stores (points, lines, polylines, circles, arcs, text, attributes and fills), layers, linetypes and text styles, and typed components attached to nodes.
- Commands with undo: every edit is a command run through the document's dispatcher, undoable and redoable, compound commands included.
- A spatial index that follows each edit synchronously: rectangle queries, picking with the full path through nested instances, and object snapping. In steady state the frame-path queries allocate nothing per entity; a pick or a snap allocates a few objects per level of instance nesting, whatever the document's size.
- A deterministic file format: a JSON codec that writes a document back
byte for byte. It keeps the fields and components it does not recognise
(another application's components, for instance) and writes them back
unchanged; a file with a newer schema version is refused with
SchemaVersionError. - A parametric layer: object types an application registers are regenerated inside the edit that changes them, in the same undo step.
Example
The snippet uses vector_math for its points, so add both:
dart pub add jet_cad_2d vector_math.
import 'package:jet_cad_2d/jet_cad_2d.dart';
import 'package:vector_math/vector_math_64.dart' show Vector2;
void main() {
final doc = DraftDocument.empty();
final circle = addDrafted(
doc, EntityKind.circle, circlePayload(Vector2(300, 250), 50),
layer: ReservedHandles.layerZero);
doc.commands.execute(circle);
final index = SpatialIndex(doc);
final hit = HitPath();
if (index.pickInto(Vector2(300, 301), 2, const QueryFilter.picking(), hit)) {
print(hit.entity == circle.record.handle); // true
}
doc.commands.undo(); // the circle is gone, and the index knows it
print(DraftDocumentCodec.encodeToString(doc));
}
The full walk-through, which also saves and reloads the document, is in
example/jet_cad_2d_example.dart.
The API
package:jet_cad_2d/jet_cad_2d.dart is the API. Nothing under src/ is.
package:jet_cad_2d/testing.dart generates benchmark documents for this
repository's own suites; it is not API and may change in any release.
While the version is 0.x, a minor release (0.8.0) may break the API, and a
patch release (0.7.3) does not.
The jet-cad packages
| Package | What it is | Depends on |
|---|---|---|
jet_cad_2d_plan |
The plan library: the editor, the widgets and the host API | the kit contract, the renderer and the engine |
jet_cad_2d_kit_architecture |
The architecture kit: walls, openings, rooms, dimensions and furniture | the kit contract, the renderer and the engine |
jet_cad_2d_kit_restaurant |
The restaurant kit: furniture and service units | the kit contract and the engine |
jet_cad_2d_kit |
The kit contract: types, tools and the symbol library format | the renderer and the engine |
jet_cad_2d_flutter |
Flutter rendering and interaction | the engine |
jet_cad_2d |
The pure-Dart engine and document model | nothing of jet-cad |
A host that embeds the planner adds jet_cad_2d_plan and the kits it loads;
the kit contract, the renderer and the engine come with them, and a host
should not also depend on them directly unless it uses their API itself.
Embedding the floor planner in an app is walked through in the host guide.
Support
If jet-cad is useful to you, you can support its development through GitHub Sponsors or Buy Me a Coffee.
License
Apache License 2.0. See LICENSE.
Libraries
- jet_cad_2d
- A pure-Dart 2D CAD engine and document model.
- testing
- Test and benchmark fixtures. Not part of the package's public surface —
jet_cad_2d.dartdeliberately does not export this. It lives inlib/for one reason: the Flutter package's render rigs and this package's query benchmark must generate byte-identical documents, and a file underbenchmark/cannot be imported across packages.