Constructive Solid Geometry¶
The pantr.cad module provides CAD-style functions for building B-spline
curves, surfaces, and volumes from geometric descriptions. All functions
return Bspline objects that integrate with the
rest of PaNTr (evaluation, derivatives, knot insertion, degree elevation, etc.).
Primitives¶
Primitives create B-spline objects directly from geometric parameters. All produce rank-3 (3D) output; lower-dimensional inputs are zero-padded.
Lines and multilinear patches¶
from pantr.cad import create_line, create_bilinear, create_trilinear
crv = create_line([0, 0, 0], [1, 0, 0]) # degree-1 curve
srf = create_bilinear() # unit square in XY
vol = create_trilinear() # unit cube
create_line() creates a degree-1 curve between two points.
create_bilinear() creates a degree-(1, 1) surface from four corners.
create_trilinear() creates a degree-(1, 1, 1) volume from eight corners.
Circles and arcs¶
from pantr.cad import create_circle
import numpy as np
full = create_circle(radius=2.0) # full circle, 4 spans
arc = create_circle(angle=np.pi / 2) # quarter arc, 1 span
arc2 = create_circle(angle=(np.pi / 4, np.pi), radius=3) # arc from 45 to 180 deg
create_circle() builds an exact rational quadratic B-spline.
The number of spans depends on the sweep angle (one span per 90 degrees),
with C0 interior knots (multiplicity equal to degree). This is the
standard conic representation.
Derived shapes¶
from pantr.cad import create_rectangle, create_disk, create_cylinder
rect = create_rectangle(corner=[0, 0, 0], width=2, height=3) # closed curve
ann = create_disk(radius_inner=0.5, radius_outer=1.0) # annular sector
cyl = create_cylinder(radius=1.0, height=5.0) # cylindrical surface
create_rectangle() returns a closed degree-1 curve visiting four corners.
create_disk() builds an annular sector (or full disk when radius_inner=0)
via create_ruled() between inner and outer circles.
create_cylinder() extrudes a circle along the z-axis.
Operations¶
Operations create higher-dimensional objects from existing ones by adding a new parametric direction.
Extrusion¶
from pantr.cad import create_circle, create_extrusion
pipe = create_extrusion(create_circle(), [0, 0, 2]) # circle -> cylindrical surface
create_extrusion() translates a curve or surface along a displacement
vector, appending a degree-1 parametric direction.
Revolution¶
from pantr.cad import create_line, create_revolution
import numpy as np
srf = create_revolution(create_line([1, 0, 0], [2, 0, 0]), point=0, axis=2)
quarter = create_revolution(create_line([1, 0, 0], [1, 0, 3]), point=0, axis=2,
angle=np.pi / 2)
create_revolution() rotates a curve or surface around an axis.
The angular direction inherits the same span structure as
create_circle() (one span per 90 degrees, C0 at arc junctions).
Supports coordinate axes (axis=0, 1, 2) and arbitrary axis vectors.
Ruled¶
from pantr.cad import create_circle, create_ruled
annulus = create_ruled(create_circle(radius=0.5), create_circle(radius=1.0))
create_ruled() linearly interpolates between two curves (or
surfaces) to produce a surface (or volume). The inputs are automatically
made compatible via make_compat().
Sweep¶
from pantr.cad import create_line, create_sweep
srf = create_sweep(create_line([0, 0, 0], [1, 0, 0]), # section
create_line([0, 0, 0], [0, 0, 3])) # trajectory
create_sweep() creates a translational sweep:
\(S(u, v) = \text{section}(u) + \text{trajectory}(v)\).
Coons blending¶
Surface¶
from pantr.cad import create_coons_surface, create_line
c_u0 = create_line([0, 0, 0], [1, 0, 0]) # bottom
c_u1 = create_line([0, 1, 0], [1, 1, 0]) # top
c_v0 = create_line([0, 0, 0], [0, 1, 0]) # left
c_v1 = create_line([1, 0, 0], [1, 1, 0]) # right
srf = create_coons_surface(((c_v0, c_v1), (c_u0, c_u1)))
create_coons_surface() builds a bilinearly blended surface from
four boundary curves using the formula \(S = R_0 + R_1 - B\), where \(R_0\)
and \(R_1\) are ruled surfaces and \(B\) is the bilinear corner interpolant. This is
the transfinite interpolation introduced by Coons [1967]; see also
Farin [2002] for a modern treatment.
Volume¶
from pantr.cad import create_bilinear, create_coons_volume
import numpy as np
# Build 6 faces of a unit cube
face_u0 = create_bilinear(np.array([[[0,0,0],[0,0,1]],[[0,1,0],[0,1,1]]], dtype=float))
face_u1 = create_bilinear(np.array([[[1,0,0],[1,0,1]],[[1,1,0],[1,1,1]]], dtype=float))
face_v0 = create_bilinear(np.array([[[0,0,0],[0,0,1]],[[1,0,0],[1,0,1]]], dtype=float))
face_v1 = create_bilinear(np.array([[[0,1,0],[0,1,1]],[[1,1,0],[1,1,1]]], dtype=float))
face_w0 = create_bilinear(np.array([[[0,0,0],[0,1,0]],[[1,0,0],[1,1,0]]], dtype=float))
face_w1 = create_bilinear(np.array([[[0,0,1],[0,1,1]],[[1,0,1],[1,1,1]]], dtype=float))
vol = create_coons_volume(((face_u0, face_u1),
(face_v0, face_v1),
(face_w0, face_w1)))
create_coons_volume() builds a trilinearly blended volume from
six boundary faces using the inclusion-exclusion formula:
where \(R\) are ruled volumes from opposite face pairs, \(B\) are bilinear blend volumes from edge quadruples, and \(T\) is the trilinear corner interpolant. Edges and corners are extracted automatically from face boundaries.
Compatibility and assembly¶
make_compat¶
from pantr.cad import make_compat, create_circle, create_line
c1 = create_line([0, 0, 0], [1, 0, 0]) # degree 1
c2 = create_circle(angle=np.pi / 2) # degree 2, different knots
r1, r2 = make_compat(c1, c2) # now same degree and knots
make_compat() makes N B-splines compatible along specified axes by:
Remapping domains to a common envelope.
Elevating degrees to the maximum.
Merging knot vectors (union of breakpoints with max multiplicities).
This is called internally by create_ruled(),
create_coons_surface(), create_coons_volume(), and
join().
join¶
from pantr.cad import join, create_line
c1 = create_line([0, 0, 0], [1, 0, 0])
c2 = create_line([1, 0, 0], [2, 1, 0])
merged = join(c1, c2, axis=0)
join() concatenates two B-splines along a parametric
axis with C0 continuity. Knots are automatically removed at the junction
when the geometry permits higher smoothness.