40#ifndef H_GEO_MESH_CSG_BUILDER_H
41#define H_GEO_MESH_CSG_BUILDER_H
44#include <geogram/mesh/mesh_CSG_utils.h>
68 static constexpr double DEFAULT_FA = 12.0;
71 static constexpr double DEFAULT_FS = 2.0;
74 static constexpr double DEFAULT_FN = 0.0;
103 fn_ = std::max(fn, 0.0);
113 fs_ = std::max(fs,0.01);
123 fa_ = std::max(fa,0.01);
144 detailed_verbose_ = x;
145 if(detailed_verbose_ && !verbose_) {
167 file_path_.push_back(path);
176 file_path_.push_back(std::filesystem::current_path());
186 file_path_.push_back(path);
194 file_path_.pop_back();
199 virtual void add_object(
200 const std::string&
object,
const ArgList& args
203 virtual void begin_instruction();
205 virtual void end_instruction(
206 const std::string& instruction,
const ArgList& args
210 bool is_object(
const std::string&
id)
const {
211 return (object_funcs_.find(
id) != object_funcs_.end());
214 bool is_instruction(
const std::string&
id)
const {
215 return (instruction_funcs_.find(
id) != instruction_funcs_.end());
222 virtual void add_square(
const ArgList& args);
223 virtual void add_circle(
const ArgList& args);
224 virtual void add_cube(
const ArgList& args);
225 virtual void add_sphere(
const ArgList& args);
226 virtual void add_cylinder(
const ArgList& args);
227 virtual void add_polyhedron(
const ArgList& args);
228 virtual void add_polygon(
const ArgList& args);
229 virtual void add_import(
const ArgList& args);
230 virtual void add_surface(
const ArgList& args);
231 virtual void add_text(
const ArgList& args);
235 virtual void eval_multmatrix(
const ArgList& args);
236 virtual void eval_translate(
const ArgList& args);
237 virtual void eval_rotate(
const ArgList& args);
238 virtual void eval_scale(
const ArgList& args);
239 virtual void eval_resize(
const ArgList& args);
240 virtual void eval_union(
const ArgList& args);
241 virtual void eval_intersection(
const ArgList& args);
242 virtual void eval_difference(
const ArgList& args);
243 virtual void eval_group(
const ArgList& args);
244 virtual void eval_color(
const ArgList& args);
245 virtual void eval_hull(
const ArgList& args);
246 virtual void eval_linear_extrude(
const ArgList& args);
247 virtual void eval_rotate_extrude(
const ArgList& args);
248 virtual void eval_projection(
const ArgList& args);
249 virtual void eval_minkowski(
const ArgList& args);
250 virtual void eval_render(
const ArgList& args);
254 [[noreturn]]
void error(
const char* str) {
255 throw(std::logic_error(str));
258 [[noreturn]]
void error(
const std::string& str) {
259 throw(std::logic_error(str.c_str()));
266 std::vector<std::filesystem::path> file_path_;
269 bool detailed_verbose_;
271 typedef std::function<void(
const ArgList& args)> csg_builder_func;
272 std::map<std::string, csg_builder_func> object_funcs_;
273 std::map<std::string, csg_builder_func> instruction_funcs_;
304 const std::initializer_list<std::shared_ptr<Mesh>>& Ms
308 void push_back(std::shared_ptr<Mesh> M) {
309 meshes_.push_back(M);
312 void emplace_back(std::shared_ptr<Mesh> M) {
313 meshes_.emplace_back(M);
321 return index_t(meshes_.size());
324 const std::shared_ptr<Mesh>& operator[](
index_t i)
const {
329 auto begin() {
return meshes_.begin(); }
330 auto end() {
return meshes_.end(); }
331 auto begin()
const {
return meshes_.begin(); }
332 auto end()
const {
return meshes_.end(); }
333 auto rbegin() {
return meshes_.rbegin(); }
334 auto rend() {
return meshes_.rend(); }
335 auto rbegin()
const {
return meshes_.rbegin(); }
336 auto rend()
const {
return meshes_.rend(); }
338 void append(std::shared_ptr<Mesh> M) {
342 template <
typename...Types>
void append(
343 std::shared_ptr<Mesh> head, Types... tail
350 std::vector<std::shared_ptr<Mesh>> meshes_;
365 virtual std::shared_ptr<Mesh> square(
vec2 size,
bool center=
false);
367 std::shared_ptr<Mesh> square(
double size=1.0,
bool center=
false) {
368 return square(
vec2(size,size), center);
377 virtual std::shared_ptr<Mesh> cube(
vec3 size,
bool center=
false);
379 std::shared_ptr<Mesh> cube(
double size=1.0,
bool center=
false) {
380 return cube(
vec3(size,size,size), center);
383 virtual std::shared_ptr<Mesh> sphere(
double r=1.0);
385 virtual std::shared_ptr<Mesh> cylinder(
386 double h,
double r1,
double r2,
bool center=
false
389 virtual std::shared_ptr<Mesh>
import(
390 const std::filesystem::path& filename,
const std::string& layer=
"",
395 virtual std::shared_ptr<Mesh> surface(
396 const std::filesystem::path& filename,
bool center,
bool invert
399 virtual std::shared_ptr<Mesh> text(
400 const std::string& text,
402 const std::string& font =
"",
403 const std::string& halign =
"left",
404 const std::string& valign =
"baseline",
405 double spacing = 1.0,
406 const std::string& direction =
"ltr",
407 const std::string& language =
"en",
408 const std::string& script =
"latin"
442 template <
typename...Types> std::shared_ptr<Mesh>
union_instr(Types...args) {
444 scope.append(args...);
445 return union_instr(scope);
462 template <
typename...Types> std::shared_ptr<Mesh>
465 scope.append(args...);
466 return intersection(scope);
486 template <
typename...Types> std::shared_ptr<Mesh>
489 scope.append(args...);
490 return difference(scope);
542 const CSGScope& scope,
double angle = 360.0
567 void add_object(
const std::string&
object,
const ArgList& args)
override;
568 void begin_instruction()
override;
569 void end_instruction(
570 const std::string& instruction,
const ArgList& args
575 void add_square(
const ArgList& args)
override;
576 void add_circle(
const ArgList& args)
override;
577 void add_cube(
const ArgList& args)
override;
578 void add_sphere(
const ArgList& args)
override;
579 void add_cylinder(
const ArgList& args)
override;
580 void add_polyhedron(
const ArgList& args)
override;
581 void add_polygon(
const ArgList& args)
override;
582 void add_import(
const ArgList& args)
override;
583 void add_surface(
const ArgList& args)
override;
584 void add_text(
const ArgList& args)
override;
588 void eval_multmatrix(
const ArgList& args)
override;
589 void eval_translate(
const ArgList& args)
override;
590 void eval_rotate(
const ArgList& args)
override;
591 void eval_scale(
const ArgList& args)
override;
592 void eval_resize(
const ArgList& args)
override;
593 void eval_union(
const ArgList& args)
override;
594 void eval_intersection(
const ArgList& args)
override;
595 void eval_difference(
const ArgList& args)
override;
596 void eval_group(
const ArgList& args)
override;
597 void eval_color(
const ArgList& args)
override;
598 void eval_hull(
const ArgList& args)
override;
599 void eval_linear_extrude(
const ArgList& args)
override;
600 void eval_rotate_extrude(
const ArgList& args)
override;
601 void eval_projection(
const ArgList& args)
override;
602 void eval_minkowski(
const ArgList& args)
override;
603 void eval_render(
const ArgList& args)
override;
613 return mat4{{1, 0, 0, T.x},
625 return mat4{{sx, 0, 0, 0},
638 if(axis.x == 0.0 && axis.y == 0.0 && axis.z == 0.0) {
641 vec3 N = normalize(axis);
645 angle = angle *
M_PI / 180;
646 double s = sin(angle);
647 double c = cos(angle);
649 return mat4{{t*x*x + c, t*x*y - s*z, t*x*z + s*y, 0.0},
650 {t*x*y + s*z, t*y*y + c, t*y*z - s*x, 0.0},
651 {t*x*z - s*y, t*y*z + s*x, t*z*z + c, 0.0},
652 {0.0, 0.0, 0.0, 1.0}};
661 double a = angles[0] *
M_PI / 180.0;
662 double b = angles[1] *
M_PI / 180.0;
663 double c = angles[2] *
M_PI / 180.0;
664 double sa = sin(a);
double ca = cos(a);
665 double sb = sin(b);
double cb = cos(b);
666 double sc = sin(c);
double cc = cos(c);
667 return mat4{{cc*cb, cc*sb*sa - sc*ca, cc*sb*ca + sc*sa, 0.0},
668 {sc*cb, sc*sb*sa + cc*ca, sc*sb*ca - cc*sa, 0.0},
669 { -sb, cb*sa, cb*ca, 0.0},
670 { 0.0, 0.0, 0.0, 1.0}};
681 return multmatrix(translation_matrix(T),scope);
692 return multmatrix(rotation_matrix(angle),scope);
708 return multmatrix(rotation_matrix(angle,axis),scope);
719 return multmatrix(rotation_matrix(angles),scope);
730 double sx,
double sy,
double sz,
const CSGScope& scope
732 return multmatrix(scaling_matrix(sx,sy,sz),scope);
753 detect_intersecting_neighbors_ = x;
766 simplify_coplanar_facets_ = x;
767 coplanar_angle_tolerance_ = angle_tolerance;
811 const std::shared_ptr<Mesh>& mesh
814 return std::make_pair(
vec3(result.xyz_min),
vec3(result.xyz_max));
819 std::shared_ptr<Mesh> surface_with_OpenSCAD(
820 const std::filesystem::path& filename,
bool center,
bool invert
823 std::shared_ptr<Mesh> text_with_OpenSCAD(
824 const std::string& text,
826 const std::string& font =
"",
827 const std::string& halign =
"left",
828 const std::string& valign =
"baseline",
829 double spacing = 1.0,
830 const std::string& direction =
"ltr",
831 const std::string& language =
"en",
832 const std::string& script =
"latin"
852 return *(file_path_.rbegin());
861 const std::filesystem::path& filename,
const std::string& layer=
"",
881 std::shared_ptr<Mesh>& mesh,
const std::string& boolean_expr
908 std::shared_ptr<Mesh>& mesh,
const std::string& boolean_expr
935 return scope_stack_.top();
939 scope_stack_.emplace();
950 bool detect_intersecting_neighbors_;
952 bool simplify_coplanar_facets_;
953 double coplanar_angle_tolerance_;
956 std::shared_ptr<Mesh> empty_mesh_;
957 std::shared_ptr<Mesh> result_;
958 std::stack<CSGScope> scope_stack_;
960 friend class CSGCompiler;
#define geo_assert(x)
Verifies that a condition is met.
#define geo_debug_assert(x)
Verifies that a condition is met.
A parsed argument list in a .csg file.
Base class for implementing CSG objects and instructions.
AbstractCSGBuilder()
AbstractCSGBuilder constructor.
void set_detailed_verbose(bool x)
Displays (even more) additional information.
void reset_defaults()
Resets defaults value for fn, fs, fa.
void reset_file_path()
Resets the file path to its default value, with only the current directory ".".
bool verbose() const
Tests wheter verbose mode is set.
void set_verbose(bool x)
Displays (lots of) additional information.
void set_fa(double fa)
Sets the minimum angle for a fragment.
void push_file_path(const std::filesystem::path &path)
Adds a path to the file path.
void set_fn(double fn)
Sets the number of fragments.
void pop_file_path()
Removes the latest pushed file path.
virtual ~AbstractCSGBuilder()
AbstractCSGBuilder destructor.
void set_fs(double fs)
Sets the minimum size for a fragment.
void add_file_path(const std::filesystem::path &path)
Adds a path to the file path.
Axis-aligned bounding box.
Implements CSG objects and instructions.
std::shared_ptr< Mesh > rotate(double angle, const vec3 &axis, const CSGScope &scope)
Commodity function for rotating a CSGScope using OpenSCAD syntax.
static mat4 scaling_matrix(double sx, double sy, double sz)
Builds a scaling matrix.
void set_delaunay(bool x)
If set, compute constrained Delaunay triangulation in the intersected triangles. If there are interse...
virtual std::shared_ptr< Mesh > rotate_extrude(const CSGScope &scope, double angle=360.0)
Computes a 3D extrusion from a 2D shape.
std::shared_ptr< Mesh > import_with_openSCAD(const std::filesystem::path &filename, const std::string &layer="", index_t timestamp=0)
For the file formats that are not supported by geogram, get help from OpenSCAD to convert them.
std::shared_ptr< Mesh > union_instr(Types...args)
Computes the union of two or more meshes.
virtual void do_CSG(std::shared_ptr< Mesh > &mesh, const std::string &boolean_expr)
Apply a CSG operation to a mesh.
virtual std::shared_ptr< Mesh > intersection(const CSGScope &scope)
Computes the intersection between two or more meshes.
virtual std::shared_ptr< Mesh > projection(const CSGScope &scope, bool cut)
Creates a 2D mesh from 3D mesh.
bool find_file(std::filesystem::path &filename)
Finds a file in the path.
virtual std::shared_ptr< Mesh > union_instr(const CSGScope &scope)
Computes the union of two or more meshes.
virtual void triangulate(std::shared_ptr< Mesh > &mesh)
Triangulates a 2D mesh.
static mat4 translation_matrix(const vec3 &T)
Builds a translation matrix.
std::shared_ptr< Mesh > scale(double sx, double sy, double sz, const CSGScope &scope)
Commodity function for scaling a CSGScope using OpenSCAD syntax.
void set_fast_union(bool x)
Sets fast union mode.
static mat4 rotation_matrix(const vec3 &angles)
Builds a rotation matrix.
static Box3d get_bbox(const std::shared_ptr< Mesh > &mesh)
Computes the bounding box of a mesh.
virtual std::shared_ptr< Mesh > linear_extrude(const CSGScope &scope, double height=1.0, bool center=false, vec2 scale=vec2(1.0, 1.0), index_t slices=0, double twist=0.0)
Computes a 3D extrusion from a 2D shape.
std::shared_ptr< Mesh > rotate(double angle, const CSGScope &scope)
Commodity function for 2D-rotating a CSGScope using OpenSCAD syntax.
std::shared_ptr< Mesh > intersection(Types...args)
Computes the mutual intersection between meshes.
virtual std::shared_ptr< Mesh > hull(const CSGScope &scope)
Computes the convex hull of several meshes.
void set_detect_intersecting_neighbors(bool x)
detect and compute intersections between facets that share a facet or an edge. Set to false if input ...
void set_simplify_coplanar_facets(bool x, double angle_tolerance=0.0)
Specifies whether coplanar facets should be simplified.
std::shared_ptr< Mesh > translate(const vec3 &T, const CSGScope &scope)
Commodity function for translating a CSGScope using OpenSCAD syntax.
std::shared_ptr< Mesh > rotate(const vec3 &angles, const CSGScope &scope)
Commodity function for rotating a CSGScope using OpenSCAD syntax.
virtual std::shared_ptr< Mesh > minkowski(const CSGScope &scope)
Computes the Minkowski sum of meshes.
void set_noop(bool x)
Sets noop mode.
std::shared_ptr< Mesh > difference(Types...args)
Computes the difference between meshes.
void keep_z0_only(std::shared_ptr< Mesh > &M)
keeps only triangles and vertices embedded in the z=0 plane, and makes the mesh 2D.
virtual std::shared_ptr< Mesh > circle(double r=1.0, index_t nu=0)
virtual std::shared_ptr< Mesh > append(const CSGScope &scope)
Appends all meshes in scope into a unique mesh, without testing for intersections.
virtual void finalize_mesh(std::shared_ptr< Mesh > &mesh)
Derived classes may override this function and compute some cached information, e....
virtual std::shared_ptr< Mesh > color(vec4 color, const CSGScope &scope)
Groups several meshes into a single one and sets their color.
virtual std::shared_ptr< Mesh > group(const CSGScope &scope)
synonym for union.
virtual std::shared_ptr< Mesh > multmatrix(const mat4 &M, const CSGScope &scope)
Groups several meshes into a single one and transforms them.
static mat4 rotation_matrix(double angle, vec3 axis={0.0, 0.0, 0.0})
Builds a rotation matrix.
static std::pair< vec3, vec3 > get_bbox_bounds(const std::shared_ptr< Mesh > &mesh)
Computes the bounding box of a mesh.
virtual void triangulate(std::shared_ptr< Mesh > &mesh, const std::string &boolean_expr)
Triangulates a 2D mesh.
virtual std::shared_ptr< Mesh > difference(const CSGScope &scope)
Computes the intersection between two meshes.
const std::filesystem::path & current_path()
Gets the current path.
A Scope corresponds to a set of primitive between curly braces in OpenSCAD, arguments of an operation...
CSGScope(const std::initializer_list< std::shared_ptr< Mesh > > &Ms)
Constructs a CSGScope from a list of meshes.
CSGScope()
Constructs an empty CSGScope.
CSGScope(std::shared_ptr< Mesh > M)
Constructs a CSGScope that contains a single mesh.
Common include file, providing basic definitions. Should be included before anything else by all head...
Global Vorpaline namespace.
void get_bbox(const Mesh &M, double *xyzmin, double *xyzmax)
Gets the bounding box of a mesh.
geo_index_t index_t
The type for storing and manipulating indices.
#define M_PI
Value of the constant PI if not defined by the system.
A parsed value in a .csg file.