Geogram Version 1.9.6
A programming library of geometric algorithms
Loading...
Searching...
No Matches
mesh_CSG.h
Go to the documentation of this file.
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_ALGO_MESH_CSG_H
41#define H_GEO_MESH_ALGO_MESH_CSG_H
42
44#include <geogram/mesh/mesh.h>
47
53namespace GEO {
54
55 class ProgressTask;
56 class Image;
57
61 class GEOGRAM_API CSGMesh : public Mesh, public Counted {
62 public:
63 CSGMesh();
64 ~CSGMesh() override;
70 const Box3d& bbox() const {
71 geo_debug_assert(vertices.nb() == 0 || bbox_initialized());
72 return bbox_;
73 }
74
82 bool bbox_initialized() const;
83
90
98 void append_mesh(const CSGMesh* other, index_t operand = NO_INDEX);
99
110 bool may_have_intersections_with(const CSGMesh* other) const {
111 return bboxes_overlap(bbox(), other->bbox());
112 }
113
114 private:
115 Box3d bbox_;
116 };
117
122
127 typedef std::vector< CSGMesh_var > CSGScope;
128
134 class GEOGRAM_API CSGBuilder {
135 public:
137 static constexpr double DEFAULT_FA = 12.0;
138
140 static constexpr double DEFAULT_FS = 2.0;
141
143 static constexpr double DEFAULT_FN = 0.0;
144
145 CSGBuilder();
146
147 /****** Objects **********/
148
149 CSGMesh_var square(vec2 size = vec2(1.0,1.0), bool center=true);
150 CSGMesh_var circle(double r=1.0);
151 CSGMesh_var cube(vec3 size = vec3(1.0, 1.0, 1.0), bool center=true);
152 CSGMesh_var sphere(double r=1.0);
153 CSGMesh_var cylinder(
154 double h=1.0, double r1=1.0, double r2=1.0, bool center=true
155 );
156 CSGMesh_var import(
157 const std::string& filename, const std::string& layer="",
158 index_t timestamp=0,
159 vec2 origin = vec2(0.0, 0.0), vec2 scale = vec2(1.0,1.0)
160 );
161 CSGMesh_var surface(
162 const std::string& filename, bool center, bool invert
163 );
164 CSGMesh_var text_with_OpenSCAD(
165 const std::string& text,
166 double size = 10.0,
167 const std::string& font = "",
168 const std::string& halign = "left",
169 const std::string& valign = "baseline",
170 double spacing = 1.0,
171 const std::string& direction = "ltr",
172 const std::string& language = "en",
173 const std::string& script = "latin"
174 );
175
176
177 /****** Instructions ****/
178
188 CSGMesh_var multmatrix(const mat4& M, const CSGScope& scope);
189
195
201
209
216 CSGMesh_var group(const CSGScope& scope) {
217 return union_instr(scope);
218 }
219
226 CSGMesh_var color(vec4 color, const CSGScope& scope);
227
232 CSGMesh_var hull(const CSGScope& scope);
233
246 const CSGScope& scope,
247 double height = 1.0,
248 bool center = true,
249 vec2 scale = vec2(1.0,1.0),
250 index_t slices = 0,
251 double twist = 0.0
252 );
253
254
261 CSGMesh_var rotate_extrude(const CSGScope& scope, double angle = 360.0);
262
269 CSGMesh_var projection(const CSGScope& scope, bool cut);
270
276
277 /****** Parameters ******/
278
284
293 void set_fn(double fn) {
294 fn_ = std::max(fn, 0.0);
295 }
296
303 void set_fs(double fs) {
304 fs_ = std::max(fs,0.01);
305 }
306
313 void set_fa(double fa) {
314 fa_ = std::max(fa,0.01);
315 }
316
323 void set_delaunay(bool x) {
324 delaunay_ = x;
325 }
326
333 detect_intersecting_neighbors_ = x;
334 }
335
345 void set_simplify_coplanar_facets(bool x, double angle_tolerance=0.0) {
346 simplify_coplanar_facets_ = x;
347 coplanar_angle_tolerance_ = angle_tolerance;
348 }
349
357 void set_fast_union(bool x) {
358 fast_union_ = x;
359 }
360
366 void set_verbose(bool x) {
367 verbose_ = x;
368 if(!verbose_ && fine_verbose_) {
369 fine_verbose_ = false;
370 }
371 }
372
378 void set_fine_verbose(bool x) {
379 fine_verbose_ = x;
380 if(fine_verbose_ && !verbose_) {
381 verbose_ = true;
382 }
383 }
384
390 bool verbose() const {
391 return verbose_;
392 }
393
400 void add_file_path(const std::string& path) {
401 file_path_.push_back(path);
402 }
403
410 void push_file_path(const std::string& path) {
411 file_path_.push_back(path);
412 }
413
418 geo_assert(file_path_.size() != 0);
419 file_path_.pop_back();
420 }
421
427 file_path_.clear();
428 file_path_.push_back(".");
429 }
430
431 /**** misc ****/
432
440 geo_assert(mesh->vertices.dimension() == 2);
441 geo_assert(mesh->facets.nb() == 0);
442 triangulate(mesh, "union");
443 }
444
451 void set_noop(bool x) {
452 noop_ = x;
453 }
454
455 protected:
456
457 bool find_file(std::string& filename);
458
459 void do_CSG(CSGMesh_var mesh, const std::string& boolean_expr);
460
471 CSGMesh_var mesh, const std::string& boolean_expr,
472 bool keep_border_only=false
473 );
474
481 const std::string& filename, const std::string& layer="",
482 index_t timestamp=0
483 );
484
492 Image* load_dat_image(const std::string& file_name);
493
502
512 index_t get_fragments_from_r(double r, double twist = 360.0);
513
514 private:
515 double fn_;
516 double fs_;
517 double fa_;
518 double STL_epsilon_;
519 bool verbose_;
520 bool fine_verbose_;
521 index_t max_arity_;
522 std::vector<std::string> file_path_;
523 bool detect_intersecting_neighbors_;
524 bool delaunay_;
525 bool simplify_coplanar_facets_;
526 double coplanar_angle_tolerance_;
527 bool fast_union_;
528 bool warnings_;
529 bool noop_;
530 };
531
532 /**************************************************************/
533
538 class GEOGRAM_API CSGCompiler {
539 public:
540
541 CSGCompiler();
542 CSGMesh_var compile_file(const std::string& input_filename);
543 CSGMesh_var compile_string(const std::string& source);
544
550 void set_verbose(bool x) {
551 builder_.set_verbose(x);
552 }
553
559 void set_fine_verbose(bool x) {
560 builder_.set_fine_verbose(x);
561 }
562
568 return builder_;
569 }
570
571 protected:
572
573 /****** Value, Arglist **********************************/
574
579 struct Value {
580 enum Type {NONE, NUMBER, BOOLEAN, ARRAY1D, ARRAY2D, STRING};
581
582 Value();
583 Value(double x);
584 Value(int x);
585 Value(bool x);
586 Value(const std::string& x);
587 std::string to_string() const;
588
589 Type type;
590 bool boolean_val;
591 double number_val;
592 vector<vector<double> > array_val;
593 std::string string_val;
594 };
595
600 class ArgList {
601 public:
602 typedef std::pair<std::string, Value> Arg;
603
604 index_t size() const {
605 return args_.size();
606 }
607
608 const std::string& ith_arg_name(index_t i) const {
609 geo_assert(i < size());
610 return args_[i].first;
611 }
612
613 const Value& ith_arg_val(index_t i) const {
614 geo_assert(i < size());
615 return args_[i].second;
616 }
617
618 void add_arg(const std::string& name, const Value& value);
619 bool has_arg(const std::string& name) const;
620 const Value& get_arg(const std::string& name) const;
621 double get_arg(const std::string& name,double default_value) const;
622 int get_arg(const std::string& name, int default_value) const;
623 bool get_arg(const std::string& name, bool default_value) const;
624 vec2 get_arg(const std::string& name, vec2 default_value) const;
625 vec3 get_arg(const std::string& name, vec3 default_value) const;
626 vec4 get_arg(const std::string& name, vec4 default_value) const;
627 mat4 get_arg(
628 const std::string& name, const mat4& default_value
629 ) const;
630 std::string get_arg(
631 const std::string& name, const std::string& default_value
632 ) const;
633 std::string get_arg(
634 const std::string& name, const char* default_value
635 ) const {
636 return get_arg(name, std::string(default_value));
637 }
638
639 private:
640 vector<Arg> args_;
641 };
642
643
644 /****** Objects *****************************************/
645
646 CSGMesh_var square(const ArgList& args);
647 CSGMesh_var circle(const ArgList& args);
648 CSGMesh_var cube(const ArgList& args);
649 CSGMesh_var sphere(const ArgList& args);
650 CSGMesh_var cylinder(const ArgList& args);
651 CSGMesh_var polyhedron(const ArgList& args);
652 CSGMesh_var polygon(const ArgList& args);
653 CSGMesh_var import(const ArgList& args);
654 CSGMesh_var surface(const ArgList& args);
655 CSGMesh_var text(const ArgList& args);
656
657 /****** Instructions ************************************/
658
659 CSGMesh_var multmatrix(const ArgList& args, const CSGScope& scope);
660 CSGMesh_var resize(const ArgList& args, const CSGScope& scope);
661 CSGMesh_var union_instr(const ArgList& args, const CSGScope& scope);
662 CSGMesh_var intersection(const ArgList& args, const CSGScope& scope);
663 CSGMesh_var difference(const ArgList& args, const CSGScope& scope);
664 CSGMesh_var group(const ArgList& args, const CSGScope& scope);
665 CSGMesh_var color(const ArgList& args, const CSGScope& scope);
666 CSGMesh_var hull(const ArgList& args, const CSGScope& scope);
667 CSGMesh_var linear_extrude(const ArgList& args, const CSGScope& scope);
668 CSGMesh_var rotate_extrude(const ArgList& args, const CSGScope& scope);
669 CSGMesh_var projection(const ArgList& args, const CSGScope& scope);
670
671 /***** Parser *******************************************/
672
673 CSGMesh_var parse_instruction_or_object();
674 CSGMesh_var parse_object();
675 CSGMesh_var parse_instruction();
676 ArgList parse_arg_list();
677 Value parse_value();
678 Value parse_array();
679 bool is_object(const std::string& id) const;
680 bool is_instruction(const std::string& id) const;
681
691 bool is_modifier(int toktype) const;
692
693 /***** Parser internals ********************************/
694
695 struct Token {
696 Token();
697 std::string to_string() const;
698 int type;
699 std::string str_val;
700 int int_val;
701 double double_val;
702 bool boolean_val;
703 };
704
711 void next_token_check(char c);
712
718
724
732
736 int lines() const;
737
741 int line() const;
742
743
748 [[noreturn]] void syntax_error(const char* msg);
749
756 [[noreturn]] void syntax_error(const char* msg, const Token& tok);
757
758 private:
759 std::string filename_;
760 void* lex_;
761 Token lookahead_token_;
762 CSGBuilder builder_;
763
764 typedef CSGMesh_var (CSGCompiler::*object_funptr)(const ArgList& args);
765 typedef CSGMesh_var (CSGCompiler::*instruction_funptr)(
766 const ArgList& args, const CSGScope& scope
767 );
768 std::map<std::string, object_funptr> object_funcs_;
769 std::map<std::string, instruction_funptr> instruction_funcs_;
770 ProgressTask* progress_;
771 index_t lines_;
772 };
773}
774
775#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
Axis-aligned bounding box.
Definition geometry.h:689
Implements CSG objects and instructions.
Definition mesh_CSG.h:134
index_t get_fragments_from_r(double r, double twist=360.0)
Computes the number of fragments, that is, edges in a polygonal approximation of a circle.
void pop_file_path()
Removes the latest pushed file path.
Definition mesh_CSG.h:417
void push_file_path(const std::string &path)
Adds a path to the file path.
Definition mesh_CSG.h:410
CSGMesh_var difference(const CSGScope &scope)
Computes the intersection between two meshes.
void set_delaunay(bool x)
If set, compute constrained Delaunay triangulation in the intersected triangles. If there are interse...
Definition mesh_CSG.h:323
CSGMesh_var intersection(const CSGScope &scope)
Computes the intersection between two or more meshes.
CSGMesh_var color(vec4 color, const CSGScope &scope)
Groups several meshes into a single one and sets their color.
void set_fn(double fn)
Sets the number of fragments.
Definition mesh_CSG.h:293
void post_process(CSGMesh_var mesh)
Post-processes the result of a previous intersection.
bool verbose() const
Tests wheter verbose mode is set.
Definition mesh_CSG.h:390
CSGMesh_var group(const CSGScope &scope)
synonym for union.
Definition mesh_CSG.h:216
void set_fast_union(bool x)
Sets fast union mode.
Definition mesh_CSG.h:357
void set_fa(double fa)
Sets the minimum angle for a fragment.
Definition mesh_CSG.h:313
void triangulate_2D_contours(CSGMesh_var mesh)
Triangulates a 2D mesh composed of vertices and segments.
Definition mesh_CSG.h:439
void add_file_path(const std::string &path)
Adds a path to the file path.
Definition mesh_CSG.h:400
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 ...
Definition mesh_CSG.h:332
void set_simplify_coplanar_facets(bool x, double angle_tolerance=0.0)
Specifies whether coplanar facets should be simplified.
Definition mesh_CSG.h:345
CSGMesh_var linear_extrude(const CSGScope &scope, double height=1.0, bool center=true, vec2 scale=vec2(1.0, 1.0), index_t slices=0, double twist=0.0)
Computes a 3D extrusion from a 2D shape.
Image * load_dat_image(const std::string &file_name)
Loads an ascii data file as an image.
void triangulate(CSGMesh_var mesh, const std::string &boolean_expr, bool keep_border_only=false)
Triangulates a 2D mesh.
void set_fine_verbose(bool x)
Displays (even more) additional information.
Definition mesh_CSG.h:378
void set_fs(double fs)
Sets the minimum size for a fragment.
Definition mesh_CSG.h:303
CSGMesh_var multmatrix(const mat4 &M, const CSGScope &scope)
Groups several meshes into a single one and transforms them.
void set_verbose(bool x)
Displays (lots of) additional information.
Definition mesh_CSG.h:366
void set_noop(bool x)
Sets noop mode.
Definition mesh_CSG.h:451
CSGMesh_var rotate_extrude(const CSGScope &scope, double angle=360.0)
Computes a 3D extrusion from a 2D shape.
void reset_file_path()
Resets the file path to its default value, with only the current directory ".".
Definition mesh_CSG.h:426
CSGMesh_var append(const CSGScope &scope)
Appends all meshes in scope into a unique mesh, without testing for intersections.
CSGMesh_var projection(const CSGScope &scope, bool cut)
Creates a 2D mesh from 3D mesh.
CSGMesh_var union_instr(const CSGScope &scope)
Computes the union of two or more meshes.
CSGMesh_var hull(const CSGScope &scope)
Computes the convex hull of several meshes.
CSGMesh_var import_with_openSCAD(const std::string &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.
void reset_defaults()
Resets defaults value for fn, fs, fa.
A parsed argument list in a .csg file.
Definition mesh_CSG.h:600
Creates meshes from OpenSCAD .csg files.
Definition mesh_CSG.h:538
void syntax_error(const char *msg, const Token &tok)
Throws an exception with an error message.
Token next_token_internal()
Function to actually get the next token from the stream.
bool is_modifier(int toktype) const
Checks if a token corresponds to an instruction or object modifier.
void next_token_check(char c)
Checks that the next token is a given character.
void set_fine_verbose(bool x)
Displays (even more) additional information.
Definition mesh_CSG.h:559
int line() const
Gets the currently parsed line source.
Token lookahead_token()
Gets the next token without any side effect.
void set_verbose(bool x)
Displays (lots of) additional information.
Definition mesh_CSG.h:550
CSGBuilder & builder()
Gets the CSGbuilder.
Definition mesh_CSG.h:567
void syntax_error(const char *msg)
Throws an exception with an error message.
Token next_token()
Gets the next token.
int lines() const
Gets the total number of lines of the currently parsed source.
A Mesh with reference counting and bounding box.
Definition mesh_CSG.h:61
bool bbox_initialized() const
Tests whether the bounding box was initialized.
const Box3d & bbox() const
Gets the bounding box.
Definition mesh_CSG.h:70
bool may_have_intersections_with(const CSGMesh *other) const
Tests whether this mesh may have an intersection with another mesh.
Definition mesh_CSG.h:110
void append_mesh(const CSGMesh *other, index_t operand=NO_INDEX)
Appends a mesh to this mesh.
void update_bbox()
Computes the bounding box.
Base class for reference-counted objects.
Definition counted.h:71
An image.
Definition image.h:59
Represents a mesh.
Definition mesh.h:3068
Tracks the progress of a task.
Definition progress.h:240
A smart pointer with reference-counted copy semantics.
Vector with aligned memory allocation.
Definition memory.h:660
Common include file, providing basic definitions. Should be included before anything else by all head...
Types and functions for memory manipulation.
The class that represents a mesh.
Global Vorpaline namespace.
Definition basic.h:55
SmartPointer< CSGMesh > CSGMesh_var
A smart pointer to a CSGMesh.
Definition mesh_CSG.h:121
std::vector< CSGMesh_var > CSGScope
A list of CSGMesh.
Definition mesh_CSG.h:127
bool bboxes_overlap(const Box &B1, const Box &B2)
Tests whether two Boxes have a non-empty intersection.
Definition geometry.h:721
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:329
Pointers with automatic reference counting.
A parsed value in a .csg file.
Definition mesh_CSG.h:579