aimstil  5.0.5
mesh_decimation.tpp
Go to the documentation of this file.
1 #ifndef TIL_MESH_DECIMATION_TPP_
2 #define TIL_MESH_DECIMATION_TPP_
3 
4 #include "til/miscTools.h"
5 
6 namespace til
7 {
8 
9  //-------------------------------------------------------------------------------------------
10 
11  namespace
12  {
13 
14  template < typename TFaces, typename TPoints, typename TNeighbors >
15  void remove_delaunay_faces(TFaces & faces, TNeighbors & neighbors, const TPoints & points)
16  {
17  typename TFaces::iterator f = faces.begin();
18  while (f != faces.end())
19  {
20  if (til::geo::is_in_circumcircle<double>(points[i], points[(*f)[0]], points[(*f)[1]], points[(*f)[2]]))
21  {
22  neighbors.insert((*f)[0]);
23  neighbors.insert((*f)[1]);
24  neighbors.insert((*f)[2]);
25  f = faces.erase(f);
26  }
27  else
28  {
29  ++f;
30  }
31  }
32  }
33 
34  } // namespace
35 
36  template < typename TFace >
37  std::list<boost::array<std::size_t,3> >
38  SimpleDelaunayTriangulation::operator()(std::vector<til::numeric_array<float, 2> > points)
39  {
40  typedef std::vector<til::numeric_array<float, 2> > Points;
41  typedef TFace Face;
42  typedef std::list<Face> FaceList;
43 
44  // Don't waste time calling this for less than 4 points.
45  assert(points.size() >= 4);
46 
47  FaceList faces;
48 
49  // compute bounding triangle and add points to list
50  bounding_triangle(points.begin(), points.end(), std::back_inserter(points));
51  // add triangle to list
52  boost::array<std::size_t,3> face = { points.size()-1, points.size()-2, points.size()-3 };
53  faces.push_back(face);
54 
55  for (std::size_t i = 0; i < n; ++i)
56  {
57  // Remove triangles if we lie in their circumcircle, and collect their vertex.
58  std::set<std::size_t> neighbors;
59  remove_delaunay_faces(faces, neighbors, points);
60  {
61  FaceList::iterator f = faces.begin();
62  while (f != faces.end())
63  {
64  if (til::geo::is_in_circumcircle<double>(points[i], points[(*f)[0]], points[(*f)[1]], points[(*f)[2]]))
65  {
66  neighbors.insert((*f)[0]);
67  neighbors.insert((*f)[1]);
68  neighbors.insert((*f)[2]);
69  f = faces.erase(f);
70  }
71  else
72  {
73  ++f;
74  }
75  }
76  }
77 
78  assert(neighbors.size() >= 3);
79 
80  // order neighbors according to the angle they make with the current point
81 
82  std::vector<Temp> tmp;
83  tmp.reserve(neighbors.size());
84  for (std::set<std::size_t>::iterator iNeighbor = neighbors.begin(); iNeighbor != neighbors.end(); ++iNeighbor)
85  {
86  Temp t;
87  t.index = *iNeighbor;
88  til::numeric_array<float,2> v = points[*iNeighbor]-points[i];
89  t.angle = til::geo::angle(v[0], v[1]);
90  tmp.push_back(t);
91  }
92  //std::sort(tmp.begin(), tmp.end(), TempComp());
93  std::sort(tmp.begin(), tmp.end());
94 
95  // Form new faces
96  for (std::size_t it = 0; it < tmp.size(); ++it)
97  {
98  //std::cout << "Adding face " << i << " " << tmp[it].index << " " << tmp[ (it+1) % til::size(tmp) ].index << std::endl;
99  Face face = {i, tmp[it].index, tmp[ (it+1) % til::size(tmp) ].index };
100  faces.push_back(face);
101  }
102  }
103  /*
104  {
105  std::cout << "faces" << std::endl;
106  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
107  {
108  std::cout << (*f)[0] << " " << (*f)[1] << " " << (*f)[2] << std::endl;
109  }
110  std::cout << "endfaces" << std::endl;
111  }
112  */
113 
114  // Remove extra faces
115  {
116  FaceList::iterator f = faces.begin();
117  while (f != faces.end())
118  {
119  // Remove faces with supertriangle vertex
120  if ((*f)[0] >= n ||
121  (*f)[1] >= n ||
122  (*f)[2] >= n)
123  {
124  f = faces.erase(f);
125  }
126  else
127  {
128  ++f;
129  }
130  }
131  }
132  /*
133  {
134  FaceList::iterator f = faces.begin();
135  std::cout << "cross2D: " << til::cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) << std::endl;
136  }
137  */
138 
139  // Check that normals are ok
140  {
141  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
142  {
143  if (til::cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) < 0)
144  {
145  std::cout << "wS!";
146  }
147  }
148  }
149 
150 
151  // Check if we have to resort to normal testing to remove faces
152  if (faces.size() != n-2)
153  {
154  /*
155  std::cout << "NI!" << faces.size() << "-" << n << std::endl;
156  {
157  std::cout << "faces2" << std::endl;
158  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
159  {
160  std::cout << (*f)[0] << " " << (*f)[1] << " " << (*f)[2] << std::endl;
161  }
162  std::cout << "endfaces" << std::endl;
163  }
164  */
165 
166  // Remove faces with bad normal
167  /*
168  {
169  FaceList::iterator f = faces.begin();
170  while (f != faces.end())
171  {
172  if (til::cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) < 0)
173  {
174  f = faces.erase(f);
175  }
176  else
177  {
178  ++f;
179  }
180  }
181  }
182  */
183 
184  {
185  FaceList::iterator f = faces.begin();
186  while (f != faces.end())
187  {
188  bool flagdel = false;
189  int count = 0;
190  for (int i = 0; i < 3; ++i)
191  {
192  if ((*f)[i] > (*f)[(i+1)%3])
193  {
194  if (++count > 1)
195  {
196  flagdel = true;
197  //f = faces.erase(f);
198  break;
199  }
200  }
201  }
202  if (flagdel) f = faces.erase(f);
203  else ++f;
204  }
205  }
206 
207  // Check again that we have the expected number of faces
208  if (faces.size() != n-2)
209  {
210  std::cout << "NI2!" << faces.size() << "-" << n << std::endl;
211  {
212  std::cout << "faces2" << std::endl;
213  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
214  {
215  std::cout << (*f)[0] << " " << (*f)[1] << " " << (*f)[2] << std::endl;
216  }
217  std::cout << "endfaces" << std::endl;
218  std::cout << "points" << std::endl;
219  for (std::size_t i = 0; i < n; ++i) std::cout << points[i] << std::endl;
220  std::cout << "end points" << std::endl;
221  }
222  }
223  }
224 
225  // check that all outer edges is missing
226  {
227  std::set<boost::array<std::size_t,2> > outer_edges;
228  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
229  {
230  for (std::size_t i = 0; i < 3; ++i)
231  {
232  std::size_t delta = std::abs(int((*f)[i]) - int((*f)[(i+1)%3]));
233  if (delta == 1 || delta == (n-1))
234  {
235  boost::array<std::size_t,2> tmp = {min((*f)[i], (*f)[(i+1)%3]), max((*f)[i], (*f)[(i+1)%3])};
236  outer_edges.insert(tmp);
237  }
238  }
239  }
240  if (outer_edges.size() != n)
241  {
242  std::cout << "wU!";
243  }
244  }
245 
246  //exit(0);
247 
248  /*
249  std::cout << "nfaces: " << til::size(faces) << std::endl;
250  for (FaceList::const_iterator i = faces.begin(); i != faces.end(); ++i)
251  {
252  std::cout << (*i)[0] << " " << (*i)[1] << " " << (*i)[2] << std::endl;
253  }
254  */
255  return faces;
256  }
257 
258 
259 
260 } // namespace til
261 
262 #endif /*MESH_DECIMATION_TPP_*/