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 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 Looper: iterable << range(1,1+levels) Cut: Box: position = (-loop_item/2.0,-loop_item/2.0,-loop_item/2.0) dx = loop_item dy = loop_item dz = loop_item Sphere: radius = loop_item/1.5
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): Screw: dy = 10 r = 1 Washer: x = 4 dx = 10 r = 1 Nut: x = 9 dx = 10 r =1
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 ThickSolid: color = '#333333' # Hollows out the bottle #closing_faces << [neck.shape_faces] offset << thickness/50.0 Fuse: # 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 Prism: # Create a solid from the bottle face vector << (0,0,height) Face: # Create a face from the base profile Wire: # Create a wire from the profile and mirrored profile Wire: profile: Segment: Point: p1: position << (-width/2.0, 0, 0) Point: p2: position << (-width/2.0, -thickness/4.0, 0) Arc: Point: position := p2.position Point: p3: position << (0, -thickness/2.0, 0) Point: position := p5.position Segment: Point: p4: position << (width/2.0, 0, 0) Point: p5: position << (width/2.0, -thickness/4.0, 0) Transform: #: TODO coerce mirror = ((0,0,0),(1,0,0)) shape = profile