Extending ConstructiveGeometry
The mesh
method
The main work of converting ideal objects to concrete meshes is done by the following mesh
method:
mesh(opt::MeshOptions, object, children_meshes)
This method should in principle not be directly called by the user. It is invoked by the ConstructiveGeometry
module with the following parameters:
opt
is aMeshOptions{T}
structure holding the parameters for computing the mesh (the typeT
is the coordinate type used for mesh vertices);object
is the object being meshed itself;children_meshes
is a list (vector or tuple) of meshes computed for the contents ofchildren(object)
.
This method must return a subtype of AbstractMesh{D}
, namely either a ShapeMesh
(for 2d objects) or a VolumeMesh
(for 3d objects). These types are, in turn, thin wrappers for mesh types handled by appropriate submodules (namely the exclusive union of closed polygonal loops / the volume delimited by a closed triangulated surface). These are also the types returned by the polygon()
and surface()
primitives.
Any two-dimensional object (viz. three-dimensional) object x
may be instantiated as a mesh by invoking polygon(x)
(viz. surface(x)
).
Defining a new primitive object
Defining a new primitive object has two main parts:
define a new concrete subtype of
AbstractGeometryLeaf{D}
(whereD
= 2 or 3 is the dimension of the object) holding the geometric information for the “ideal” object;implement a meshing method for this type, by extending the
ConstructiveGeometry.mesh
method; more specifically,mesh(opt::MeshOptions{T}, s::NewObjectType, _)
. (the last parameter is the list of children meshes, which will always be empty for a leaf type).
On top of this, several methods may be added as syntactic sugar to help the user define objects of this new type.
This is exactly how e.g. Cube
is defined:
struct Cube{T} <: AbstractGeometry{3}
size::SVector{3,T}
end
mesh(g::MeshOptions{T}, s::Cube, _) where{T} =
# children are not used here
# VolumeMesh is constructed from default attributes, vertices, triangles:
VolumeMesh(g, cube_vertices(T.(s.size)), cube_triangles)
Defining a new transformation
If this transformation applies to a single object, then define a new concrete subtype of
AbstractTransform{D}
with a singlechild
field: this will enable the multiplicative syntax for applying this transformation to an object;otherwise, define a new concrete subtype of
AbstractGeometry{D}
and extend thechildren
method to the new type, returning a proper list (vector, tuple etc; it must only be iterable) of the object's children.extend the
mesh
method to this type.
As in the case of leaf objects, it is also possible to add some methods to make it easier for the user to call the transformation, e.g. by using the operator()
function.
The operator()
function
This function is a shortcut to define the multiplicative syntax for an object transformation. It has two main methods:
operator(Constructor, parameters, solid)
(whereparameters
is a tuple) is the same asConstructor(parameters..., solid)
;operator(Constructor, parameters)
returns an encapsulationF
such thatF * solid
is again interpreted asConstructor(parameters..., solid)
.
For example, multiplicative syntax can be given to a transformation Frobnicate
by defining frobnicate(param1, param2, s...) = operator(Frobnicate, (param1, param2,), s...)
.