A declarative parametric 3D modeling program built using Open Cascade. Allows you to build and edit 3D models in a simple and easy to learn language that extends python.

What is DeclaraCAD?

DeclaraCAD is an OpenCascade based application that let's you build 3D models using python. Unlike a few other python based programs and libraries which use an imperative code, DeclaraCAD uses a python extension language called enaml which allows 3D models to be written declaratively (hence the name). Since models are defined declaratively and properties are parametric. Model structure can be dynamically generated based on conditions, arrays, and other expressions (such as functions or data models). This enables you to very quickly build dynamic and sophisticated models that are still easy to read, manipulate, and extend.

Models are Declarative

Models are defined declaratively using shapes (cube, cylinder, sphere, etc..), operations (cut, fillet, extrude, etc..), and drawings. They are all nested as required to build the desired shape.

from enaml.core.api import Looper
from occ.shape import Box, Sphere
from occ.algo import Cut
from occ.part import Part

enamldef TurnersCube(Part):
    name = "Turners Cube"

    attr levels: int = 3
        iterable << range(1,1+levels)
                position = (-loop_item/2.0,-loop_item/2.0,-loop_item/2.0)
                dx = loop_item
                dy = loop_item
                dz = loop_item
                radius = loop_item/1.5
Parts are reusable

Making a new Part is as simple as defining it in a file, importing, and using it. It uses the same syntax as python. Allowing you to build complete libraries of parts and group them into packages.

from occ.part import Part
from toolbox.basic import Screw, Nut, Washer

enamldef Assembly(Part):
        dy = 10
        r = 1
        x = 4
        dx = 10
        r = 1
        x = 9
        dx = 10
        r =1
Properties are Parametric

Properties of models are parametric. You can define relations to other shapes and specify any equation that is evaluated to define a property.

from occ.shape import Cylinder, Prism, Face
from occ.draw import Segment, Arc, Wire, Point
from occ.algo import Fuse, ThickSolid, Fillet, Transform
from occ.part import Part

enamldef Bottle(Part): part:
    name = "Bottle"

    #: "Parametric" properties of this shape
    attr height = 7.0
    attr width = 5.0
    attr thickness = 3.0

    #: Actual shape
        color = '#333333'
        # Hollows out the bottle
        #closing_faces << [neck.shape_faces[0]]
        offset << thickness/50.0
            # Fuse the bottle to the neck
            Cylinder: neck:
                # Bottle neck
                position << (0,0,part.height)
                direction = (0,0,1)
                radius << thickness/4.0
                height << part.height/10.0
            Fillet: bottle:
                # Bottle, with filleted edges
                radius << thickness/12.0
                    # Create a solid from the bottle face
                    vector << (0,0,height)
                        # Create a face from the base profile
                            # Create a wire from the profile and mirrored profile
                            Wire: profile:
                                    Point: p1:
                                        position << (-width/2.0, 0, 0)
                                    Point: p2:
                                        position << (-width/2.0, -thickness/4.0, 0)
                                        position := p2.position
                                    Point: p3:
                                        position << (0, -thickness/2.0, 0)
                                        position := p5.position

                                    Point: p4:
                                        position << (width/2.0, 0, 0)
                                    Point: p5:
                                        position << (width/2.0, -thickness/4.0, 0)
                                #: TODO coerce
                                mirror = ((0,0,0),(1,0,0))
                                shape = profile