A standalone C++17 reference implementation of the Morphe sketch schema:
data structures, JSON (de)serialization, and validation. Mirrors the
Python implementation in ../morphe/ but does not depend on it.
The two implementations agree on the wire format documented in
../SPECIFICATION.md §13 and pinned by the conformance corpus under
../tests/conformance/.
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureRequires CMake 3.16+, a C++17 compiler (gcc 9+, clang 9+, MSVC 2019+).
add_subdirectory(path/to/morphe/cpp)
target_link_libraries(your_target PRIVATE morphe::morphe)morphe is a header-only INTERFACE library at this stage; linking it
brings in the include path for <morphe/...> headers and the vendored
<nlohmann/json.hpp>.
third_party/nlohmann/json.hpp— nlohmann/json v3.11.3 (MIT)third_party/doctest/doctest.h— doctest/doctest v2.4.11 (MIT, tests only)
Both are checked in as single headers so the project builds offline with
no CMake FetchContent dance.
The reference implementation covers:
- All core types (
Point2D,Vector2D,PointType,PointRef). - All seven primitive types (
Line,Arc,Circle,Point,Spline,Ellipse,EllipticalArc) modeled as astd::variant. - All 19
ConstraintTypevalues plus theCONSTRAINT_RULEStable. SketchDocumentwith insertion-ordered primitives.- JSON (de)serialization matching the Python encoder byte-for-byte on shared corpus fixtures.
- Schema validation with the same severity-tagged issue codes as the
Python validator (e.g.,
LINE_ZERO_LENGTH,ARC_RADIUS_INCONSISTENT,CONST_TOO_FEW_REFS), and the same 1-micron default tolerance.
Out of scope (matches the Python core): a constraint solver, CAD adapters (FreeCAD / SolidWorks / Inventor / Fusion), or computational helpers (B-spline evaluation, ellipse parametric, etc.). These belong above the schema layer.
The shared corpus under ../tests/conformance/*.json is the wire-format
contract. It is generated from the Python implementation
(tests/conformance/generate_corpus.py) and consumed by both:
- Python:
tests/test_conformance_corpus.pychecks thatsave_sketch(load_sketch(f)) == fbyte-for-byte. - C++:
tests/test_conformance.cpploads each fixture, round-trips throughmorphe::to_json, and compares parsed JSON trees with float tolerance. Therounded_rect.jsonfixture is also rebuilt in C++ and semantically compared, pinning the exact wire format.
CI (.github/workflows/cpp.yml) runs both checks on Ubuntu (gcc-13,
clang-18), macOS, and Windows.
The C++ decoder accepts both the omit-when-default form (the
canonical wire format described in SPECIFICATION.md §13.1.1) and
the verbose form with explicit defaults ("value": null, "inferred": false, "confidence": 1.0). Documents from older or
third-party encoders that emit defaults explicitly therefore load
correctly. Round-tripping through morphe::to_json normalizes them
to the minimal form.