CAD-agnostic representation for 2D sketch geometry and constraints
Project description
Morphe
Pronounced "mor-FAY" (from Greek μορφή, meaning "form" or "shape")
A CAD-agnostic 2D sketch geometry and constraint representation with adapter support for FreeCAD, Fusion 360, SolidWorks, and Autodesk Inventor.
Overview
This project provides:
morphe: Platform-independent schema for 2D sketch geometry and constraintsmorphe.adapters.freecad: Adapter for FreeCAD's Sketcher workbenchmorphe.adapters.fusion: Adapter for Autodesk Fusion 360morphe.adapters.solidworks: Adapter for SolidWorks (Windows only, via COM)morphe.adapters.inventor: Adapter for Autodesk Inventor (Windows only, via COM)
The canonical format enables constrained sketches to be stored, transferred, and manipulated independently of any specific CAD system.
See SPECIFICATION.md for the complete technical specification, including supported geometry types, constraints, JSON schema format, and platform-specific adapter details.
Installation
pip install -e .
Platform-Specific Requirements
| Adapter | Platform | Requirements |
|---|---|---|
| FreeCAD | Linux, macOS, Windows | FreeCAD installed and accessible via PYTHONPATH |
| Fusion 360 | Windows, macOS | Run from within Fusion 360's Python environment |
| SolidWorks | Windows only | SolidWorks installed, pywin32 package |
| Inventor | Windows only | Autodesk Inventor installed, pywin32 package |
For Windows COM-based adapters (SolidWorks, Inventor):
pip install pywin32
Quick Start
from morphe import (
SketchDocument, Point2D, Line, Circle, Horizontal, Radius,
save_sketch, load_sketch
)
# Create a sketch
sketch = SketchDocument(name="MySketch")
line_id = sketch.add_primitive(Line(start=Point2D(0, 0), end=Point2D(100, 0)))
circle_id = sketch.add_primitive(Circle(center=Point2D(50, 50), radius=20))
sketch.add_constraint(Horizontal(line_id))
sketch.add_constraint(Radius(circle_id, 20))
save_sketch(sketch, "my_sketch.json")
# Load from file
sketch = load_sketch("my_sketch.json")
FreeCAD Integration
from morphe import load_sketch
from morphe.adapters.freecad import FreeCADAdapter
sketch = load_sketch("my_sketch.json")
adapter = FreeCADAdapter()
adapter.create_sketch(sketch.name)
adapter.load_sketch(sketch)
status, dof = adapter.get_solver_status()
print(f"Status: {status.name}, DOF: {dof}")
adapter.close_sketch()
Fusion 360 Integration
The Fusion 360 adapter runs as a script or add-in within Fusion 360:
# Run this inside Fusion 360's Scripts environment
import sys
sys.path.insert(0, r"path/to/morphe-repo")
from morphe import load_sketch
from morphe.adapters.fusion import FusionAdapter
def run(context):
sketch = load_sketch("my_sketch.json")
adapter = FusionAdapter()
adapter.create_sketch(sketch.name)
adapter.load_sketch(sketch)
# Export back to canonical format
exported = adapter.export_sketch()
print(f"Exported {len(exported.primitives)} primitives")
status, dof = adapter.get_solver_status()
print(f"Status: {status.name}, DOF: {dof}")
SolidWorks Integration
The SolidWorks adapter uses COM automation via pywin32 (Windows only):
from morphe import load_sketch
from morphe.adapters.solidworks import SolidWorksAdapter, SOLIDWORKS_AVAILABLE
if SOLIDWORKS_AVAILABLE:
sketch = load_sketch("my_sketch.json")
adapter = SolidWorksAdapter()
adapter.create_sketch(sketch.name)
adapter.load_sketch(sketch)
# Export back to canonical format
exported = adapter.export_sketch()
print(f"Exported {len(exported.primitives)} primitives")
status, dof = adapter.get_solver_status()
print(f"Status: {status.name}, DOF: {dof}")
Notes:
- Requires SolidWorks to be installed and running (or will launch automatically)
- The adapter connects to an existing SolidWorks instance or starts a new one
- Sketches are created on the Front Plane by default (XY plane)
- Dimensional constraints use geometry recreation to avoid blocking dialogs
Supported Features:
- All primitive types: Line, Arc, Circle, Point, Spline, Ellipse, EllipticalArc
- All geometric constraints: Coincident, Tangent, Parallel, Perpendicular, Horizontal, Vertical, Equal, Concentric, Collinear, Midpoint, Fixed, Symmetric
- All dimensional constraints: Length, Radius, Diameter, Angle, Distance, DistanceX, DistanceY
- Construction geometry
- Solver status and DOF reporting
Inventor Integration
The Inventor adapter uses COM automation via pywin32 (Windows only):
from morphe import load_sketch
from morphe.adapters.inventor import InventorAdapter, INVENTOR_AVAILABLE
if INVENTOR_AVAILABLE:
sketch = load_sketch("my_sketch.json")
adapter = InventorAdapter()
adapter.create_sketch(sketch.name)
adapter.load_sketch(sketch)
# Export back to canonical format
exported = adapter.export_sketch()
print(f"Exported {len(exported.primitives)} primitives")
status, dof = adapter.get_solver_status()
print(f"Status: {status.name}, DOF: {dof}")
Notes:
- Requires Autodesk Inventor to be installed and running (or will launch automatically)
- The adapter connects to an existing Inventor instance or starts a new one
- Sketches are created on the XY plane by default
Supported Features:
- All primitive types: Line, Arc, Circle, Point, Spline, Ellipse, EllipticalArc
- All geometric constraints: Coincident, Tangent, Parallel, Perpendicular, Horizontal, Vertical, Equal, Concentric, Collinear, Midpoint, Fixed, Symmetric
- All dimensional constraints: Length, Radius, Diameter, Angle, Distance, DistanceX, DistanceY
- Construction geometry
- Solver status and DOF reporting
RPC Server Mode
For GUI tools or external scripts that need to communicate with CAD applications, each adapter provides an RPC server/client pair.
Starting Servers
FreeCAD (run in FreeCAD's Python console):
from morphe.adapters.freecad import start_server
start_server() # localhost:9876
Fusion 360 (install the MorpheServer add-in from morphe/adapters/fusion/addin/MorpheServer/):
cd morphe/adapters/fusion/addin
python setup_addin.py install
The server starts automatically when Fusion 360 launches (localhost:9879).
SolidWorks (run with SolidWorks open):
from morphe.adapters.solidworks import start_server
start_server() # localhost:9878
Inventor (run with Inventor open):
from morphe.adapters.inventor import start_server
start_server() # localhost:9877
Using Clients
All clients share the same interface:
from morphe.adapters.freecad import FreeCADClient
# or: from morphe.adapters.fusion import FusionClient
# or: from morphe.adapters.solidworks import SolidWorksClient
# or: from morphe.adapters.inventor import InventorClient
client = FreeCADClient()
if client.connect():
# List available sketches
sketches = client.list_sketches()
# Export a sketch to canonical format
sketch = client.export_sketch("Sketch")
# Import a sketch into the CAD application
client.import_sketch(my_sketch, name="NewSketch")
# Get solver status
status, dof = client.get_solver_status("Sketch")
Running Tests
Core tests (no CAD software required):
pytest tests/ # All tests
pytest tests/ --cov # With coverage
FreeCAD adapter tests (requires FreeCAD):
pytest tests/test_freecad_roundtrip.py -v
Fusion 360 adapter tests (run from within Fusion 360):
The Fusion 360 test suite (73 tests) must be run as a script inside Fusion 360:
- Open Fusion 360
- Go to Utilities > Add-Ins > Scripts
- Add and run the test script from
morphe/adapters/fusion/script/MorpheTests/
SolidWorks adapter tests (requires SolidWorks on Windows):
pytest tests/test_solidworks_roundtrip.py -v
The SolidWorks test suite includes 80 tests covering:
- Basic and complex geometry primitives
- All constraint types including symmetric constraints
- Solver status detection
- Precision and edge cases
- Arc variations and tangent constraints
Inventor adapter tests (requires Inventor on Windows):
pytest tests/test_inventor_roundtrip.py -v
Tests cover all primitives, constraints, solver status, and edge cases.
License
MIT - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file morphe_sketch-0.1.0.tar.gz.
File metadata
- Download URL: morphe_sketch-0.1.0.tar.gz
- Upload date:
- Size: 178.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa31fbc33fef44f9ff42b8cd1f8e8582a8ac04defc5880893a68c02336228e98
|
|
| MD5 |
1ac64ab63bdd0814306963add3bed7a7
|
|
| BLAKE2b-256 |
6b10461b2a9d4642640677a76219341bad04aa61e5b7ce48ff08e1d77bd3de21
|
Provenance
The following attestation bundles were made for morphe_sketch-0.1.0.tar.gz:
Publisher:
publish.yml on CodeReclaimers/morphe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
morphe_sketch-0.1.0.tar.gz -
Subject digest:
fa31fbc33fef44f9ff42b8cd1f8e8582a8ac04defc5880893a68c02336228e98 - Sigstore transparency entry: 833475957
- Sigstore integration time:
-
Permalink:
CodeReclaimers/morphe@2a08e1f5c675faab515634fe46edcbb3ddc3919e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/CodeReclaimers
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2a08e1f5c675faab515634fe46edcbb3ddc3919e -
Trigger Event:
release
-
Statement type:
File details
Details for the file morphe_sketch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: morphe_sketch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 146.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05cb2f2e8dd411f61f981278b27cd85631f8614e8c9b8d1f9ecbe56270517264
|
|
| MD5 |
ce9f03d8855c3346c6e449d44c7035f8
|
|
| BLAKE2b-256 |
4ac7b307fde60bbbb2ba3630f663e5ee66a01d1a164e59e2a379721c34ec4442
|
Provenance
The following attestation bundles were made for morphe_sketch-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on CodeReclaimers/morphe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
morphe_sketch-0.1.0-py3-none-any.whl -
Subject digest:
05cb2f2e8dd411f61f981278b27cd85631f8614e8c9b8d1f9ecbe56270517264 - Sigstore transparency entry: 833475959
- Sigstore integration time:
-
Permalink:
CodeReclaimers/morphe@2a08e1f5c675faab515634fe46edcbb3ddc3919e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/CodeReclaimers
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2a08e1f5c675faab515634fe46edcbb3ddc3919e -
Trigger Event:
release
-
Statement type: