Geogram  Version 1.9.1
A programming library of geometric algorithms
meshcomesh.h
1 /*
2  * Copyright (c) 2000-2022 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_MESHCOMESH_H
41 #define H_MESHCOMESH_H
42 
44 #include <geogram/mesh/mesh.h>
45 #include <exploragram/hexdom/polygon.h>
46 #include <exploragram/hexdom/intersect_tools.h>
47 
52 namespace GEO {
53  struct TrFan {
54  struct TrFanElt {
55  TrFanElt(Mesh* m, index_t v, index_t p_f, index_t p_chart) : f(p_f), chart(p_chart) {
56  geo_assert(m->facets.nb_vertices(f) == 3);
57  FOR (c, 3) {
58  if (m->facets.vertex(f, c) != v) continue;
59  org = m->facets.vertex(f, (c + 1) % 3);
60  dest = m->facets.vertex(f, (c + 2) % 3);
61  break;
62  }
63  }
64 
65  index_t f;
66  index_t chart;
67  index_t org;
68  index_t dest;
69  };
70 
71  TrFan(index_t v, Mesh *m, vector<vector<index_t> > &v2f, Attribute<index_t> &chart) : m_(m), v_(v), incomplete_(false) {
72  if (!v2f[v].size()) return;
73 
74  FOR(i, v2f[v].size()) { // collect triangles around v
75  index_t f = v2f[v][i];
76  geo_assert(3 == m->facets.nb_vertices(f));
77  fan.push_back(TrFanElt(m, v, f, chart[f]));
78  }
79 
80  FOR(i, fan.size()) { // find boundary fan element and put it in the first position
81  bool boundary = true;
82  FOR(j, fan.size()) {
83  if (fan[i].org == fan[j].dest) {
84  geo_assert(i != j);
85  boundary = false;
86  break;
87  }
88  }
89  if (boundary) {
90  std::swap(fan[0], fan[i]);
91  incomplete_ = true;
92  break;
93  }
94  }
95 
96  FOR(f, fan.size()-1) { // sort triangles in circular order, first triangle is not moved
97  for (index_t i = f+2; i<fan.size(); i++) {
98  if (fan[f].dest == fan[i].org) {
99  std::swap(fan[f + 1], fan[i]);
100  break;
101  }
102  }
103  }
104 
105  FOR(f, fan.size()) {
106  if (fan[f].dest == fan[(f+1) % fan.size()].org) continue;
107  if (f+1==fan.size() && incomplete_) continue;
108  GEO::Logger::out("HexDom") << "Fan around vertex " << v_ << " is not valid" << std::endl;
109  FOR(ff, fan.size()) GEO::Logger::out("HexDom") << "fan[ff].org = " << fan[ff].org << "\tfan[ff].dest = " << fan[ff].dest << std::endl;
111  }
112 
113  if (!incomplete_) {
114  index_t rotate = 0; // find a boundary between charts (any boundary will do); if no boundary rotate will be zero
115  FOR(f, fan.size()) {
116  if (fan[rotate].chart != fan[(rotate-1+fan.size())%fan.size()].chart) break;
117  rotate++;
118  }
119  geo_assert(rotate <= fan.size());
120  std::rotate(fan.begin(), fan.begin() + int(rotate), fan.end());
121  }
122 
123  chart_offset.push_back(0);
124  FOR(f, fan.size()-1) {
125  if (fan[f].chart == fan[f+1].chart) continue;
126  chart_offset.push_back(int(f + 1));
127  }
128  }
129 
130  index_t ncharts() {
131  return index_t(chart_offset.size());
132  }
133 
134  bool triangulate() {
135  // 2 charts max, and incomplete fan must not have more than 1 chart
136  Attribute<bool> selection(m_->vertices.attributes(), "selection");
137  if (2<ncharts() || (incomplete_ && 1!=ncharts())) {
138  selection[v_] = true;
139  return false;
140  }
141 
142  bool result = true;
143  FOR(ichart, ncharts()) {
144  vector<index_t> vidx;
145  int off1 = chart_offset[ichart];
146  int off2 = ichart+1 < ncharts() ? chart_offset[ichart+1] : int(fan.size());
147  for (int ivert=off1; ivert<off2; ivert++) {
148  vidx.push_back(fan[ivert].org);
149  }
150  if (incomplete_ || 1<ncharts()) {
151  vidx.push_back(fan[off2-1].dest);
152  }
153  triangles.push_back(vector<index_t>());
154  if (3>vidx.size()) continue;
155 
156  vector<vec3> pts3d;
157  FOR(ivert, vidx.size()) {
158  pts3d.push_back(X(m_)[vidx[ivert]]);
159  }
160 
161  pts3d.push_back(X(m_)[v_]);
162 
163  vec3 nrm = Poly3d(pts3d).normal();
164  if (nrm.length()<1e-10) nrm = vec3(0,0,1); // ça va, si c'est un polygon degenere, prenons un truc au pif
165 
166  Basis3d b(nrm);
167  pts3d.pop_back(); // v_ was useful for computing the normal, removing it for the triangulation
168 
169  vector<vec2> pts2d;
170  FOR(ivert, pts3d.size()) {
171  pts2d.push_back(b.project_xy(pts3d[ivert]));
172  }
173 
174  vector<index_t> tri_local_indices;
175  if (!Poly2d(pts2d).try_triangulate_minweight(tri_local_indices)) {
176  error("was not able to triangulate");
177 // tri_local_indices.clear();
178  result = false;
179  }
180 
181  FOR(ivert, tri_local_indices.size()) {
182  triangles.back().push_back(vidx[tri_local_indices[ivert]]);
183  }
184 
185  geo_assert(0 == triangles.back().size() % 3);
186  }
187  return result;
188  }
189 
190  TrFanElt& operator[](int i) {
191  geo_assert(i >= 0 && i < int(fan.size()));
192  return fan[i];
193  }
194 
195  TrFanElt& operator[](index_t i) {
196  geo_assert(i < fan.size());
197  return fan[i];
198  }
199 
200  index_t nb_fan_triangles() {
201  return index_t(fan.size());
202  }
203 
204  vector<vector<index_t> > triangles;
205  vector<TrFanElt> fan;
206  vector<int> chart_offset;
207 
208  Mesh *m_;
209  index_t v_;
210  bool incomplete_;
211  };
212 
213  vector<vector<index_t> > generate_v2f(Mesh *m);
214  bool find_self_intersections(Mesh* facets_with_quads_and_tri_only, vector<index_t> &intersections);
215  bool lock_self_intersecting_regions(Mesh* facets_with_quads_and_tri_only, vector<BBox>& regions_to_lock);
216  bool lock_self_intersecting_regions(Mesh* facets_with_quads_and_tri_only, Attribute<bool> &verts_to_remove, Attribute<index_t> &undo);
217  bool try_simplify(Mesh* m, Attribute<index_t> &chart, Attribute<bool> &verts_to_remove, Attribute<index_t> &undo);
218 }
219 
220 #endif
#define geo_assert_not_reached
Sets a non reachable point in the program.
Definition: assert.h:177
#define geo_assert(x)
Verifies that a condition is met.
Definition: assert.h:149
static std::ostream & out(const std::string &feature)
Gets the stream to send information messages.
index_t vertex(index_t f, index_t lv) const
Gets a vertex by facet and local vertex index.
Definition: mesh.h:1054
index_t nb_vertices(index_t f) const
Gets the number of vertices of a facet.
Definition: mesh.h:1043
AttributesManager & attributes() const
Gets the attributes manager.
Definition: mesh.h:100
Represents a mesh.
Definition: mesh.h:2701
Vector with aligned memory allocation.
Definition: memory.h:635
index_t size() const
Gets the number of elements.
Definition: memory.h:674
Included by all headers in exploragram.
The class that represents a mesh.
Global Vorpaline namespace.
Definition: basic.h:55
vecng< 3, Numeric::float64 > vec3
Represents points and vectors in 3d.
Definition: geometry.h:65
geo_index_t index_t
The type for storing and manipulating indices.
Definition: numeric.h:329