Converters
Four converters bridge Rockable’s shape format and the usual geometry formats.
They live in prepro/converters, and are built by CMake with
ROCKABLE_COMPILE_PREPRO.
stl2shape: from a triangulated mesh
Converts a binary STL mesh into a single shape, by taking the mesh as the skeleton of a sphero-polyhedron and dilating it by a Minkowski radius.
stl2shape -r 0.01 -c file.stl
The shape is written in the file mesh.shp of the current folder (an existing
mesh.shp is overwritten), and is named after the STL file, without its
folder (file.stl). The options -o and -n change both.
Option |
Description |
|---|---|
file.stl (last argument) |
Input STL file. Required, and it must be the binary flavour of STL. |
|
Minkowski radius of the resulting shape. Required. |
|
Rescale the object by a given factor. |
|
Rescale the object so that its largest dimension, its sieving size, takes the given value. |
|
Rescale the radius along with the object, instead of keeping it as given. |
|
Remove the duplicated edges. |
|
Name of the shape. By default, the name of the STL file, without its folder. |
|
Name of the shape file written, |
Important
Use -c almost always. An STL file stores each triangle independently, so
every edge appears twice and every vertex several times. Without cleaning,
the shape carries duplicated sub-elements, which costs time at every contact
detection and can produce forces counted twice.
Warning
The cost of a shape grows with its number of vertices, edges and faces, and
so does the cost of the contact detection. A mesh exported at full resolution
from a CAD tool or a scanner easily has thousands of triangles, which is far
more than a discrete element simulation needs. Decimate the mesh before
converting, and consider AddOrRemoveInteractions OBBtree for the complex
shapes that remain.
The converted shape has preCompDone n: run shapeSurvey on it to compute
its mass properties and save them (see Application shapeSurvey).
tess2shape: from a Neper tessellation
Converts a Neper tessellation into a shape library and the matching particle list. This is the usual route to a sample of space-filling grains, of the kind used for the bonded models.
tess2shape command.txt
The cells are shrunk by the Minkowski radius (each face moves inwards by the
radius), so that two neighbouring cells touch without overlapping, and can be
glued by stickBCM. The mass properties of each cell are computed by a
Monte-Carlo integration of MCnstep points: most of the time of the
conversion, about 30 s for 1000 cells with 20000.
Note
tif2rockable, in the same folder, is still not built by CMake (its
line is commented out in prepro/converters/CMakeLists.txt).
The command file is a list of keywords:
tessFileName tessel.tess
inputFileName input.txt
shapesFileName shapes.txt
MinkowskiRadius 0.01
ParticlesGroup 0
ParticlesCluster 0
ParticlesHomothety 1.0
MCnstep 50000
Keyword |
Description |
|---|---|
|
The |
|
Conf-file to write, holding the particle list. |
|
Shape library to write, one shape per cell of the tessellation. |
|
Radius given to every generated shape. |
|
Group, cluster and homothety given to every generated particle. |
|
Number of Monte-Carlo samples used for the mass properties. |
Warning
The keyword is MinkowskiRadius. Older command files may spell it
MinskowskiRadius, which is not recognised: the line is ignored and
the radius silently keeps its default value.
Generating the tessellation itself is a Neper matter:
neper -T -n 100 -domain "cube(1,1,1)" -o tessel
Neper places its domain at the origin; -transform "translate(x,y,z)" moves
it, for instance to surround a shape that will be used as a cookie cutter
(see examples/bunnyFun/voronoiBunny).
Warning
Neper 5.0.1 crashes with a domain read from a file,
-domain "file(shape.obj)", even for a cube: a non-convex domain cannot
be tessellated directly. The tutorial voronoiBunny tessellates a box,
and keeps the cells whose centre is inside the shape.
Tip
Neper is built from its sources (https://github.com/neperfepx/neper),
with gsl and nlopt. With GCC 16, which compiles C in C23 by default,
the library Scotch that Neper includes needs
-DCMAKE_C_FLAGS="-std=gnu17 -Wno-incompatible-pointer-types".
Tip
Giving every particle the same cluster makes all the bonds inner, which
is what a single fragmenting solid needs. Distinct clusters make them
outer, for an assembly of separate grains. See Pre-processing commands.
stl2blocks: a mesh cut into blocks
Cuts a closed STL mesh (binary or ascii) into blocks along families of parallel
planes, and writes the blocks as a shape library and the matching particle
list, ready to be glued by stickBCM.
stl2blocks command.txt
The cuts form a tree. The whole mesh (the block root) is cut along one
direction into slabs, numbered 0, 1, … along that direction; each slab
can then be cut along its own direction, with its own spacing of the planes,
and so on. A block that is not cut any more is a final block (or several, when
the planes leave several separate parts of the mesh in it).
The Minkowski radius R is given first, and the blocks are built so that,
once rounded by R, they fill the mesh and touch each other:
the faces of the mesh are moved inwards by
R(the core of the mesh);each cutting plane removes a slice of thickness
2R: the faces of the two blocks on either side of it are2Rapart.
stlFile ../bunny.stl
homothety 2
translation 0 0.0515 0
MinkowskiRadius 0.001
cut root 1 0 0 spacing 0.02 0
cut root.* 0 1 0.3 spacing 0.02 0.005
cut root.*.* 0.2 -0.3 1 number 5
cut root.3.* 1 1 1 random 2 3
shapesFile blocks.shp
inputFile blocks.txt
ParticlesGroup 1
ParticlesCluster 1
MCnstep 10000
A line cut <path> <direction> <planes> cuts the blocks whose path matches
<path>: root, root.2 (the slab 2 of root), root.2.0… A
* matches any slab number; when several lines match a block, the one with
the fewest * is used (the last one, if they have as many). Above,
root.3.* is cut along 1 1 1, and the other slabs of the second level
along 0.2 -0.3 1. The direction need not be normalised. The planes are placed
in one of five ways, along the direction (a position p is the plane
x.u = p, u being the normalised direction):
Planes |
Description |
|---|---|
|
|
|
The planes |
|
|
|
|
|
|
Only the planes inside the block are used. The program prints the tree of cuts, with the slabs kept (a slab with no part of the mesh is not kept, but the numbers of the other slabs do not change), then one line per final block: its name, its path, its number of vertices and faces, its volume.
Keyword |
Description |
|---|---|
|
The STL file, binary or ascii. |
|
Applied to the mesh before the cuts (and before |
|
Radius of all the blocks (required). |
|
A cut (see above), one line per rule. |
|
The shape library and the conf-file (the line |
|
The blocks are named |
|
Group and cluster of all the particles ( |
|
Number of Monte-Carlo points for the mass properties of each block
( |
|
The parts whose core is smaller than this volume are removed ( |
|
|
The vertices for the glue. stickBCM bonds the vertices of two blocks
that face each other, 2R apart. Two blocks on either side of a plane are
cut by different later planes, and their vertices do not face each other: a
cubic grid of cuts gives four bonds per interface, an oblique tree of cuts
often one or two, and an interface with fewer than three bonds has no area
(it breaks at once). So the program adds to both blocks the corners of the
part of the plane they share: the vertices of each one that face the other
block, and the points where their sides cross. These vertices are in the faces
of the blocks, and do not change their shapes. The program also prints the area
of the faces of the cuts, to be compared with the area given by stickBCM.
Repair of the mesh. The mesh is checked first: the triangles stuck on the
mesh by a single side (a fin) are removed, the triangles are oriented
outwards, and the holes are closed by fans of triangles. The Stanford bunny of
examples/bunnyFun has one fin.
Warning
The parts of the mesh thinner than 2R cannot be represented. Moving the
faces inwards by R is done node by node: on triangles smaller than
R, the nodes are moved less, so that no triangle is turned over (the
program says how many); the core may then cross itself, and a face of a cut
have a crossed outline (the program says so too). Choose R small
compared with the details of the mesh, and with the spacing of the planes:
a slab thinner than 2R disappears, and a block whose slabs are all
thinner than 2R is not cut.
Tip
Two parts of a block closer than 2R to each other (a thin neck of the
mesh, cut by the planes) would overlap once rounded: they are kept together,
in one block. Small blocks need a small time step: the program gives the
smallest one. For the bunny of examples/bunnyFun (homothety 2) cut as
above, dt 2e-7 is stable, 1e-6 is not. Even so, 29 of its 780
interfaces (those with fewer than three bonds, where two blocks touch only
along a sliver) break at the first step.
The program works on a copy of polyhTool.hpp of toofus (in its folder),
extended to polyhedra that are not convex: the cut by a plane gives faces with
several loops, holes, and concave outlines, triangulated by ear clipping.
shape2mesh: from a shape to a surface mesh
The reverse direction: meshes the exact surface of a sphero-polyhedron, that is the Minkowski sum of the skeleton with a ball. Rounded edges, corners, concavities and open surfaces are all handled, and the vertex normals are the analytic normals of the surface, so even a coarse mesh shades correctly.
shape2mesh shapes.txt --rmsh
Option |
Description |
|---|---|
|
Output format, |
|
Absolute sag tolerance, in the length unit of the shape file. Smaller means finer; the grid step follows \(h \sim \sqrt{8 \epsilon R}\). The default is 1% of the radius. |
|
Merge the coplanar triangles, with a default tolerance of 0.25 degree, and re-triangulate the flat regions from their boundary only. |
|
Write a single |
|
Output directory. |
The mesh is expressed in the body frame of the shape, the frame stored in the shape file.
The method (exact signed distance, choice of the grid step, coplanar merge), its validation and its limits are described in a technical note, see Watertight skin meshes of three-dimensional R-shapes.
The .rmsh companion
With -r, all the shapes of a library are meshed into one .rmsh file.
When that file sits next to the shape file, see draws each particle with its
skin mesh instead of the overlapping spheres, tubes and slabs it normally uses.
The difference is purely visual, but on a rounded polyhedron it is the
difference between a figure that reads and one that does not.
Note
The mesh is built in the body frame of the shape: its mass centre and its
principal axes, where Rockable and see put a shape when they read it.
A shape still marked preCompDone n, such as the output of
stl2shape, is first pre-computed by shape2mesh (it says so, and it
takes the time of a Monte-Carlo integration). The shape file itself is not
modified: pre-compute it once with shapeSurvey shapes.shp -P shapes.shp
(see Application shapeSurvey) to save that time, here and at each start of a
computation.
The skin mesh cannot follow the deformation of a soft particle (see Deformable particles (DCEM)): the soft particles are always drawn with the overlapping primitives, deformed.
shape2mesh shapes.txt --rmsh # -> shapes.rmsh
shape2mesh shapes.txt --rmsh -s # smaller, flat faces merged
Without an explicit -e, the sag is chosen per shape, at 0.4% of its
bounding-box diagonal, so a large flat wall and a small detailed grain both get
a sensible mesh.
Note
The simplification is safe on the flat parts: the offset faces of a sphero-polyhedron are exact planes, so merging their triangles does not change the surface, and the mesh stays watertight. The curved regions, the rounded edges and corners, are left untouched. On a rounded polyhedron the triangle count typically drops by about 60%; on a sphere, nothing changes.