Geogram Version 1.9.7
A programming library of geometric algorithms
Loading...
Searching...
No Matches
mesh_CSG_builder.h
1/*
2 * Copyright (c) 2000-2023 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef H_GEO_MESH_CSG_BUILDER_H
41#define H_GEO_MESH_CSG_BUILDER_H
42
44#include <geogram/mesh/mesh_CSG_utils.h>
45#include <memory>
46#include <functional>
47#include <stack>
48
49namespace GEO {
50
62 class GEOGRAM_API AbstractCSGBuilder {
63 public:
65 typedef GEOCSG::Value Value;
66
68 static constexpr double DEFAULT_FA = 12.0;
69
71 static constexpr double DEFAULT_FS = 2.0;
72
74 static constexpr double DEFAULT_FN = 0.0;
75
76
81
86
87 /****** Parameters ******/
88
94
103 void set_fn(double fn) {
104 fn_ = std::max(fn, 0.0);
105 }
106
113 void set_fs(double fs) {
114 fs_ = std::max(fs,0.01);
115 }
116
123 void set_fa(double fa) {
124 fa_ = std::max(fa,0.01);
125 }
126
132 void set_verbose(bool x) {
133 verbose_ = x;
134 if(verbose_) {
135 warnings_ = true;
136 }
137 }
138
144 void set_detailed_verbose(bool x) {
145 detailed_verbose_ = x;
146 if(detailed_verbose_ && !verbose_) {
147 verbose_ = true;
148 }
149 }
150
156 bool verbose() const {
157 return verbose_;
158 }
159
160
167 void add_file_path(const std::filesystem::path& path) {
168 file_path_.push_back(path);
169 }
170
176 file_path_.clear();
177 file_path_.push_back(std::filesystem::current_path());
178 }
179
186 void push_file_path(const std::filesystem::path& path) {
187 file_path_.push_back(path);
188 }
189
194 geo_assert(file_path_.size() != 0);
195 file_path_.pop_back();
196 }
197
198 /**** Abstract API - objects ******/
199
200 virtual void add_object(
201 const std::string& object, const ArgList& args
202 );
203
204 virtual void begin_instruction();
205
206 virtual void end_instruction(
207 const std::string& instruction, const ArgList& args
208 );
209
210
211 bool is_object(const std::string& id) const {
212 return (object_funcs_.find(id) != object_funcs_.end());
213 }
214
215 bool is_instruction(const std::string& id) const {
216 return (instruction_funcs_.find(id) != instruction_funcs_.end());
217 }
218
219 protected:
220
221 /****** Objects ******************************************/
222
223 virtual void add_square(const ArgList& args);
224 virtual void add_circle(const ArgList& args);
225 virtual void add_cube(const ArgList& args);
226 virtual void add_sphere(const ArgList& args);
227 virtual void add_cylinder(const ArgList& args);
228 virtual void add_polyhedron(const ArgList& args);
229 virtual void add_polygon(const ArgList& args);
230 virtual void add_import(const ArgList& args);
231 virtual void add_surface(const ArgList& args);
232 virtual void add_text(const ArgList& args);
233
234 /****** Instructions ************************************/
235
236 virtual void eval_multmatrix(const ArgList& args);
237 virtual void eval_resize(const ArgList& args);
238 virtual void eval_union(const ArgList& args);
239 virtual void eval_intersection(const ArgList& args);
240 virtual void eval_difference(const ArgList& args);
241 virtual void eval_group(const ArgList& args);
242 virtual void eval_color(const ArgList& args);
243 virtual void eval_hull(const ArgList& args);
244 virtual void eval_linear_extrude(const ArgList& args);
245 virtual void eval_rotate_extrude(const ArgList& args);
246 virtual void eval_projection(const ArgList& args);
247 virtual void eval_minkowski(const ArgList& args);
248 virtual void eval_render(const ArgList& args);
249
250 /**************************/
251
252 [[noreturn]] void error(const char* str) {
253 throw(std::logic_error(str));
254 }
255
256 [[noreturn]] void error(const std::string& str) {
257 throw(std::logic_error(str.c_str()));
258 }
259
260 double fn_;
261 double fs_;
262 double fa_;
263
264 std::vector<std::filesystem::path> file_path_;
265 bool warnings_;
266 bool verbose_;
267 bool detailed_verbose_;
268
269 typedef std::function<void(const ArgList& args)> csg_builder_func;
270 std::map<std::string, csg_builder_func> object_funcs_;
271 std::map<std::string, csg_builder_func> instruction_funcs_;
272 };
273
274 /***********************************************************************/
275
281 typedef std::vector<std::shared_ptr<Mesh>> CSGScope;
282
288 class GEOGRAM_API CSGBuilder : public AbstractCSGBuilder {
289 public:
290 CSGBuilder();
291 ~CSGBuilder() override;
292
293 /****** Objects **********/
294
295 virtual std::shared_ptr<Mesh> square(
296 vec2 size = vec2(1.0,1.0), bool center=true
297 );
298
303 virtual std::shared_ptr<Mesh> circle(double r=1.0, index_t nu=0);
304
305 virtual std::shared_ptr<Mesh> cube(
306 vec3 size = vec3(1.0, 1.0, 1.0), bool center=true
307 );
308
309 virtual std::shared_ptr<Mesh> sphere(double r=1.0);
310
311 virtual std::shared_ptr<Mesh> cylinder(
312 double h=1.0, double r1=1.0, double r2=1.0, bool center=true
313 );
314
315 virtual std::shared_ptr<Mesh> import(
316 const std::filesystem::path& filename, const std::string& layer="",
317 index_t timestamp=0,
318 vec2 origin = vec2(0.0, 0.0), vec2 scale = vec2(1.0,1.0)
319 );
320
321 virtual std::shared_ptr<Mesh> surface(
322 const std::filesystem::path& filename, bool center, bool invert
323 );
324
325 virtual std::shared_ptr<Mesh> text(
326 const std::string& text,
327 double size = 10.0,
328 const std::string& font = "",
329 const std::string& halign = "left",
330 const std::string& valign = "baseline",
331 double spacing = 1.0,
332 const std::string& direction = "ltr",
333 const std::string& language = "en",
334 const std::string& script = "latin"
335 );
336
337
338 /****** Instructions ****/
339
349 virtual std::shared_ptr<Mesh> multmatrix(
350 const mat4& M, const CSGScope& scope
351 );
352
357 virtual std::shared_ptr<Mesh> union_instr(const CSGScope& scope);
358
363 virtual std::shared_ptr<Mesh> intersection(const CSGScope& scope);
364
371 virtual std::shared_ptr<Mesh> difference(const CSGScope& scope);
372
379 virtual std::shared_ptr<Mesh> group(const CSGScope& scope);
380
387 virtual std::shared_ptr<Mesh> color(vec4 color, const CSGScope& scope);
388
393 virtual std::shared_ptr<Mesh> hull(const CSGScope& scope);
394
406 virtual std::shared_ptr<Mesh> linear_extrude(
407 const CSGScope& scope,
408 double height = 1.0,
409 bool center = false,
410 vec2 scale = vec2(1.0,1.0),
411 index_t slices = 0,
412 double twist = 0.0
413 );
414
421 virtual std::shared_ptr<Mesh> rotate_extrude(
422 const CSGScope& scope, double angle = 360.0
423 );
424
431 virtual std::shared_ptr<Mesh> projection(const CSGScope& scope, bool cut);
432
436 virtual std::shared_ptr<Mesh> minkowski(const CSGScope& scope);
437
443 virtual std::shared_ptr<Mesh> append(const CSGScope& scope);
444
445 /****** AbstractCSGBuilder API ********************************/
446
447 void add_object(const std::string& object, const ArgList& args) override;
448 void begin_instruction() override;
449 void end_instruction(
450 const std::string& instruction, const ArgList& args
451 ) override;
452
453 /****** Objects (AbstractCSGBuilder API) *********************/
454
455 void add_square(const ArgList& args) override;
456 void add_circle(const ArgList& args) override;
457 void add_cube(const ArgList& args) override;
458 void add_sphere(const ArgList& args) override;
459 void add_cylinder(const ArgList& args) override;
460 void add_polyhedron(const ArgList& args) override;
461 void add_polygon(const ArgList& args) override;
462 void add_import(const ArgList& args) override;
463 void add_surface(const ArgList& args) override;
464 void add_text(const ArgList& args) override;
465
466 /****** Instructions (AbstractCSGBuilder API) ****************/
467
468
469 void eval_multmatrix(const ArgList& args) override;
470 void eval_resize(const ArgList& args) override;
471 void eval_union(const ArgList& args) override;
472 void eval_intersection(const ArgList& args) override;
473 void eval_difference(const ArgList& args) override;
474 void eval_group(const ArgList& args) override;
475 void eval_color(const ArgList& args) override;
476 void eval_hull(const ArgList& args) override;
477 void eval_linear_extrude(const ArgList& args) override;
478 void eval_rotate_extrude(const ArgList& args) override;
479 void eval_projection(const ArgList& args) override;
480 void eval_minkowski(const ArgList& args) override;
481 void eval_render(const ArgList& args) override;
482
483 /**************************/
484
491 void set_delaunay(bool x) {
492 delaunay_ = x;
493 }
494
501 detect_intersecting_neighbors_ = x;
502 }
503
513 void set_simplify_coplanar_facets(bool x, double angle_tolerance=0.0) {
514 simplify_coplanar_facets_ = x;
515 coplanar_angle_tolerance_ = angle_tolerance;
516 }
517
525 void set_fast_union(bool x) {
526 fast_union_ = x;
527 }
528
529
530 /***** misc ********/
531
538 void set_noop(bool x) {
539 noop_ = x;
540 }
541
542
549 static Box3d get_bbox(const std::shared_ptr<Mesh>& mesh);
550
558 static std::pair<vec3, vec3> get_bbox_bounds(
559 const std::shared_ptr<Mesh>& mesh
560 ) {
561 Box3d result = get_bbox(mesh);
562 return std::make_pair(vec3(result.xyz_min), vec3(result.xyz_max));
563 }
564
565 protected:
566
567 std::shared_ptr<Mesh> surface_with_OpenSCAD(
568 const std::filesystem::path& filename, bool center, bool invert
569 );
570
571 std::shared_ptr<Mesh> text_with_OpenSCAD(
572 const std::string& text,
573 double size = 10.0,
574 const std::string& font = "",
575 const std::string& halign = "left",
576 const std::string& valign = "baseline",
577 double spacing = 1.0,
578 const std::string& direction = "ltr",
579 const std::string& language = "en",
580 const std::string& script = "latin"
581 );
582
583 /**** Lower-level functions ****/
584
592 bool find_file(std::filesystem::path& filename);
593
598 const std::filesystem::path& current_path() {
599 geo_assert(file_path_.size() != 0);
600 return *(file_path_.rbegin());
601 }
602
608 std::shared_ptr<Mesh> import_with_openSCAD(
609 const std::filesystem::path& filename, const std::string& layer="",
610 index_t timestamp=0
611 );
612
628 virtual void do_CSG(
629 std::shared_ptr<Mesh>& mesh, const std::string& boolean_expr
630 );
631
655 virtual void triangulate(
656 std::shared_ptr<Mesh>& mesh, const std::string& boolean_expr
657 );
658
664 virtual void triangulate(std::shared_ptr<Mesh>& mesh);
665
672 void keep_z0_only(std::shared_ptr<Mesh>& M);
673
679 virtual void finalize_mesh(std::shared_ptr<Mesh>& mesh);
680
681 CSGScope& top_scope() {
682 geo_debug_assert(!scope_stack_.empty());
683 return scope_stack_.top();
684 }
685
686 void push_scope() {
687 scope_stack_.emplace();
688 }
689
690 void pop_scope() {
691 geo_debug_assert(!scope_stack_.empty());
692 scope_stack_.pop();
693 }
694
695 protected:
696 double STL_epsilon_;
697 index_t max_arity_;
698 bool detect_intersecting_neighbors_;
699 bool delaunay_;
700 bool simplify_coplanar_facets_;
701 double coplanar_angle_tolerance_;
702 bool fast_union_;
703 bool noop_;
704 std::shared_ptr<Mesh> empty_mesh_;
705 std::shared_ptr<Mesh> result_;
706 std::stack<CSGScope> scope_stack_;
707
708 friend class CSGCompiler;
709 };
710
711}
712
713#endif
#define geo_assert(x)
Verifies that a condition is met.
Definition assert.h:149
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
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.
Definition geometry.h:689
Implements CSG objects and instructions.
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.
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.
void set_fast_union(bool x)
Sets fast union mode.
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.
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.
virtual std::shared_ptr< Mesh > minkowski(const CSGScope &scope)
Computes the Minkowski sum of meshes.
void set_noop(bool x)
Sets noop mode.
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 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.
Common include file, providing basic definitions. Should be included before anything else by all head...
Global Vorpaline namespace.
Definition basic.h:55
void get_bbox(const Mesh &M, double *xyzmin, double *xyzmax)
Gets the bounding box of a mesh.
std::vector< std::shared_ptr< Mesh > > CSGScope
A Scope corresponds to a set of primitive between curly braces in OpenSCAD, arguments of an operation...
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:329
A parsed value in a .csg file.