Geogram Version 1.9.6-rc
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 }
369
375 bool verbose() const {
376 return verbose_;
377 }
378
385 void add_file_path(const std::string& path) {
386 file_path_.push_back(path);
387 }
388
394 file_path_.clear();
395 file_path_.push_back(".");
396 }
397
398 /**** misc ****/
399
407 geo_assert(mesh->vertices.dimension() == 2);
408 geo_assert(mesh->facets.nb() == 0);
409 triangulate(mesh, "union");
410 }
411
412 protected:
413
414 bool find_file(std::string& filename);
415
416 void do_CSG(CSGMesh_var mesh, const std::string& boolean_expr);
417
428 CSGMesh_var mesh, const std::string& boolean_expr,
429 bool keep_border_only=false
430 );
431
438 const std::string& filename, const std::string& layer="",
439 index_t timestamp=0
440 );
441
449 Image* load_dat_image(const std::string& file_name);
450
459
469 index_t get_fragments_from_r(double r, double twist = 360.0);
470
471 private:
472 double fn_;
473 double fs_;
474 double fa_;
475 double STL_epsilon_;
476 bool verbose_;
477 index_t max_arity_;
478 std::vector<std::string> file_path_;
479 bool detect_intersecting_neighbors_;
480 bool delaunay_;
481 bool simplify_coplanar_facets_;
482 double coplanar_angle_tolerance_;
483 bool fast_union_;
484 bool warnings_;
485 };
486
487 /**************************************************************/
488
493 class GEOGRAM_API CSGCompiler {
494 public:
495
496 CSGCompiler();
497 CSGMesh_var compile_file(const std::string& input_filename);
498 CSGMesh_var compile_string(const std::string& source);
499
505 void set_verbose(bool x) {
506 builder_.set_verbose(x);
507 }
508
514 return builder_;
515 }
516
517 protected:
518
519 /****** Value, Arglist **********************************/
520
525 struct Value {
526 enum Type {NONE, NUMBER, BOOLEAN, ARRAY1D, ARRAY2D, STRING};
527
528 Value();
529 Value(double x);
530 Value(int x);
531 Value(bool x);
532 Value(const std::string& x);
533 std::string to_string() const;
534
535 Type type;
536 bool boolean_val;
537 double number_val;
538 vector<vector<double> > array_val;
539 std::string string_val;
540 };
541
546 class ArgList {
547 public:
548 typedef std::pair<std::string, Value> Arg;
549
550 index_t size() const {
551 return args_.size();
552 }
553
554 const std::string& ith_arg_name(index_t i) const {
555 geo_assert(i < size());
556 return args_[i].first;
557 }
558
559 const Value& ith_arg_val(index_t i) const {
560 geo_assert(i < size());
561 return args_[i].second;
562 }
563
564 void add_arg(const std::string& name, const Value& value);
565 bool has_arg(const std::string& name) const;
566 const Value& get_arg(const std::string& name) const;
567 double get_arg(const std::string& name,double default_value) const;
568 int get_arg(const std::string& name, int default_value) const;
569 bool get_arg(const std::string& name, bool default_value) const;
570 vec2 get_arg(const std::string& name, vec2 default_value) const;
571 vec3 get_arg(const std::string& name, vec3 default_value) const;
572 vec4 get_arg(const std::string& name, vec4 default_value) const;
573 mat4 get_arg(
574 const std::string& name, const mat4& default_value
575 ) const;
576 std::string get_arg(
577 const std::string& name, const std::string& default_value
578 ) const;
579 std::string get_arg(
580 const std::string& name, const char* default_value
581 ) const {
582 return get_arg(name, std::string(default_value));
583 }
584
585 private:
586 vector<Arg> args_;
587 };
588
589
590 /****** Objects *****************************************/
591
592 CSGMesh_var square(const ArgList& args);
593 CSGMesh_var circle(const ArgList& args);
594 CSGMesh_var cube(const ArgList& args);
595 CSGMesh_var sphere(const ArgList& args);
596 CSGMesh_var cylinder(const ArgList& args);
597 CSGMesh_var polyhedron(const ArgList& args);
598 CSGMesh_var polygon(const ArgList& args);
599 CSGMesh_var import(const ArgList& args);
600 CSGMesh_var surface(const ArgList& args);
601 CSGMesh_var text(const ArgList& args);
602
603 /****** Instructions ************************************/
604
605 CSGMesh_var multmatrix(const ArgList& args, const CSGScope& scope);
606 CSGMesh_var resize(const ArgList& args, const CSGScope& scope);
607 CSGMesh_var union_instr(const ArgList& args, const CSGScope& scope);
608 CSGMesh_var intersection(const ArgList& args, const CSGScope& scope);
609 CSGMesh_var difference(const ArgList& args, const CSGScope& scope);
610 CSGMesh_var group(const ArgList& args, const CSGScope& scope);
611 CSGMesh_var color(const ArgList& args, const CSGScope& scope);
612 CSGMesh_var hull(const ArgList& args, const CSGScope& scope);
613 CSGMesh_var linear_extrude(const ArgList& args, const CSGScope& scope);
614 CSGMesh_var rotate_extrude(const ArgList& args, const CSGScope& scope);
615 CSGMesh_var projection(const ArgList& args, const CSGScope& scope);
616
617 /***** Parser *******************************************/
618
619 CSGMesh_var parse_instruction_or_object();
620 CSGMesh_var parse_object();
621 CSGMesh_var parse_instruction();
622 ArgList parse_arg_list();
623 Value parse_value();
624 Value parse_array();
625 bool is_object(const std::string& id) const;
626 bool is_instruction(const std::string& id) const;
627
637 bool is_modifier(int toktype) const;
638
639 /***** Parser internals ********************************/
640
641 struct Token {
642 Token();
643 std::string to_string() const;
644 int type;
645 std::string str_val;
646 int int_val;
647 double double_val;
648 bool boolean_val;
649 };
650
657 void next_token_check(char c);
658
664
670
678
682 int lines() const;
683
687 int line() const;
688
689
694 [[noreturn]] void syntax_error(const char* msg);
695
702 [[noreturn]] void syntax_error(const char* msg, const Token& tok);
703
704 private:
705 std::string filename_;
706 void* lex_;
707 Token lookahead_token_;
708 CSGBuilder builder_;
709
710 typedef CSGMesh_var (CSGCompiler::*object_funptr)(const ArgList& args);
711 typedef CSGMesh_var (CSGCompiler::*instruction_funptr)(
712 const ArgList& args, const CSGScope& scope
713 );
714 std::map<std::string, object_funptr> object_funcs_;
715 std::map<std::string, instruction_funptr> instruction_funcs_;
716 ProgressTask* progress_;
717 index_t lines_;
718 };
719}
720
721#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.
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:375
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:406
void add_file_path(const std::string &path)
Adds a path to the file path.
Definition mesh_CSG.h:385
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_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
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:393
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:546
Creates meshes from OpenSCAD .csg files.
Definition mesh_CSG.h:493
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.
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:505
CSGBuilder & builder()
Gets the CSGbuilder.
Definition mesh_CSG.h:513
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:3050
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:525