1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef TrenchBroom_Polyhedron_Misc_h
21 #define TrenchBroom_Polyhedron_Misc_h
22 
23 #include <map>
24 
25 template <typename T, typename FP, typename VP>
26 class Polyhedron<T,FP,VP>::VertexDistanceCmp {
27 private:
28     V m_anchor;
29 public:
VertexDistanceCmp(const V & anchor)30     VertexDistanceCmp(const V& anchor) :
31     m_anchor(anchor) {}
32 
operator()33     bool operator()(const Vertex* lhs, const Vertex* rhs) const {
34         const T lDist = m_anchor.squaredDistanceTo(lhs->position());
35         const T rDist = m_anchor.squaredDistanceTo(rhs->position());
36         if (lDist < rDist)
37             return true;
38         if (lDist > rDist)
39             return false;
40         return lhs->position().compare(rhs->position()) < 0;
41     }
42 };
43 
44 
45 template <typename T, typename FP, typename VP>
operator()46 const typename Polyhedron<T,FP,VP>::V& Polyhedron<T,FP,VP>::GetVertexPosition::operator()(const Vertex* vertex) const {
47     return vertex->position();
48 }
49 
50 template <typename T, typename FP, typename VP>
operator()51 const typename Polyhedron<T,FP,VP>::V& Polyhedron<T,FP,VP>::GetVertexPosition::operator()(const HalfEdge* halfEdge) const {
52     return halfEdge->origin()->position();
53 }
54 
55 template <typename T, typename FP, typename VP>
~Callback()56 Polyhedron<T,FP,VP>::Callback::~Callback() {}
57 
58 template <typename T, typename FP, typename VP>
plane(const Face * face)59 Plane<T,3> Polyhedron<T,FP,VP>::Callback::plane(const Face* face) const {
60     const HalfEdgeList& boundary = face->boundary();
61     assert(boundary.size() >= 3);
62 
63     const HalfEdge* e1 = boundary.front();
64     const HalfEdge* e2 = e1->next();
65     const HalfEdge* e3 = e2->next();
66 
67     const V& p1 = e1->origin()->position();
68     const V& p2 = e2->origin()->position();
69     const V& p3 = e3->origin()->position();
70 
71     Plane<T,3> plane;
72     assertResult(setPlanePoints(plane, p2, p1, p3));
73     return plane;
74 }
75 
76 template <typename T, typename FP, typename VP>
faceWasCreated(Face * face)77 void Polyhedron<T,FP,VP>::Callback::faceWasCreated(Face* face) {}
78 
79 template <typename T, typename FP, typename VP>
faceWillBeDeleted(Face * face)80 void Polyhedron<T,FP,VP>::Callback::faceWillBeDeleted(Face* face) {}
81 
82 template <typename T, typename FP, typename VP>
faceDidChange(Face * face)83 void Polyhedron<T,FP,VP>::Callback::faceDidChange(Face* face) {}
84 
85 template <typename T, typename FP, typename VP>
faceWasSplit(Face * original,Face * clone)86 void Polyhedron<T,FP,VP>::Callback::faceWasSplit(Face* original, Face* clone) {}
87 
88 template <typename T, typename FP, typename VP>
facesWillBeMerged(Face * remaining,Face * toDelete)89 void Polyhedron<T,FP,VP>::Callback::facesWillBeMerged(Face* remaining, Face* toDelete) {}
90 
91 template <typename T, typename FP, typename VP>
Polyhedron()92 Polyhedron<T,FP,VP>::Polyhedron() {
93     updateBounds();
94 }
95 
96 template <typename T, typename FP, typename VP>
Polyhedron(const V & p1,const V & p2,const V & p3,const V & p4)97 Polyhedron<T,FP,VP>::Polyhedron(const V& p1, const V& p2, const V& p3, const V& p4) {
98     Callback c;
99     addPoints(p1, p2, p3, p4, c);
100 }
101 
102 template <typename T, typename FP, typename VP>
Polyhedron(const V & p1,const V & p2,const V & p3,const V & p4,Callback & callback)103 Polyhedron<T,FP,VP>::Polyhedron(const V& p1, const V& p2, const V& p3, const V& p4, Callback& callback) {
104     addPoints(p1, p2, p3, p4, callback);
105 }
106 
107 template <typename T, typename FP, typename VP>
Polyhedron(const BBox<T,3> & bounds)108 Polyhedron<T,FP,VP>::Polyhedron(const BBox<T,3>& bounds) {
109     Callback c;
110     setBounds(bounds, c);
111 }
112 
113 template <typename T, typename FP, typename VP>
Polyhedron(const BBox<T,3> & bounds,Callback & callback)114 Polyhedron<T,FP,VP>::Polyhedron(const BBox<T,3>& bounds, Callback& callback) {
115     setBounds(bounds, callback);
116 }
117 
118 template <typename T, typename FP, typename VP>
Polyhedron(const typename V::List & positions)119 Polyhedron<T,FP,VP>::Polyhedron(const typename V::List& positions) {
120     Callback c;
121     addPoints(positions.begin(), positions.end(), c);
122 }
123 
124 template <typename T, typename FP, typename VP>
Polyhedron(const typename V::List & positions,Callback & callback)125 Polyhedron<T,FP,VP>::Polyhedron(const typename V::List& positions, Callback& callback) {
126     addPoints(positions.begin(), positions.end(), callback);
127 }
128 
129 template <typename T, typename FP, typename VP>
Polyhedron(const typename V::Set & positions)130 Polyhedron<T,FP,VP>::Polyhedron(const typename V::Set& positions) {
131     Callback c;
132     addPoints(positions.begin(), positions.end(), c);
133 }
134 
135 template <typename T, typename FP, typename VP>
Polyhedron(const typename V::Set & positions,Callback & callback)136 Polyhedron<T,FP,VP>::Polyhedron(const typename V::Set& positions, Callback& callback) {
137     addPoints(positions.begin(), positions.end(), callback);
138 }
139 
140 template <typename T, typename FP, typename VP>
addPoints(const V & p1,const V & p2,const V & p3,const V & p4,Callback & callback)141 void Polyhedron<T,FP,VP>::addPoints(const V& p1, const V& p2, const V& p3, const V& p4, Callback& callback) {
142     addPoint(p1, callback);
143     addPoint(p2, callback);
144     addPoint(p3, callback);
145     addPoint(p4, callback);
146 }
147 
148 template <typename T, typename FP, typename VP>
setBounds(const BBox<T,3> & bounds,Callback & callback)149 void Polyhedron<T,FP,VP>::setBounds(const BBox<T,3>& bounds, Callback& callback) {
150     if (bounds.min == bounds.max) {
151         addPoint(bounds.min);
152         return;
153     }
154 
155     // Explicitely create the polyhedron for better performance when building brushes.
156 
157     const V p1(bounds.min.x(), bounds.min.y(), bounds.min.z());
158     const V p2(bounds.min.x(), bounds.min.y(), bounds.max.z());
159     const V p3(bounds.min.x(), bounds.max.y(), bounds.min.z());
160     const V p4(bounds.min.x(), bounds.max.y(), bounds.max.z());
161     const V p5(bounds.max.x(), bounds.min.y(), bounds.min.z());
162     const V p6(bounds.max.x(), bounds.min.y(), bounds.max.z());
163     const V p7(bounds.max.x(), bounds.max.y(), bounds.min.z());
164     const V p8(bounds.max.x(), bounds.max.y(), bounds.max.z());
165 
166     Vertex* v1 = new Vertex(p1);
167     Vertex* v2 = new Vertex(p2);
168     Vertex* v3 = new Vertex(p3);
169     Vertex* v4 = new Vertex(p4);
170     Vertex* v5 = new Vertex(p5);
171     Vertex* v6 = new Vertex(p6);
172     Vertex* v7 = new Vertex(p7);
173     Vertex* v8 = new Vertex(p8);
174 
175     m_vertices.append(v1, 1);
176     m_vertices.append(v2, 1);
177     m_vertices.append(v3, 1);
178     m_vertices.append(v4, 1);
179     m_vertices.append(v5, 1);
180     m_vertices.append(v6, 1);
181     m_vertices.append(v7, 1);
182     m_vertices.append(v8, 1);
183 
184     // Front face
185     HalfEdge* f1h1 = new HalfEdge(v1);
186     HalfEdge* f1h2 = new HalfEdge(v5);
187     HalfEdge* f1h3 = new HalfEdge(v6);
188     HalfEdge* f1h4 = new HalfEdge(v2);
189     HalfEdgeList f1b;
190     f1b.append(f1h1, 1);
191     f1b.append(f1h2, 1);
192     f1b.append(f1h3, 1);
193     f1b.append(f1h4, 1);
194     m_faces.append(new Face(f1b), 1);
195 
196     // Left face
197     HalfEdge* f2h1 = new HalfEdge(v1);
198     HalfEdge* f2h2 = new HalfEdge(v2);
199     HalfEdge* f2h3 = new HalfEdge(v4);
200     HalfEdge* f2h4 = new HalfEdge(v3);
201     HalfEdgeList f2b;
202     f2b.append(f2h1, 1);
203     f2b.append(f2h2, 1);
204     f2b.append(f2h3, 1);
205     f2b.append(f2h4, 1);
206     m_faces.append(new Face(f2b), 1);
207 
208     // Bottom face
209     HalfEdge* f3h1 = new HalfEdge(v1);
210     HalfEdge* f3h2 = new HalfEdge(v3);
211     HalfEdge* f3h3 = new HalfEdge(v7);
212     HalfEdge* f3h4 = new HalfEdge(v5);
213     HalfEdgeList f3b;
214     f3b.append(f3h1, 1);
215     f3b.append(f3h2, 1);
216     f3b.append(f3h3, 1);
217     f3b.append(f3h4, 1);
218     m_faces.append(new Face(f3b), 1);
219 
220     // Top face
221     HalfEdge* f4h1 = new HalfEdge(v2);
222     HalfEdge* f4h2 = new HalfEdge(v6);
223     HalfEdge* f4h3 = new HalfEdge(v8);
224     HalfEdge* f4h4 = new HalfEdge(v4);
225     HalfEdgeList f4b;
226     f4b.append(f4h1, 1);
227     f4b.append(f4h2, 1);
228     f4b.append(f4h3, 1);
229     f4b.append(f4h4, 1);
230     m_faces.append(new Face(f4b), 1);
231 
232     // Back face
233     HalfEdge* f5h1 = new HalfEdge(v3);
234     HalfEdge* f5h2 = new HalfEdge(v4);
235     HalfEdge* f5h3 = new HalfEdge(v8);
236     HalfEdge* f5h4 = new HalfEdge(v7);
237     HalfEdgeList f5b;
238     f5b.append(f5h1, 1);
239     f5b.append(f5h2, 1);
240     f5b.append(f5h3, 1);
241     f5b.append(f5h4, 1);
242     m_faces.append(new Face(f5b), 1);
243 
244     // Right face
245     HalfEdge* f6h1 = new HalfEdge(v5);
246     HalfEdge* f6h2 = new HalfEdge(v7);
247     HalfEdge* f6h3 = new HalfEdge(v8);
248     HalfEdge* f6h4 = new HalfEdge(v6);
249     HalfEdgeList f6b;
250     f6b.append(f6h1, 1);
251     f6b.append(f6h2, 1);
252     f6b.append(f6h3, 1);
253     f6b.append(f6h4, 1);
254     m_faces.append(new Face(f6b), 1);
255 
256     m_edges.append(new Edge(f1h4, f2h1), 1); // v1, v2
257     m_edges.append(new Edge(f2h4, f3h1), 1); // v1, v3
258     m_edges.append(new Edge(f1h1, f3h4), 1); // v1, v5
259     m_edges.append(new Edge(f2h2, f4h4), 1); // v2, v4
260     m_edges.append(new Edge(f4h1, f1h3), 1); // v2, v6
261     m_edges.append(new Edge(f2h3, f5h1), 1); // v3, v4
262     m_edges.append(new Edge(f3h2, f5h4), 1); // v3, v7
263     m_edges.append(new Edge(f4h3, f5h2), 1); // v4, v8
264     m_edges.append(new Edge(f1h2, f6h4), 1); // v5, v6
265     m_edges.append(new Edge(f6h1, f3h3), 1); // v5, v7
266     m_edges.append(new Edge(f6h3, f4h2), 1); // v6, v8
267     m_edges.append(new Edge(f6h2, f5h3), 1); // v7, v8
268 }
269 
270 template <typename T, typename FP, typename VP>
271 class Polyhedron<T,FP,VP>::Copy {
272 private:
273     typedef std::map<const Vertex*, Vertex*> VertexMap;
274     typedef typename VertexMap::value_type VertexMapEntry;
275 
276     typedef std::map<const HalfEdge*, HalfEdge*> HalfEdgeMap;
277     typedef typename HalfEdgeMap::value_type HalfEdgeMapEntry;
278 
279     VertexMap m_vertexMap;
280     HalfEdgeMap m_halfEdgeMap;
281 
282     VertexList m_vertices;
283     EdgeList m_edges;
284     FaceList m_faces;
285     Polyhedron& m_destination;
286 public:
Copy(const FaceList & originalFaces,const EdgeList & originalEdges,Polyhedron & destination)287     Copy(const FaceList& originalFaces, const EdgeList& originalEdges, Polyhedron& destination) :
288     m_destination(destination) {
289         copyFaces(originalFaces);
290         copyEdges(originalEdges);
291         swapContents();
292     }
293 private:
copyFaces(const FaceList & originalFaces)294     void copyFaces(const FaceList& originalFaces) {
295         typename FaceList::const_iterator fIt, fEnd;
296         for (fIt = originalFaces.begin(), fEnd = originalFaces.end(); fIt != fEnd; ++fIt) {
297             const Face* originalFace = *fIt;
298             copyFace(originalFace);
299         }
300     }
301 
copyFace(const Face * originalFace)302     void copyFace(const Face* originalFace) {
303         HalfEdgeList myBoundary;
304 
305         typename HalfEdgeList::const_iterator hIt, hEnd;
306         for (hIt = originalFace->m_boundary.begin(), hEnd = originalFace->m_boundary.end(); hIt != hEnd; ++hIt) {
307             const HalfEdge* originalHalfEdge = *hIt;
308             myBoundary.append(copyHalfEdge(originalHalfEdge), 1);
309         }
310 
311         Face* copy = new Face(myBoundary);
312         m_faces.append(copy, 1);
313     }
314 
copyHalfEdge(const HalfEdge * original)315     HalfEdge* copyHalfEdge(const HalfEdge* original) {
316         const Vertex* originalOrigin = original->origin();
317 
318         Vertex* myOrigin = findOrCopyVertex(originalOrigin);
319         HalfEdge* copy = new HalfEdge(myOrigin);
320         m_halfEdgeMap.insert(std::make_pair(original, copy));
321         return copy;
322     }
323 
findOrCopyVertex(const Vertex * original)324     Vertex* findOrCopyVertex(const Vertex* original) {
325         typedef std::pair<bool, typename VertexMap::iterator> InsertPos;
326 
327         InsertPos insertPos = MapUtils::findInsertPos(m_vertexMap, original);
328         if (!insertPos.first) {
329             Vertex* copy = new Vertex(original->position());
330             m_vertices.append(copy, 1);
331             m_vertexMap.insert(insertPos.second, std::make_pair(original, copy));
332             return copy;
333         }
334         return insertPos.second->second;
335     }
336 
copyEdges(const EdgeList & originalEdges)337     void copyEdges(const EdgeList& originalEdges) {
338         typename EdgeList::const_iterator eIt, eEnd;
339         for (eIt = originalEdges.begin(), eEnd = originalEdges.end(); eIt != eEnd; ++eIt) {
340             const Edge* originalEdge = *eIt;
341             Edge* copy = copyEdge(originalEdge);
342             m_edges.append(copy, 1);
343         }
344     }
345 
copyEdge(const Edge * original)346     Edge* copyEdge(const Edge* original) const {
347         HalfEdge* myFirst = findHalfEdge(original->firstEdge());
348         if (!original->fullySpecified())
349             return new Edge(myFirst);
350 
351         HalfEdge* mySecond = findHalfEdge(original->secondEdge());
352         return new Edge(myFirst, mySecond);
353     }
354 
findHalfEdge(const HalfEdge * original)355     HalfEdge* findHalfEdge(const HalfEdge* original) const {
356         HalfEdge* result = MapUtils::find(m_halfEdgeMap, original, static_cast<HalfEdge*>(NULL));
357         assert(result != NULL);
358         return result;
359     }
360 
swapContents()361     void swapContents() {
362         using std::swap;
363         swap(m_vertices, m_destination.m_vertices);
364         swap(m_edges, m_destination.m_edges);
365         swap(m_faces, m_destination.m_faces);
366         m_destination.updateBounds();
367     }
368 };
369 
370 template <typename T, typename FP, typename VP>
Polyhedron(const Polyhedron<T,FP,VP> & other)371 Polyhedron<T,FP,VP>::Polyhedron(const Polyhedron<T,FP,VP>& other) {
372     Copy copy(other.faces(), other.edges(), *this);
373 }
374 
375 template <typename T, typename FP, typename VP>
~Polyhedron()376 Polyhedron<T,FP,VP>::~Polyhedron() {
377     clear();
378 }
379 
380 template <typename T, typename FP, typename VP>
381 Polyhedron<T,FP,VP>& Polyhedron<T,FP,VP>::operator=(Polyhedron<T,FP,VP> other) {
382     swap(*this, other);
383     return *this;
384 }
385 
386 template <typename T, typename FP, typename VP>
vertexCount()387 size_t Polyhedron<T,FP,VP>::vertexCount() const {
388     return m_vertices.size();
389 }
390 
391 template <typename T, typename FP, typename VP>
vertices()392 const typename Polyhedron<T,FP,VP>::VertexList& Polyhedron<T,FP,VP>::vertices() const {
393     return m_vertices;
394 }
395 
396 template <typename T, typename FP, typename VP>
hasVertex(const V & position,const T epsilon)397 bool Polyhedron<T,FP,VP>::hasVertex(const V& position, const T epsilon) const {
398     return findVertexByPosition(position, NULL, epsilon) != NULL;
399 }
400 
401 template <typename T, typename FP, typename VP>
hasVertices(const typename V::List & positions,const T epsilon)402 bool Polyhedron<T,FP,VP>::hasVertices(const typename V::List& positions, const T epsilon) const {
403     if (positions.size() != vertexCount())
404         return false;
405     typename V::List::const_iterator it, end;
406     for (it = positions.begin(), end = positions.end(); it != end; ++it) {
407         if (!hasVertex(*it, epsilon))
408             return false;
409     }
410     return true;
411 }
412 
413 template <typename T, typename FP, typename VP>
printVertices()414 void Polyhedron<T,FP,VP>::printVertices() const {
415     const Vertex* firstVertex = m_vertices.front();
416     const Vertex* currentVertex = firstVertex;
417     do {
418         std::cout << currentVertex->position().asString() << std::endl;
419         currentVertex = currentVertex->next();
420     } while (currentVertex != firstVertex);
421 }
422 
423 
424 template <typename T, typename FP, typename VP>
edgeCount()425 size_t Polyhedron<T,FP,VP>::edgeCount() const {
426     return m_edges.size();
427 }
428 
429 template <typename T, typename FP, typename VP>
edges()430 const typename Polyhedron<T,FP,VP>::EdgeList& Polyhedron<T,FP,VP>::edges() const {
431     return m_edges;
432 }
433 
434 template <typename T, typename FP, typename VP>
hasEdge(const V & pos1,const V & pos2,const T epsilon)435 bool Polyhedron<T,FP,VP>::hasEdge(const V& pos1, const V& pos2, const T epsilon) const {
436     return findEdgeByPositions(pos1, pos2, epsilon) != NULL;
437 }
438 
439 template <typename T, typename FP, typename VP>
faceCount()440 size_t Polyhedron<T,FP,VP>::faceCount() const {
441     return m_faces.size();
442 }
443 
444 template <typename T, typename FP, typename VP>
faces()445 const typename Polyhedron<T,FP,VP>::FaceList& Polyhedron<T,FP,VP>::faces() const {
446     return m_faces;
447 }
448 
449 template <typename T, typename FP, typename VP>
hasFace(const typename V::List & positions,const T epsilon)450 bool Polyhedron<T,FP,VP>::hasFace(const typename V::List& positions, const T epsilon) const {
451     return findFaceByPositions(positions, epsilon) != NULL;
452 }
453 
454 template <typename T, typename FP, typename VP>
bounds()455 const BBox<T,3>& Polyhedron<T,FP,VP>::bounds() const {
456     return m_bounds;
457 }
458 
459 template <typename T, typename FP, typename VP>
empty()460 bool Polyhedron<T,FP,VP>::empty() const {
461     return vertexCount() == 0;
462 }
463 
464 template <typename T, typename FP, typename VP>
point()465 bool Polyhedron<T,FP,VP>::point() const {
466     return vertexCount() == 1;
467 }
468 
469 template <typename T, typename FP, typename VP>
edge()470 bool Polyhedron<T,FP,VP>::edge() const {
471     return vertexCount() == 2;
472 }
473 
474 template <typename T, typename FP, typename VP>
polygon()475 bool Polyhedron<T,FP,VP>::polygon() const {
476     return faceCount() == 1;
477 }
478 
479 template <typename T, typename FP, typename VP>
polyhedron()480 bool Polyhedron<T,FP,VP>::polyhedron() const {
481     return faceCount() > 3;
482 }
483 
484 template <typename T, typename FP, typename VP>
closed()485 bool Polyhedron<T,FP,VP>::closed() const {
486     return vertexCount() + faceCount() == edgeCount() + 2;
487 }
488 
489 template <typename T, typename FP, typename VP>
clear()490 void Polyhedron<T,FP,VP>::clear() {
491     m_faces.clear();
492     m_edges.clear();
493     m_vertices.clear();
494 }
495 
496 template <typename T, typename FP, typename VP>
FaceHit(Face * i_face,const T i_distance)497 Polyhedron<T,FP,VP>::FaceHit::FaceHit(Face* i_face, const T i_distance) : face(i_face), distance(i_distance) {}
498 
499 template <typename T, typename FP, typename VP>
FaceHit()500 Polyhedron<T,FP,VP>::FaceHit::FaceHit() : face(NULL), distance(Math::nan<T>()) {}
501 
502 template <typename T, typename FP, typename VP>
isMatch()503 bool Polyhedron<T,FP,VP>::FaceHit::isMatch() const { return face != NULL; }
504 
505 template <typename T, typename FP, typename VP>
pickFace(const Ray<T,3> & ray)506 typename Polyhedron<T,FP,VP>::FaceHit Polyhedron<T,FP,VP>::pickFace(const Ray<T,3>& ray) const {
507     const Math::Side side = polygon() ? Math::Side_Both : Math::Side_Front;
508     Face* firstFace = m_faces.front();
509     Face* currentFace = firstFace;
510     do {
511         const T distance = currentFace->intersectWithRay(ray, side);
512         if (!Math::isnan(distance))
513             return FaceHit(currentFace, distance);
514         currentFace = currentFace->next();
515     } while (currentFace != firstFace);
516     return FaceHit();
517 }
518 
519 template <typename T, typename FP, typename VP>
findVertexByPosition(const V & position,const Vertex * except,const T epsilon)520 typename Polyhedron<T,FP,VP>::Vertex* Polyhedron<T,FP,VP>::findVertexByPosition(const V& position, const Vertex* except, const T epsilon) const {
521     Vertex* firstVertex = m_vertices.front();
522     Vertex* currentVertex = firstVertex;
523     do {
524         if (currentVertex != except && position.equals(currentVertex->position(), epsilon))
525             return currentVertex;
526         currentVertex = currentVertex->next();
527     } while (currentVertex != firstVertex);
528     return NULL;
529 }
530 
531 template <typename T, typename FP, typename VP>
findClosestVertex(const V & position)532 typename Polyhedron<T,FP,VP>::Vertex* Polyhedron<T,FP,VP>::findClosestVertex(const V& position) const {
533     T closestDistance = std::numeric_limits<T>::max();
534     Vertex* closestVertex = NULL;
535 
536     Vertex* firstVertex = m_vertices.front();
537     Vertex* currentVertex = firstVertex;
538     do {
539         const T distance = position.squaredDistanceTo(currentVertex->position());
540         if (distance < closestDistance) {
541             closestDistance = distance;
542             closestVertex = currentVertex;
543         }
544         currentVertex = currentVertex->next();
545     } while (currentVertex != firstVertex);
546     return closestVertex;
547 }
548 
549 template <typename T, typename FP, typename VP>
findClosestVertices(const V & position)550 typename Polyhedron<T,FP,VP>::ClosestVertexSet Polyhedron<T,FP,VP>::findClosestVertices(const V& position) const {
551     ClosestVertexSet result = ClosestVertexSet(VertexDistanceCmp(position));
552     Vertex* firstVertex = m_vertices.front();
553     Vertex* currentVertex = firstVertex;
554     do {
555         result.insert(currentVertex);
556         currentVertex = currentVertex->next();
557     } while (currentVertex != firstVertex);
558     return result;
559 }
560 
561 template <typename T, typename FP, typename VP>
findEdgeByPositions(const V & pos1,const V & pos2,const T epsilon)562 typename Polyhedron<T,FP,VP>::Edge* Polyhedron<T,FP,VP>::findEdgeByPositions(const V& pos1, const V& pos2, const T epsilon) const {
563     Edge* firstEdge = m_edges.front();
564     Edge* currentEdge = firstEdge;
565     do {
566         currentEdge = currentEdge->next();
567         if (currentEdge->hasPositions(pos1, pos2, epsilon))
568             return currentEdge;
569     } while (currentEdge != firstEdge);
570     return NULL;
571 }
572 
573 template <typename T, typename FP, typename VP>
findFaceByPositions(const typename V::List & positions,const T epsilon)574 typename Polyhedron<T,FP,VP>::Face* Polyhedron<T,FP,VP>::findFaceByPositions(const typename V::List& positions, const T epsilon) const {
575     Face* firstFace = m_faces.front();
576     Face* currentFace = firstFace;
577     do {
578         if (currentFace->hasVertexPositions(positions, epsilon))
579             return currentFace;
580         currentFace = currentFace->next();
581     } while (currentFace != firstFace);
582     return NULL;
583 }
584 
585 template <typename T, typename FP, typename VP> template <typename O>
getVertexPositions(O output)586 void Polyhedron<T,FP,VP>::getVertexPositions(O output) const {
587     Vertex* firstVertex = m_vertices.front();
588     Vertex* currentVertex = firstVertex;
589     do {
590         output = currentVertex->position();
591         currentVertex = currentVertex->next();
592     } while (currentVertex != firstVertex);
593 }
594 
595 template <typename T, typename FP, typename VP>
hasVertex(const Vertex * vertex)596 bool Polyhedron<T,FP,VP>::hasVertex(const Vertex* vertex) const {
597     const Vertex* firstVertex = m_vertices.front();
598     const Vertex* currentVertex = firstVertex;
599     do {
600         if (currentVertex == vertex)
601             return true;
602         currentVertex = currentVertex->next();
603     } while (currentVertex != firstVertex);
604     return false;
605 }
606 
607 template <typename T, typename FP, typename VP>
hasEdge(const Edge * edge)608 bool Polyhedron<T,FP,VP>::hasEdge(const Edge* edge) const {
609     const Edge* firstEdge = m_edges.front();
610     const Edge* currentEdge = firstEdge;
611     do {
612         if (currentEdge == edge)
613             return true;
614         currentEdge = currentEdge->next();
615     } while (currentEdge != firstEdge);
616     return false;
617 }
618 
619 template <typename T, typename FP, typename VP>
hasFace(const Face * face)620 bool Polyhedron<T,FP,VP>::hasFace(const Face* face) const {
621     const Face* firstFace = m_faces.front();
622     const Face* currentFace = firstFace;
623     do {
624         if (currentFace == face)
625             return true;
626         currentFace = currentFace->next();
627     } while (currentFace != firstFace);
628     return false;
629 }
630 
631 template <typename T, typename FP, typename VP>
checkInvariant()632 bool Polyhedron<T,FP,VP>::checkInvariant() const {
633     /*
634     if (!checkConvex())
635         return false;
636      */
637     if (!checkFaceBoundaries())
638         return false;
639     if (polyhedron() && !checkClosed())
640         return false;
641     if (polyhedron() && !checkNoDegenerateFaces())
642         return false;
643     if (polyhedron() && !checkVertexLeavingEdges())
644         return false;
645     if (polyhedron() && !checkEdges())
646         return false;
647     /* This check leads to false positive with almost coplanar faces.
648     if (polyhedron() && !checkNoCoplanarFaces())
649         return false;
650      */
651     return true;
652 }
653 
654 template <typename T, typename FP, typename VP>
checkFaceBoundaries()655 bool Polyhedron<T,FP,VP>::checkFaceBoundaries() const {
656     if (m_faces.empty())
657         return true;
658     Face* first = m_faces.front();
659     Face* current = first;
660     do {
661         if (!current->checkBoundary())
662             return false;
663         current = current->next();
664     } while (current != first);
665     return true;
666 }
667 
668 template <typename T, typename FP, typename VP>
checkConvex()669 bool Polyhedron<T,FP,VP>::checkConvex() const {
670     typename FaceList::const_iterator fIt, fEnd;
671     for (fIt = m_faces.begin(), fEnd = m_faces.end(); fIt != fEnd; ++fIt) {
672         const Face* face = *fIt;
673         typename VertexList::const_iterator vIt, vEnd;
674         for (vIt = m_vertices.begin(), vEnd = m_vertices.end(); vIt != vEnd; ++vIt) {
675             const Vertex* vertex = *vIt;
676             if (face->pointStatus(vertex->position()) == Math::PointStatus::PSAbove)
677                 return false;
678         }
679     }
680     return true;
681 }
682 
683 template <typename T, typename FP, typename VP>
checkClosed()684 bool Polyhedron<T,FP,VP>::checkClosed() const {
685     typename EdgeList::const_iterator eIt, eEnd;
686     for (eIt = m_edges.begin(), eEnd = m_edges.end(); eIt != eEnd; ++eIt) {
687         const Edge* edge = *eIt;
688         if (!edge->fullySpecified())
689             return false;
690 
691         const Face* firstFace = edge->firstFace();
692         const Face* secondFace = edge->secondFace();
693 
694         if (!m_faces.contains(firstFace))
695             return false;
696         if (!m_faces.contains(secondFace))
697             return false;
698     }
699     return true;
700 }
701 
702 template <typename T, typename FP, typename VP>
checkNoCoplanarFaces()703 bool Polyhedron<T,FP,VP>::checkNoCoplanarFaces() const {
704     typename EdgeList::const_iterator eIt, eEnd;
705     for (eIt = m_edges.begin(), eEnd = m_edges.end(); eIt != eEnd; ++eIt) {
706         const Edge* edge = *eIt;
707         const Face* firstFace = edge->firstFace();
708         const Face* secondFace = edge->secondFace();
709 
710         if (firstFace == secondFace)
711             return false;
712         if (firstFace->coplanar(secondFace))
713             return false;
714     }
715     return true;
716 }
717 
718 template <typename T, typename FP, typename VP>
checkNoDegenerateFaces()719 bool Polyhedron<T,FP,VP>::checkNoDegenerateFaces() const {
720     typename FaceList::const_iterator fIt, fEnd;
721     for (fIt = m_faces.begin(), fEnd = m_faces.end(); fIt != fEnd; ++fIt) {
722         const Face* face = *fIt;
723         if (face->vertexCount() < 3)
724             return false;
725 
726         const HalfEdgeList& boundary = face->boundary();
727         typename HalfEdgeList::const_iterator hIt, hEnd;
728         for (hIt = boundary.begin(), hEnd = boundary.end(); hIt != hEnd; ++hIt) {
729             const HalfEdge* halfEdge = *hIt;
730             const Edge* edge = halfEdge->edge();
731 
732             if (edge == NULL || !edge->fullySpecified())
733                 return false;
734         }
735     }
736     return true;
737 }
738 
739 template <typename T, typename FP, typename VP>
checkVertexLeavingEdges()740 bool Polyhedron<T,FP,VP>::checkVertexLeavingEdges() const {
741     const Vertex* firstVertex = m_vertices.front();
742     const Vertex* currentVertex = firstVertex;
743     do {
744         const HalfEdge* leaving = currentVertex->leaving();
745         if (leaving == NULL)
746             return false;
747         if (leaving->origin() != currentVertex)
748             return false;
749         const Edge* edge = leaving->edge();
750         if (edge == NULL)
751             return false;
752         if (!edge->fullySpecified())
753             return false;
754         if (!hasEdge(edge))
755             return false;
756         currentVertex = currentVertex->next();
757     } while (currentVertex != firstVertex);
758     return true;
759 }
760 
761 template <typename T, typename FP, typename VP>
checkEdges()762 bool Polyhedron<T,FP,VP>::checkEdges() const {
763     if (m_edges.empty())
764         return true;
765 
766     Edge* firstEdge = m_edges.front();
767     Edge* currentEdge = firstEdge;
768     do {
769         if (!currentEdge->fullySpecified())
770             return false;
771         Face* firstFace = currentEdge->firstFace();
772         if (firstFace == NULL)
773             return false;
774         if (!m_faces.contains(firstFace))
775             return false;
776 
777         Face* secondFace = currentEdge->secondFace();
778         if (secondFace == NULL)
779             return false;
780         if (!m_faces.contains(secondFace))
781             return false;
782 
783         currentEdge = currentEdge->next();
784     } while (currentEdge != firstEdge);
785     return true;
786 }
787 
788 template <typename T, typename FP, typename VP>
checkEdgeLengths(const T minLength)789 bool Polyhedron<T,FP,VP>::checkEdgeLengths(const T minLength) const {
790     if (m_edges.empty())
791         return true;
792 
793     const T minLength2 = minLength * minLength;
794 
795     const Edge* firstEdge = m_edges.front();
796     const Edge* currentEdge = firstEdge;
797     do {
798         const T length2 = currentEdge->vector().squaredLength();
799         if (length2 < minLength2)
800             return false;
801         currentEdge = currentEdge->next();
802     } while (currentEdge != firstEdge);
803     return true;
804 }
805 
806 template <typename T, typename FP, typename VP>
correctVertexPositions(const size_t decimals,const T epsilon)807 void Polyhedron<T,FP,VP>::correctVertexPositions(const size_t decimals, const T epsilon) {
808     Vertex* firstVertex = m_vertices.front();
809     Vertex* currentVertex = firstVertex;
810     do {
811         currentVertex->correctPosition(decimals, epsilon);
812         currentVertex = currentVertex->next();
813     } while (currentVertex != firstVertex);
814 }
815 
816 template <typename T, typename FP, typename VP>
healEdges(const T minLength)817 bool Polyhedron<T,FP,VP>::healEdges(const T minLength) {
818     Callback callback;
819     return healEdges(callback, minLength);
820 }
821 
822 template <typename T, typename FP, typename VP>
healEdges(Callback & callback,const T minLength)823 bool Polyhedron<T,FP,VP>::healEdges(Callback& callback, const T minLength) {
824     const T minLength2 = minLength * minLength;
825 
826     /*
827      We have to iterate over all edges while the list of edges is being modified, so we cannot use the usual
828      do / while iteration. Instead, we count the number of edges we have examined - but since one or more edges
829      can be removed in every iteration, we have to correct that number for the decrease in the total number of
830      edges of the brush - this is where sizeDelta comes in. If no edges has been removed, it comes out as -1.
831      If one edge has been removed, it comes out as 0, if two edges have been removed, it comes out as +1, and so on.
832 
833      Since sizeDelta is subtracted from the number of examined edges, it corrects exactly for the change in the number
834      of edges of the brush.
835      */
836 
837     long examined = 0;
838     Edge* currentEdge = m_edges.front();
839     while (examined < static_cast<long>(m_edges.size()) && polyhedron()) {
840         const size_t oldSize = m_edges.size();
841 
842         const T length2 = currentEdge->vector().squaredLength();
843         if (length2 < minLength2)
844             currentEdge = removeEdge(currentEdge, callback);
845         else
846             currentEdge = currentEdge->next();
847 
848         const long sizeDelta = static_cast<long>(oldSize - m_edges.size()) - 1;
849         examined -= sizeDelta;
850     }
851 
852     assert(!polyhedron() || checkEdgeLengths(minLength));
853 
854     return polyhedron();
855 }
856 
857 template <typename T, typename FP, typename VP>
removeEdge(Edge * edge,Callback & callback)858 typename Polyhedron<T,FP,VP>::Edge* Polyhedron<T,FP,VP>::removeEdge(Edge* edge, Callback& callback) {
859     // First, transfer all edges from the second to the first vertex of the given edge.
860     // This results in the edge being a loop and the second vertex to be orphaned.
861     Vertex* firstVertex = edge->firstVertex();
862     Vertex* secondVertex = edge->secondVertex();
863     while (secondVertex->leaving() != NULL) {
864         HalfEdge* leaving = secondVertex->leaving();
865         HalfEdge* newLeaving = leaving->previous()->twin();
866         leaving->setOrigin(firstVertex);
867         if (newLeaving->origin() == secondVertex)
868             secondVertex->setLeaving(newLeaving);
869         else
870             secondVertex->setLeaving(NULL);
871     }
872 
873     // Remove the edge's first edge from its first face and delete the face if it degenerates
874     {
875         Face* firstFace = edge->firstFace();
876         HalfEdge* firstEdge = edge->firstEdge();
877         HalfEdge* nextEdge = firstEdge->next();
878 
879         firstVertex->setLeaving(firstEdge->previous()->twin());
880         firstFace->removeFromBoundary(firstEdge);
881         nextEdge->setOrigin(firstVertex);
882         delete firstEdge;
883 
884         if (firstFace->vertexCount() == 2)
885             removeDegenerateFace(firstFace, callback);
886     }
887 
888     // Remove the edges's second edge from its second face and delete the face if it degenerates
889     {
890         Face* secondFace = edge->secondFace();
891         HalfEdge* secondEdge = edge->secondEdge();
892 
893         secondFace->removeFromBoundary(secondEdge);
894         delete secondEdge;
895 
896         if (secondFace->vertexCount() == 2)
897             removeDegenerateFace(secondFace, callback);
898     }
899 
900     m_vertices.remove(secondVertex);
901     delete secondVertex;
902 
903     Edge* result = edge->next();
904     m_edges.remove(edge);
905     delete edge;
906 
907     // Merge faces that may have become coplanar
908     {
909         HalfEdge* firstEdge = firstVertex->leaving();
910         HalfEdge* currentEdge = firstEdge;
911         do {
912             HalfEdge* nextEdge = currentEdge->nextIncident();
913             Face* currentFace = firstEdge->face();
914             Face* neighbour = firstEdge->twin()->face();
915             if (currentFace->coplanar(neighbour))
916                 mergeNeighbours(currentEdge, callback);
917             currentEdge = nextEdge;
918         } while (currentEdge != firstEdge);
919     }
920 
921     return result;
922 }
923 
924 template <typename T, typename FP, typename VP>
removeDegenerateFace(Face * face,Callback & callback)925 void Polyhedron<T,FP,VP>::removeDegenerateFace(Face* face, Callback& callback) {
926     assert(face->vertexCount() == 2);
927 
928     HalfEdge* halfEdge1 = face->boundary().front();
929     HalfEdge* halfEdge2 = halfEdge1->next();
930     assert(halfEdge2->next() == halfEdge1);
931     assert(halfEdge1->previous() == halfEdge2);
932 
933     Vertex* vertex1 = halfEdge1->origin();
934     Vertex* vertex2 = halfEdge2->origin();
935 
936     vertex1->setLeaving(halfEdge2->twin());
937     vertex2->setLeaving(halfEdge1->twin());
938 
939     Edge* edge1 = halfEdge1->edge();
940     Edge* edge2 = halfEdge2->edge();
941 
942     edge1->makeSecondEdge(halfEdge1);
943     edge2->makeFirstEdge(halfEdge2);
944 
945     HalfEdge* halfEdge3 = edge2->secondEdge();
946     halfEdge3->setEdge(NULL);
947     edge1->unsetSecondEdge();
948     edge1->setSecondEdge(halfEdge3);
949 
950     m_edges.remove(edge2);
951     delete edge2;
952 
953     callback.faceWillBeDeleted(face);
954     m_faces.remove(face);
955     delete face;
956 }
957 
958 template <typename T, typename FP, typename VP>
updateBounds()959 void Polyhedron<T,FP,VP>::updateBounds() {
960     if (m_vertices.size() == 0) {
961         m_bounds.min = m_bounds.max = Vec<T,3>::NaN;
962     } else {
963         Vertex* first = m_vertices.front();
964         Vertex* current = first;
965         m_bounds.min = m_bounds.max = current->position();
966 
967         current = current->next();
968         while (current != first) {
969             m_bounds.mergeWith(current->position());
970             current = current->next();
971         }
972     }
973 }
974 
975 #endif
976