Skip to content

Tutorial¤

This tutorial gives a brief overview of the functionality of compas_occt and recommended best practices.

Working with Curves¤

NURBS curves are created from control points (or from primitives such as lines, circles, and ellipses) and can be evaluated and discretised anywhere in their parameter domain.

from compas.geometry import Point
from compas_occt.geometry import OCCNurbsCurve

points = [Point(0, 0, 0), Point(3, 6, 0), Point(6, -3, 3), Point(10, 0, 0)]
curve = OCCNurbsCurve.from_points(points)

start, end = curve.domain
point = curve.point_at(0.5 * (start + end))
tangent = curve.tangent_at(0.5 * (start + end))
polyline = curve.to_polyline(n=100)

Working with Surfaces¤

NURBS surfaces are created from a grid of control points and evaluated in their (u, v) parameter space. Isocurves are returned as curves that can be discretised like any other.

from compas.geometry import Point
from compas_occt.geometry import OCCNurbsSurface

points = [
    [Point(0, 0, 0), Point(1, 0, 0), Point(2, 0, 0)],
    [Point(0, 1, 0), Point(1, 1, 2), Point(2, 1, 0)],
    [Point(0, 2, 0), Point(1, 2, 0), Point(2, 2, 0)],
]
surface = OCCNurbsSurface.from_points(points=points)

point = surface.point_at(0.5, 0.5)
u_isocurve = surface.isocurve_u(0.5)

Working with Breps¤

Breps (Boundary Representations) describe solids through their faces, edges, and vertices. They are created from primitives or other geometry, queried for mass properties, and combined with boolean operations (+ union, - difference, & intersection).

from compas.geometry import Box, Frame
from compas_occt.brep import OCCBrep

a = OCCBrep.from_box(Box(1))
b = OCCBrep.from_box(Box(1, frame=Frame([0.5, 0.5, 0.5])))

union = a + b

print(union.is_solid, union.volume, union.area)

A Brep can also be reduced to the wire geometry of its boundary. to_curves() converts every edge to the COMPAS curve matching its underlying geometry -- a Line for a straight edge, a Circle for a circular one, and so on -- reporting each edge once even where two faces share it.

from compas.geometry import Cylinder
from compas_occt.brep import OCCBrep

brep = OCCBrep.from_cylinder(Cylinder(radius=1, height=2))

for curve in brep.to_curves():
    print(type(curve).__name__)

to_polylines() is the flat-polygon case of the same idea. A Brep whose faces are all planar and bounded by straight edges is fully described by the points of its loops, so it converts to one closed polyline per loop -- the outer loop of a face first, then its holes -- with nothing lost. Anything else would silently lose its curvature, so the conversion is refused instead of approximated. Check is_polygonal up front, or use to_polygons() to reduce the faces whatever their geometry.

from compas.geometry import Box
from compas_occt.brep import OCCBrep

plate = OCCBrep.from_box(Box(10, 10, 1)) - OCCBrep.from_box(Box(2, 2, 5))

print(plate.is_polygonal)

for polyline in plate.to_polylines():
    print(len(polyline.points), polyline.is_closed)

Visualisation¤

compas_occt geometry is visualised with compas_viewer. Convert a Brep to its tessellated mesh and boundary curves, and add those to the viewer.

from compas.geometry import Box
from compas_occt.brep import OCCBrep
from compas_viewer import Viewer

brep = OCCBrep.from_box(Box(1))
mesh, boundaries = brep.to_tesselation()

viewer = Viewer()
viewer.scene.add(mesh)
viewer.scene.add(boundaries)
viewer.show()

Using the plugin system¤

compas_occt provides a NURBS and Brep (Boundary Representation) backend for COMPAS based on OpenCASCADE. Although it can be used as a standalone package, the recommended way to use it is through the plugin system. The following snippets accomplish the same thing, but the first uses compas_occt directly, and the second uses it as a plugin.

from compas.geometry import Point
from compas_occt.geometry import OCCNurbsCurve

points = [
    Point(0, 0, 0),
    Point(3, 6, 0),
    Point(6, -3, 3),
    Point(10, 0, 0)
]

curve = OCCNurbsCurve.from_points(points)
from compas.geometry import Point
from compas.geometry import NurbsCurve

points = [
    Point(0, 0, 0),
    Point(3, 6, 0),
    Point(6, -3, 3),
    Point(10, 0, 0)
]

curve = NurbsCurve.from_points(points)

The advantage of using the plugin system is that it allows COMPAS to automatically switch to different backends depending on the current environment without changing the script. For example, when working in Rhino, the first script will throw an error, whereas the second script will work as expected by switching to RhinoCommon as a backend.