CSG operations

Boolean operations

Basic operations

Base.unionMethod
union(a::AbstractGeometry...)

Computes the union of several solids. The dimensions must match.

source
julia> s = union(cube(50), sphere(50)); # equivalently: cube(50) ∪ sphere(50)

example: union of a sphere and a cube

N-ary union may be performed in this way:

julia> s = union(([0,10i]+square(5) for i in 1:5)...); # equivalently: ⋃(([0,10i]+square(5) for i in 1:5)...)

example: n-ary union

Base.intersectMethod
intersect(a::AbstractGeometry...)

Computes the intersection of several solids. Mismatched dimensions are allowed; 3d solids will be intersected with the horizontal plane (as if by the slice() operation) and a 2d intersection will be returned.

source
julia> s = intersect(cube(50), sphere(50)); # equivalently: cube(50) ∩ sphere(50)

example: intersection of a sphere and a cube

Base.setdiffMethod
setdiff(a::AbstractGeometry, b::AbstractGeometry)

Computes the difference of two solids. The following dimensions are allowed: (2,2), (3,3), and (2,3). In the latter case, the 3d object will be intersected with the horizontal plane via the slice() operation.

source
julia> s = setdiff(cube(50), [50,0,0]+sphere(50)); # equivalently: cube(50) - sphere(50)

example: difference of a sphere and a cube

ConstructiveGeometry.complementFunction
complement(x::AbstractGeometry)
~x

Returns the complement of x, i.e. an object X such that y ∩ X = y ∖ x.

Warning: complement

Complements are symbolic and only supported as shortcuts for some Boolean operations: ∪, ∩, ∖. (They would not make any sense in most other constructions anyway).

source

Complements are provided as a shortcut to simplify “subtractive” operations, i.e. chains of intersections and differences. See Three-dimensional embeddings of two-dimensional objects.

Rewriting rules

The CSG tree as constructed by the user is subjected to immediate rewriting (this is performed by the union, intersect etc. functions), before any meshing function is called.

The following rewriting rules are used:

  • associative operations (union, intersect, hull, minkowski) are regrouped:
julia> display(union(union(square(1), circle(1)), polygon([])))
union
├─ Square
├─ Circle
└─ ShapeMesh # 0 polygon(s), 0 vertices
  • single-operand unions and intersects are removed:
julia> display(union(square(1)))
Square
  • symbolic complements are replaced by the appropriate values:
julia> display(intersect(square(1), ~circle(1), polygon([])))
intersection
├─ difference
│  ├─ Square
│  └─ Circle
└─ ShapeMesh # 0 polygon(s), 0 vertices
  • empty unions and intersections are removed:
julia> display(union(square(1),union(),circle(1)))
union
├─ Square
└─ Circle

Convex hull

ConstructiveGeometry.hullFunction
hull(s::AbstractGeometry...)
hull(s::AbstractGeometry | StaticVector...)

Represents the convex hull of given solids (and, possibly, individual points). Mixing dimensions (and points) is allowed.

source
julia> s = hull(cube(50), [50,0,0]+sphere(50));

example: convex hull of a sphere and a cube

In the case of mixed dimensions, two-dimensional objects are understood as included in the horizontal plane, unless they have been subjected to a three-dimensional affine transformation; in that case, this transformation is applied to their vertices. See Three-dimensional embeddings of two-dimensional objects.

Minkowski sum

ConstructiveGeometry.minkowskiFunction
minkowski(s1::AbstractGeometry, s2::AbstractGeometry)

Represents the Minkowski sum of given solids. Mixing dimensions is allowed (and returns a three-dimensional object).

source
julia> c = cube(10);

julia> s1 = minkowski(square(50), circle(20));

julia> s2 = minkowski(c, cube(20,1,1));

julia> s3 = minkowski(c, polygon([[0,0],[0,30],[30,0]]));

The Minkowski sum between a polygon and a circle of radius r is the same as the offset of the polygon by this radius: example: Minkowski sum of a square and a circle

Minkowski sum between volumes is allowed; e.g. the Minkowski sum of two axis-aligned parallelepipeds is again a parallelepiped: example: Minkowski sum of two axis-aligned cubes

Minkowski sum between a volume and a polygon is also allowed; here the polygon is a triangle in the horizontal plane: example: Minkowski sum of a cube and a polygon

Slicing and projection

Slicing and projection convert a volume to a shape. These transformations are only defined with respect to horizontal planes, since these are the only planes in which canonical (x,y) coordinates are defined.

To use another plane, say the image of the horizontal plane by a rotation R, apply the inverse rotation of R to the object to bring the situation back to the horizontal plane.

slice

ConstructiveGeometry.sliceFunction
slice(z, s...)
slice(s...)

Computes the (3d to 2d) intersection of a shape and the given horizontal plane (at z=0 if not precised).

source
julia> s = slice()*setdiff(sphere(20),sphere(18));

example: slicing a hollow sphere

project

julia> s = project()*setdiff(sphere(20),sphere(18));

example: projecting a hollow sphere

Intersection with half-space

ConstructiveGeometry.halfFunction
half(direction, s...; origin = 0)
half(direction; origin = 0) * s

Keeps only the part of objects s lying in the halfspace/halfplane with given direction and origin.

direction may be either a vector, or one of the six symbols :top, :bottom, :left, :right, :front, :back.

origin may be either a point (i.e. one point on the hyperplane) or a scalar (b in the equation a*x=b of the hyperplane).

source
julia> s = half(:bottom)*setdiff(sphere(20),sphere(18));

example: one half of a hollow sphere