ImplicitGeometries.jl
This package enables construction of implicit geometries by composition of primitive shapes described by signed distance functions. It supports evaluation of gradients and normals of such implicit representations.
To represent the construction tree structure, parts of the AbstractTrees.jl interface are implemented.
The articles by Inigo Quilez are a great resource about implicit geometry representations via signed distance functions. This package uses ideas presented in these articles.
ImplicitGeometries.SDF
— Typeabstract type SDF{Dim,T}
A signed distance function (SDF) represents a geometry implicitly by giving the signed distance from any point in space to the surface of the geometry.
For a region Ω in ℝⁿ with boundary ∂Ω, the signed distance function ϕ(x) returns:
- a negative value if x is inside Ω,
- zero if x lies on the boundary ∂Ω,
- a positive value if x is outside Ω.
Strictly speaking, the value of ϕ(x) is equal to the shortest (Euclidean) distance to the boundary ∂Ω, with a sign that indicates whether the point is inside or outside the region Ω.
Note, that not all operations implemented in ImplicitGeometries.jl
return a true signed distance function. The (Euclidean) distance property is not always preserved.
All data types subtyping SDF
are intended to act as functors. They are callable with a single argument of type SVector{Dim,T}
where Dim
is the dimension of the domain and T
is the used number type.
Shapes
Types subtyping Shape
serve as building blocks for construction of more complex geometries. These are typically true signed distance functions, i.e. they return the minimal Euclidean distance to the shape boundary.
The following primitive shapes are currently implemented:
ImplicitGeometries.Shape
— Typeabstract type Shape{Dim,T} <: SDF{Dim,T}
Signed distance functions describing primitive shapes subtype this.
ImplicitGeometries.Rectangle
— Typestruct Rectangle{T} <: Shape{2,T}
Signed distance function representing a rectangle.
ImplicitGeometries.Rectangle
— MethodRectangle(; w::T = 1.0, h::T = 1.0) where {T<:Real}
Initialize Rectangle
of width w
and height h
.
ImplicitGeometries.Circle
— Typestruct Circle{T} <: Shape{2,T}
Signed distance function representing a circle.
ImplicitGeometries.Circle
— MethodCircle(; r::T = 1.0) where {T<:Real}
Initialize Circle
with radius r
.
ImplicitGeometries.Box
— Typestruct Box{T} <: Shape{3,T}
Signed distance function representing a box.
ImplicitGeometries.Box
— MethodBox(; w::T = 1.0, h::T = 1.0, d::T = 1.0) where {T<:Real}
Initialize Box
of width w
, height h
and depth d
.
ImplicitGeometries.Sphere
— Typestruct Sphere{T} <: Shape{3,T}
Signed distance function representing a sphere.
ImplicitGeometries.Sphere
— MethodSphere(; r::T = 1.0) where {T<:Real}
Initialize Sphere
with radius r
.
ImplicitGeometries.Cylinder
— Typestruct Cylinder{T} <: Shape{3,T}
Signed distance function representing a cylinder.
ImplicitGeometries.Cylinder
— MethodCylinder(; r::T = 1.0) where {T<:Real}
Initialize Cylinder
with radius r
and height h
.
ImplicitGeometries.QuadraticBezierSegment
— Typestruct QuadraticBezierSegment{T} <: Shape{2,T}
Signed distance function defined by a quadratic Bezier segment.
ImplicitGeometries.QuadraticBezierSegment
— MethodQuadraticBezierSegment(; A::SVector{2,T}, B::SVector{2,T}, C::SVector{2,T}) where {T<:Real}
Initialize QuadraticBezierSegment
with control points A
, B
and C
.
ImplicitGeometries.QuadraticBezier
— Typestruct QuadraticBezier{T} <: Shape{2,T}
Signed distance function defined by a quadratic Bezier curve.
ImplicitGeometries.QuadraticBezier
— MethodQuadraticBezier(; v::Vector{SVector{2,T}}) where {T<:Real}
Initialize QuadraticBezier
. The control points for all Bezier segments are collected in the vector v
. Typically, the first and the last control point will coincide. The orientation of each segment must be consistent.
ImplicitGeometries.Polygon
— Typestruct Polygon{T} <: Shape{2,T}
Signed distance function representing a polygon.
ImplicitGeometries.Polygon
— MethodPolygon(; v::Vector{SVector{2,T}}) where {T<:Real}
Initialize Polygon
through points v
.
Operations
Types subtyping Operation
are compositions of two or more signed distance functions. Not all operations are described by a true signed distance function.
The following operations are currently implemented:
BooleanUnion
,Base.:∪
BooleanIntersection
,Base.:∩
BooleanSubtraction
,Base.:-
BooleanDifference
,Base.:\
SmoothMinimum
SmoothUnion
SmoothIntersection
SmoothSubtraction
ImplicitGeometries.Operation
— Typeabstract type Operation{Dim,T} <: SDF{Dim,T}
Operations on two or more signed distance functions subtype this.
ImplicitGeometries.BooleanOperation
— Typeabstract type BooleanOperation{Dim,T} <: Operation{Dim,T}
Boolean operations subtype this.
ImplicitGeometries.BooleanUnion
— Typestruct BooleanUnion{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Boolean union of two signed distance functions.
ImplicitGeometries.BooleanUnion
— MethodBooleanUnion(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean union of shape1
and shape2
.
Base.:∪
— FunctionBase.:∪(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean union of shape1
and shape2
.
ImplicitGeometries.BooleanIntersection
— Typestruct BooleanIntersection{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Boolean intersection of two signed distance functions.
ImplicitGeometries.BooleanIntersection
— MethodBooleanIntersection(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean intersection of shape1
and shape2
.
Base.:∩
— FunctionBase.:∩(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean intersection of shape1
and shape2
.
ImplicitGeometries.BooleanSubtraction
— Typestruct BooleanSubtraction{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Boolean subtraction of two signed distance functions.
ImplicitGeometries.BooleanSubtraction
— MethodBooleanSubtraction(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean subtraction of shape1
and shape2
.
Base.:-
— FunctionBase.:-(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean subtraction of shape1
and shape2
.
ImplicitGeometries.BooleanDifference
— Typestruct BooleanDifference{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Boolean difference of two signed distance functions.
ImplicitGeometries.BooleanDifference
— MethodBooleanDifference(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean difference of shape1
and shape2
.
Base.:\
— FunctionBase.:\(shape1::S1, shape2::S2) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing boolean difference of shape1
and shape2
.
ImplicitGeometries.SmoothMinimum
— Typestruct SmoothMinimum{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Smooth minimum of two signed distance functions.
ImplicitGeometries.SmoothMinimum
— MethodSmoothMinimum(shape1::S1, shape2::S2; k::T = 0.1) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing smooth minimum of shape1
and shape2
. The parameter k
control the smoothness.
ImplicitGeometries.SmoothUnion
— Typestruct SmoothUnion{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Smooth union of two signed distance functions.
ImplicitGeometries.SmoothUnion
— MethodSmoothUnion(shape1::S1, shape2::S2; k::T = 0.1) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing smooth union of shape1
and shape2
. The parameter k
controls the smoothness.
ImplicitGeometries.SmoothIntersection
— Typestruct SmoothIntersection{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Smooth intersection of two signed distance functions.
ImplicitGeometries.SmoothIntersection
— MethodSmoothIntersection(shape1::S1, shape2::S2; k::T = 0.1) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing smooth intersection of shape1
and shape2
. The parameter k
controls the smoothness.
ImplicitGeometries.SmoothSubtraction
— Typestruct SmoothSubtraction{Dim,T,S1,S2} <: BooleanOperation{Dim,T}
Smooth subtraction of two signed distance functions.
ImplicitGeometries.SmoothSubtraction
— MethodSmoothSubtraction(shape1::S1, shape2::S2; k::T = 0.1) where {Dim,T,S1<:SDF{Dim,T},S2<:SDF{Dim,T}}
Initialize signed distance function representing smooth subtraction of shape1
and shape2
. The parameter k
controls the smoothness.
Transformations
Types subtyping Transformation
operate on a single signed distance function. Most transformations are described by a true signed distance function.
The following transformations are currently implemented:
ImplicitGeometries.Transformation
— Typeabstract type Transformation{Dim,T} <: SDF{Dim,T}
Transformations of a signed distance function subtype this.
ImplicitGeometries.Translation
— Typestruct Translation{Dim,T,S} <: Transformation{Dim,T}
Translated signed distance function.
ImplicitGeometries.Translation
— MethodTranslation(shape::S; dx::T = 0.0, dy::T = 0.0) where {T,S<:SDF{2,T}}
Initialize Translation
from shape
. Parameters dx
and dy
control the translation amount in x
and y
direction.
Translation(shape::S; dx::T = 0.0, dy::T = 0.0, dz::T = 0.0) where {T,S<:SDF{3,T}}
Initialize Translation
from shape
. Parameters dx
, dy
and dz
control the translation amount in x
, y
and z
direction.
ImplicitGeometries.Rotation
— Typestruct Rotation{Dim,T,S} <: Transformation{Dim,T}
Rotated signed distance function.
ImplicitGeometries.Rotation
— MethodRotation(shape::S; θ::T = 0.0, dx::T = 0.0, dy::T = 0.0) where {T,S<:SDF{2,T}}
Initialize Rotation
from shape
rotated by angle θ
. The parameters dx
and dy
control the center of rotation.
Rotation(shape::S; ϕ::T = 0.0, θ::T = 0.0, ψ::T = 0.0, dx::T = 0.0, dy::T = 0.0, dz::T = 0.0) where {T,S<:SDF{3,T}}
Initialize Rotation
from shape
. The parameters ϕ
, θ
and ψ
are rotation angles around the first, second and third axis. The parameters dx
, dy
and dz
control the center of rotation.
ImplicitGeometries.Onion
— Typestruct Onion{Dim,T,S} <: Transformation{Dim,T}
Onion of a signed distance function.
ImplicitGeometries.Onion
— MethodOnion(shape::S; r::T = 0.0) where {T,S<:SDF{2,T}}
Initialize Onion
from shape
. Parameter r
controls the thickness.
ImplicitGeometries.Ring
— Typestruct Ring{Dim,T,S} <: Transformation{Dim,T}
Ring of a signed distance function.
ImplicitGeometries.Ring
— MethodRing(shape::S; r::T = 0.0) where {T,S<:SDF{2,T}}
Initialize Ring
from shape
. Parameter r
controls the offset.
ImplicitGeometries.Scaling
— Typestruct Scaling{Dim,T,S} <: Transformation{Dim,T}
Scaling of a signed distance function.
ImplicitGeometries.Scaling
— MethodScaling(shape::S; s::T = 1.0) where {T,S<:SDF{2,T}}
Initialize Scaling
from shape
. Parameter s
controls the scale.
ImplicitGeometries.Elongation
— Typestruct Elongation{Dim,T,S} <: Transformation{Dim,T}
Elongation of a signed distance function.
ImplicitGeometries.Elongation
— MethodElongation(op::S; dx::T = 0.0, dy::T = 0.0, dz::T = 0.0) where {T,S<:SDF{3,T}}
Initialize Elongation
from three dimensional shape
. Parameters dx
, dy
, dz
the amount of elongation in x
, y
and z
.
ImplicitGeometries.Revolution
— Typestruct Revolution{T,S} <: Transformation{3,T}
Revolution of a two dimensional signed distance function around the origin.
ImplicitGeometries.Revolution
— MethodRevolution(op::S; o::T = 1.0) where {T,S<:SDF{2,T}}
Initialize Revolution
from two dimensional shape
. Parameter o
controls the radius of the revolution.
ImplicitGeometries.Extrusion
— Typestruct Extrusion{T,S} <: Transformation{3,T}
Extrusion of a two dimensional signed distance function around the origin.
ImplicitGeometries.Extrusion
— MethodExtrusion(op::S; h::T = 1.0) where {T,S<:SDF{2,T}}
Initialize Extrusion
from two dimensional shape
. Parameter h
controls the height of the extrusion.
ImplicitGeometries.BooleanNegative
— Typestruct BooleanNegative{Dim,T,S} <: Transformation{Dim,T}
Boolean negative of a signed distance function.
ImplicitGeometries.BooleanNegative
— MethodBooleanNegative(op::S) where {T,S<:SDF{2,T}}
Initialize BooleanNegative
from op
.
ImplicitGeometries.:¬
— Function¬(shape::S) where {Dim,T,S<:SDF{Dim,T}}
Initialize BooleanNegative
from shape
.
Gradients
ImplicitGeometries.jl
supports evaluation of gradients of signed distance functions. Currently, the gradients in two dimensions are approximated by second order finite differences with a 4-point cross stencil. The gradients in three dimensions are approximated by first order finite differences with a 4-point tetrahedron stencil. The Gradient
is a functor similar to SDF
. It can be evaluated a some position p
.
ImplicitGeometries.Gradient
— Typestruct Gradient{Dim,T,S<:SDF{Dim,T}}
Gradient of a signed distance function.
ImplicitGeometries.Gradient
— MethodGradient(shape::S; h::T = 1e-4) where {Dim,T,S<:SDF{Dim,T}}
Initialize Gradient
for a signed distance function shape
. The parameter h
controls the width of the finite difference stencil.
Automatic differentiation can also be used to evaluate gradients of signed distance functions and, depending on the application, might also be preferable to the finite differencing used in Gradient
. In the following example we use Zygote.jl
to evaluate the gradient using automatic differentiation.
julia> using Zygote, StaticArrays
julia> geometry = Ring(Rectangle() - Circle(; r=0.25); r=0.1);
julia> print_tree(geometry)
Ring (r = 0.1)
└─ BooleanSubtraction
├─ Rectangle (w = 1.0, h = 1.0)
└─ Circle (r = 0.25)
julia> Zygote.gradient(geometry, p)[1]
2-element SVector{2, Float64} with indices SOneTo(2):
0.7071067811865476
0.7071067811865476
julia> Gradient(geometry)(p)
2-element SVector{2, Float64} with indices SOneTo(2):
0.7071067811870169
0.7071067811881271
Note: ForwardDiff.jl
seems to struggle with some signed distance functions.
Normals
A normal on the boundary of a region described by a constant levelset of a signed distance function is nothing more than the normalized Gradient
evaluated on that boundary. The same approximations as in Gradient
are used here.
ImplicitGeometries.Normal
— Typestruct Normal{Dim,T,S<:SDF{Dim,T}}
Vector field of normals of a signed distance function.
ImplicitGeometries.Normal
— MethodNormal(shape::S; h::T = 1e-4) where {Dim,T,S<:SDF{Dim,T}}
Initialize Normal
for a signed distance function shape
. The parameter h
controls the width of the finite difference stencil.