Lines and loops

Solid and planar primitives are not always enough to build the geometry you need. The more advanced operations in this manual can construct bodies from arbitrary curves.

ZenCad and the OpenCascade kernel have two classes of one-dimensional geometry: Edge and Wire. An Edge is a simple primitive; joining several edges into a composite curve produces a Wire. They can often be used interchangeably, but the distinction matters when inspecting a model's topology.

A collection of Wire and/or Edge objects can be joined with sew (described below).

Closed curves are called loops. If a loop and all its constituent curves lie in one plane, fill can turn it into a face (see "Planar primitives").

Additional operations are described in "Curve analysis".


Segment

An ordinary line segment, specified by two points.

Signature:

segment(pnt1, pnt2)


Polysegment

A polysegment is a polyline specified by an array of points, pnts. Setting closed adds a segment from the final point back to the first.

Signature:

polysegment(pnts, closed=False)


Interpolation through points

Builds an interpolated curve through pnts. The optional tangs parameter specifies a tangent direction at each point (None leaves it unconstrained). Setting closed adds a closing curve segment.

Signature:

interpolate(pnts, tangs=None, closed=False)



Circular arc through three points

An alternative to circle (see Planar primitives) for creating a circular arc, using three points.

Signature:

circle_arc(p1, p2, p3)


Helix

An ascending helix specified by radius r, height h and pitch step. Setting left changes right-handed winding to left-handed winding. The optional angle makes the radius vary with height along a cone.

Signature:

helix(r, h, step, angle=angle, left=False)



Bézier curve

A Bézier curve (wiki), specified by control points and optional weights. Omitted weights are all one.

Signature:

bezier(pnts)
bezier(pnts, weights)


BSpline

Creates a BSpline by specifying its parameters directly.

Signature:

bspline(pnts, knots, muls, degree, periodic=False)
bspline(pnts, knots, muls, degree, weights=weights, check_rational=True)

knots gives parameter values; muls gives their multiplicities. For example, a cubic curve with four control points and clamped endpoints:

from zencad import *

curve = bspline(
    [(0, 0, 0), (10, 20, 0), (20, -10, 0), (30, 0, 0)],
    knots=[0, 1], muls=[4, 4], degree=3,
)
display(curve)
show()

Rounded polysegment

Adds circular arcs at the joins between line segments. r sets the fillet radius. It can be used with pipe_shell (see sweep surfaces). Setting closed closes the curve with a rounded join.

Signature:

rounded_polysegment(pnts, r, closed=False)

Example:

rounded_polysegment(
    pnts=[(0,0,0), (20,0,0), (20,20,40), (-40,20,40), (-40,20,0)],
    r=10)


Creating a composite curve

sew assembles a composite curve from the parts in wires.

The parts can be Edge and Wire objects (geometric types).

Parts must meet at their endpoints and follow the correct order. If sort is set, the algorithm attempts to order them automatically.

Signature:

sew(wires, True) # sort is positional; default: True

Example:

sew([
    segment((0,0,0), (0,10,0)),
    circle_arc((0,10,0),(10,15,0),(20,10,0)),
    segment((20,0,0), (20,10,0)),
    segment((20,0,0), (0,0,0))
])


Wire builder

Builds a curve one section at a time, starting each edge at the previous edge's endpoint. Operations accept absolute or relative coordinates. In relative mode, control-point coordinates are added to the builder's current position. rel selects the mode: False for absolute, True for relative. If omitted, defrel is used.

Constructor arguments:
start — starting point
defrel — default coordinate mode

wb = wire_builder(start=(0,0,0), defrel=False)

Restarting

Restarts at a new point and clears the edge list.

wb.restart(pnt, y=None, z=None)
wb.restart(point3(10,15,0))
wb.restart(10,15)

Adding a segment

Builds a segment to pnt.

wb.segment(pnt, y=None, z=None, rel=None)
wb.line(b, y=None, z=None, rel=None)
wb.l(b, y=None, z=None, rel=None)
wire_builder(defrel=True).restart((0,10)).l(10,0).l(0,-10).close().doit() # draw a square


Adding a circular arc through points

wb.arc_by_points(a,b,rel=None)

Adding an interpolated curve

curtang sets the curve direction at the starting point. Setting approx derives curtang from the direction at the end of the preceding section.

wb.interpolate(pnts, tangs=None, curtang=(0,0,0), approx=False, rel=None)

Closing

close builds a section back to the starting point. approx_a and approx_b enable interpolation at the closing joins.

wb.close(approx_a=False, approx_b=False)

The finished contour

.doit() returns the constructed Wire. The contour can be filled and extruded into a body:

from zencad import *

contour = (wire_builder(start=(0, 0, 0))
           .segment((30, 0, 0))
           .arc_by_points((40, 10, 0), (30, 20, 0))
           .segment((0, 20, 0))
           .close()
           .doit())
body = fill(contour).extrude(5)
display(body)
show()