-
Notifications
You must be signed in to change notification settings - Fork 137
CSG
Geogram's CSG subsystem is implemented in
geogram/mesh/mesh_CSG.h. The main
class is the CSGBuilder. It applies
boolean operations to a set of meshes, with an API made compatible with OpenSCAD's .csg
file format. OpenSCAD is a 3D modeler with a programming language that lets you create
objects using basic primitives (spheres, boxes, ...), geometric transforms and boolean operations to
combine them. OpenSCAD supports two file formats:
-
.scad
, which is its native file format, with all the constructs of the programming language (for loops, conditional statements, functions, modules ...) -
.csg
, which is a file format with only a CSG tree (primitives, transforms and boolean operations).
Geogram's CSGBuilder follows (as closely as possible) OpenSCAD's .csg
file format. The example program
src/examples/geogram/compute_CSG has four examples ported from OpenSCAD.
The CSGBuilder
manipulates CSGMesh
es. A CSGMesh
is a geogram Mesh plus some additional information used by the CSGBuilder bookkeeping (bounding box, caching...). The type CSGMesh_var
corresponds to a smart pointer to a CSGMesh
(does memory management for you).
The C++ code to generate the first four OpenSCAD examples (see figure) is as follows. It uses curly-braces constructors for matrices, vectors and CSGScope
s (that is, a list of CSGMesh
es). The syntax is very close to OpenSCAD .csg
files (with the exception of union
that writes union_instr
in CSGBuilder
parlance, because union
is a reserved C++ keyword !).
GEO::CSGMesh_var example001() {
using namespace GEO;
CSGBuilder B;
return B.difference({
B.sphere(25.0),
B.multmatrix(
{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}},
{ B.cylinder(62.5, 12.5, 12.5) }
),
B.multmatrix(
{{1, 0, 0, 0}, {0, 0, -1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}},
{ B.cylinder(62.5, 12.5, 12.5) }
),
B.multmatrix(
{{0, 0, 1, 0}, {0, 1, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 1}},
{ B.cylinder(62.5, 12.5, 12.5) }
)
});
}
GEO::CSGMesh_var example002() {
using namespace GEO;
CSGBuilder B;
return B.intersection({
B.difference({
B.union_instr({
B.cube({30,30,30}),
B.multmatrix(
{{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, -25},
{0, 0, 0, 1}},
{B.cube({15,15,40})}
)
}),
B.union_instr({
B.cube({50,10,10}),
B.cube({10,50,10}),
B.cube({10,10,50})
}),
}),
B.multmatrix(
{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 5}, {0, 0, 0, 1}},
{ B.cylinder(50, 20, 5) }
)
});
}
GEO::CSGMesh_var example003() {
using namespace GEO;
CSGBuilder B;
return B.difference({
B.union_instr({
B.cube({30, 30, 30}),
B.cube({40, 15, 15}),
B.cube({15, 40, 15}),
B.cube({15, 15, 40})
}),
B.union_instr({
B.cube({50, 10, 10}),
B.cube({10, 50, 10}),
B.cube({10, 10, 50})
})
});
}
GEO::CSGMesh_var example004() {
using namespace GEO;
CSGBuilder B;
return B.difference({
B.cube({30,30,30}),
B.sphere(20)
});
}
To generate these meshes, one can use:
$ compute_CSG example001
(resp. example002
,example003
,example004
). This will generate the result in out.meshb
. Then, to visualize the result, use:
$ vorpaview out.meshb
To gain more speed and more robustness in the extreme cases, read about GeogramPlus.