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.:\SmoothMinimumSmoothUnionSmoothIntersectionSmoothSubtraction
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.7071067811881271Note: 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.