VCG Library
Loading...
Searching...
No Matches
halfedge_indexed.h
1/****************************************************************************
2* VCGLib o o *
3* Visual and Computer Graphics Library o o *
4* _ O _ *
5* Copyright(C) 2004-2016 \/)\/ *
6* Visual Computing Lab /\/| *
7* ISTI - Italian National Research Council | *
8* \ *
9* All rights reserved. *
10* *
11* This program is free software; you can redistribute it and/or modify *
12* it under the terms of the GNU General Public License as published by *
13* the Free Software Foundation; either version 2 of the License, or *
14* (at your option) any later version. *
15* *
16* This program is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20* for more details. *
21* *
22****************************************************************************/
23
24#ifndef __VCGLIB_HALFEDGE_
25#define __VCGLIB_HALFEDGE_
26
27#include <vcg/complex/algorithms/clean.h>
28#include <vcg/complex/algorithms/update/topology.h>
29#include <vcg/complex/algorithms/update/halfedge_topology.h>
30
31namespace vcg
32{
33 namespace tri{
36
39 template <class MeshType >
41 public:
42 typedef typename MeshType::VertexType VertexType;
43 typedef typename MeshType::VertexPointer VertexPointer;
44 typedef typename MeshType::VertexIterator VertexIterator;
45 typedef typename MeshType::HEdgePointer HEdgePointer;
46 typedef typename MeshType::HEdgeType HEdgeType;
47 typedef typename MeshType::EdgePointer EdgePointer;
48 typedef typename MeshType::EdgeType EdgeType;
49 typedef typename MeshType::EdgeIterator EdgeIterator;
50 typedef typename MeshType::HEdgeIterator HEdgeIterator;
51 typedef typename MeshType::FaceIterator FaceIterator;
52 typedef typename MeshType::FaceType FaceType;
53
55 VertexPairEdgePtr(VertexPointer _v0,VertexPointer _v1,HEdgePointer _ep):v0(_v0),v1(_v1),ep(_ep){if(v0>v1) std::swap(v0,v1);}
56 bool operator <(const VertexPairEdgePtr &o) const {return (v0 == o.v0)? (v1<o.v1):(v0<o.v0);}
57 bool operator ==(const VertexPairEdgePtr &o) const {return (v0 == o.v0)&& (v1==o.v1);}
58
59 VertexPointer v0,v1;
60 HEdgePointer ep;
61 };
62 struct FacePtrInt{
63 FacePtrInt ( FaceType * _f,int _i):f(_f),i(_i){}
64 FaceType * f;
65 int i;
66 };
67
68 typedef std::vector<bool> BitVector;
69
75 static void FromIndexed(MeshType & m){
76 assert(HasFVAdjacency(m));
77 assert(HasHOppAdjacency(m));
78 assert(HasHNextAdjacency(m));
79
80 typename MeshType::template PerFaceAttributeHandle<BitVector> flagVisited =
81 vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<BitVector>(m,"");
82 std::vector<FacePtrInt > borderEdges;
83
84 // allocate all new half edges
85 FaceIterator fi;
86 unsigned int n_edges = 0;
87
88 // count how many half edge to allocate
89 for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(! (*fi).IsD())
90 {n_edges+=(*fi).VN();
91 for(int i = 0; i < (*fi).VN(); ++i)
92 if(vcg::face::IsBorder<FaceType>((*fi),(i)))
93 ++n_edges;
94 }
95
96 m.hedge.clear();
97 m.hn = 0;
98
99 // allocate the half edges
100 typename MeshType::HEdgeIterator ei = vcg::tri::Allocator<MeshType>::AddHEdges(m,n_edges);
101
102
103 std::vector<VertexPairEdgePtr> all;
104 int firstEdge = 0;
105 for(fi = m.face.begin(); fi != m.face.end(); ++fi)if(!(*fi).IsD()){
106 assert((*fi).VN()>2);
107 if(flagVisited[*fi].empty()) {flagVisited[*fi].resize((*fi).VN());}
108
109 for(int i = 0; i < (*fi).VN(); ++i,++ei)
110 {
111 (*ei).HVp() = (*fi).V(i);
112 (*ei).HNp() = &m.hedge[firstEdge + (i +1) % (*fi).VN()];
113 if(MeshType::HEdgeType::HasHFAdjacency())
114 (*ei).HFp() = &(*fi);
115 if( MeshType::FaceType::HasFHAdjacency())
116 (*fi).FHp() = &(*ei);
117 if(MeshType::HEdgeType::HasHPrevAdjacency())
118 (*ei).HPp() = &m.hedge[firstEdge + (i +(*fi).VN()-1) % (*fi).VN()];
119 if(HasVHAdjacency(m))
120 (*ei).HVp()->VHp() = &(*ei);
121 all.push_back(VertexPairEdgePtr((*fi).V(i), (*fi).V((*fi).Next(i)),&(*ei)));// it will be used to link the hedges
122
123 if( vcg::face::IsBorder<FaceType>((*fi),(i)))
124 borderEdges.push_back(FacePtrInt(&(*fi),i));
125 }
126 firstEdge += (*fi).VN();
127 }
128
129 // add all the border hedges
130 int borderLength;
131 typename std::vector<FacePtrInt >::iterator ebi;
132 for( ebi = borderEdges.begin(); ebi != borderEdges.end(); ++ebi)
133 if( !flagVisited[(*ebi).f][(*ebi).i])// not already inserted
134 {
135
136 borderLength = 0;
137 vcg::face::Pos<FaceType> bp((*ebi).f,(*ebi).i);
138
139 //FaceType * start = (*ebi).f;
140 VertexType * start = ((*ebi).f)->V((*ebi).i);
141 do{
142 all.push_back( VertexPairEdgePtr ( bp.f->V( bp.f->Next(bp.z) ),bp.f->V( bp.z ),&(*ei)));
143 (*ei).HVp() = bp.f->V(bp.f->Next(bp.z)) ;
144 flagVisited[bp.f][bp.z] = true;
145 ++ei;
146 bp.NextB();
147 ++borderLength;
148 }while (bp.v != start);
149 //}while (bp.f != start);
150
151
152 // run over the border edges to link the adjacencies
153 for(int be = 0; be < borderLength; ++be)
154 {
155 if(MeshType::HEdgeType::HasHFAdjacency())
156 m.hedge[firstEdge + be].HFp() = NULL;
157
158 if(MeshType::HEdgeType::HasHPrevAdjacency())
159 m.hedge[firstEdge + be].HPp() = &m.hedge[firstEdge + (be +borderLength-1) % borderLength];
160
161 m.hedge[firstEdge + be].HNp() = &m.hedge[firstEdge + (be +1) % borderLength];
162 }
163 firstEdge+=borderLength;
164 }
165
166 vcg::tri::Allocator<MeshType>:: template DeletePerFaceAttribute<BitVector>(m,flagVisited );
167
168 std::sort(all.begin(),all.end());
169 assert(all.size() == n_edges);
170
171 for(unsigned int i = 0 ; i < all.size(); )
172 if(all[i] == all[i+1])
173 {
174 all[i].ep->HOp() = all[i+1].ep;
175 all[i+1].ep->HOp() = all[i].ep;
176 i+=2;
177 }
178 else
179 {
180 all[i].ep->HOp() = all[i].ep;
181 i+=1;
182 }
183
184 if(HasEHAdjacency(m) && HasHEAdjacency(m))
185 {
186 assert(m.edge.size() == 0 || m.edge.size() == n_edges/2);
187
188 if ( m.edge.size() == 0 )
189 {
190 m.en = 0;
191 // allocate the edges
192 typename MeshType::EdgeIterator edge_i = vcg::tri::Allocator<MeshType>::AddEdges(m,n_edges/2);
193
194 for(ei = m.hedge.begin(); ei != m.hedge.end(); ++ei)
195 {
196 if((*ei).HEp() == NULL)
197 {
198 (*ei).HEp() = &(*edge_i);
199 (*ei).HOp()->HEp() = &(*edge_i);
200
201 (*edge_i).EHp() = &(*ei);
202
203 ++edge_i;
204 }
205 }
206
207 }
208 else
209 {
210
211 if(HasEVAdjacency(m) && HasHEAdjacency(m) && HasEHAdjacency(m))
212 {
213 //update edge relations
214
215 for(typename MeshType::EdgeIterator ei1 = m.edge.begin(); ei1 != m.edge.end(); ++ei1 )
216 {
217 std::vector<HEdgePointer> hedges = HalfEdgeTopology<MeshType>::get_incident_hedges((*ei1).V(0));
218
219 for(typename std::vector<HEdgePointer>::iterator hi = hedges.begin(); hi != hedges.end(); ++hi)
220 {
221 if((*hi)->HOp()->HVp() == (*ei1).V(1))
222 {
223
224 assert((*hi)->HEp() == NULL);
225 assert((*hi)->HOp()->HEp() == NULL);
226
227 // EH
228 (*ei1).EHp() = *hi;
229
230 // HE
231 (*hi)->HEp() = &(*ei1);
232 (*hi)->HOp()->HEp() = &(*ei1);
233
234 break;
235 }
236 }
237 }
238 }
239 }
240
241 }
242
243 }
244
248 static bool CheckConsistency_FHp(MeshType & m){
249 assert(MeshType::FaceType::HasFHAdjacency());
250 FaceIterator fi;
251 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
252 if(!(*fi).IsD()){
253 if((*fi).FHp() < &(*m.hedge.begin())) return false;
254 if((*fi).FHp() > &(m.hedge.back())) return false;
255 }
256 return true;
257 }
258
262 static bool CheckConsistency(MeshType & m){
263 assert(MeshType::HEdgeType::HasHNextAdjacency());
264 assert(MeshType::HEdgeType::HasHOppAdjacency());
265 assert(MeshType::HEdgeType::HasHVAdjacency());
266 assert(MeshType::FaceType::HasFHAdjacency());
267
268 //bool hasHEF = ( MeshType::HEdgeType::HasHFAdjacency());
269 bool hasHP = ( MeshType::HEdgeType::HasHPrevAdjacency());
270
271 FaceIterator fi;
272 HEdgePointer ep,ep1;
273 int cnt = 0;
274
275 if( MeshType::HEdgeType::HasHFAdjacency() )
276 {
277 int iDb = 0;
278 for(fi = m.face.begin(); fi != m.face.end(); ++fi,++iDb)
279 if(!(*fi).IsD())
280 {
281 ep = ep1 = (*fi).FHp();
282
283 do{
284 if(ep->IsD())
285 return false; // the hedge should not be connected, it has been deleted
286 if( ! ep->HFp())
287 return false;
288 if(ep->HFp() != &(*fi))
289 return false;// hedge is not pointing to the rigth face
290 ep = ep->HNp();
291 if(cnt++ > m.hn)
292 return false; // hedges are ill connected (HENp())
293
294 }while(ep!=ep1);
295
296 }
297 }
298
299 HEdgePointer epPrev;
300 HEdgeIterator hi;
301 //bool extEdge ;
302 for( hi = m.hedge.begin(); hi != m.hedge.end(); ++hi)
303 if(!(*hi).IsD())
304 {
305 //cnt = 0;
306 epPrev = ep = ep1 = &(*hi);
307 //do{
308 //extEdge = (ep->HFp()==NULL);
309 if(hasHP)
310 {
311 if( !ep->HPp())
312 return false;
313 if( ep->HPp() == ep)
314 return false; // the previous of an edge cannot be the edge itself
315 if( ep->HNp()->HPp() != ep)
316 return false; // next and prev relation are not mutual
317 if( ep->HPp()->IsD())
318 return false; //
319 }
320
321 if( ! ep->HOp() )
322 return false;
323
324 if( ep->HOp() == ep)
325 return false; // opposite relation is not mutual
326
327 if( ep->HOp()->IsD())
328 return false;
329
330 if( ep->HOp()->HOp() != ep)
331 return false; // opposite relation is not mutual
332
333 if( HasHFAdjacency(m) )
334 {
335 if(ep->HFp())
336 {
337 if( ep->HFp()->IsD())
338 return false; // pointed face must not be deleted
339 }
340 }
341
342 if( HasHEAdjacency(m) && (m.en!=0))
343 {
344 if( ! ep->HEp())
345 return false; //halfedge must point to an edge
346
347 if( ep->HEp()->IsD())
348 return false; // pointed edge must not be deleted
349
350 if(ep->HEp() != ep->HOp()->HEp())
351 return false; // he and opposite he must point to the same edge
352
353 if(ep->HEp()->EHp() != ep && ep->HEp()->EHp() != ep->HOp() )
354 return false; // halfedge points to an edge not pointing it or its opposite
355
356 }
357
358
359 if( !ep->HNp() )
360 return false;
361
362 if( ep->HNp() == ep )
363 return false; // the next of an hedge cannot be the hedge itself
364
365 if( ep->HNp()->IsD())
366 return false; //
367
368 if(hasHP)
369 if( ep->HNp()->HPp() != ep)
370 return false; //
371
372 if( HasHVAdjacency(m) )
373 {
374 if( ! ep->HVp() )
375 return false; // halfedge must point to a vertex
376
377 if( ep->HVp()->IsD() )
378 return false; // pointed vertex must not be deleted
379
380 if( HasVHAdjacency(m) )
381 if( ! (ep->HVp()->VHp()) )
382 return false; // halfedge points to a vertex pointing NULL
383
384 }
385
386
387 ep = ep->HNp();
388 if( ep->HVp() != epPrev->HOp()->HVp())
389 return false;
390
391 epPrev = ep;
392
393 // if(cnt++ > m.hn)
394 // return false; // edges are ill connected (HENp())
395
396 //}while(ep!=ep1);
397 }
398
399 if(HasEHAdjacency(m) && HasHEAdjacency(m))
400 for(EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
401 {
402 if(!(*ei).IsD())
403 {
404 if( !(*ei).EHp())
405 return false; //edge must have a valid pointer to his halfedge
406
407 if( (*ei).EHp()->HEp() != &(*ei) )
408 return false; // edge's halfedge must point to the edge itself
409
410 if( (*ei).EHp()->IsD())
411 return false;
412 }
413 }
414
415 if(HasVHAdjacency(m))
416 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
417 {
418 if( !(*vi).IsD() )
419 if( (*vi).VHp() )
420 {
421 if( (*vi).VHp()->HVp() != &(*vi) )
422 return false;
423 if( (*vi).VHp()->IsD())
424 return false;
425 }
426 }
427
428
429 return true;
430 }
431
434 private:
435 static void SetRelationsLoopFace(HEdgeType * e0, FaceType * f){
436 assert(HEdgeType::HasHNextAdjacency());
437 assert(FaceType::HasFHAdjacency());
438
439 HEdgeType *e = e0;
440 assert(e!=NULL);
441 do{ e->HFp() = f; e = e->HNp(); } while(e != e0);
442 f->FHp() = e0;
443 }
444
448 static void MergeFaces(FaceType *, FaceType *){}
449
453 static HEdgeType * PreviousEdge(HEdgeType * e0){
454 HEdgeType * ep = e0;
455 do{
456 if(ep->HNp() == e0) return ep;
457 ep = ep->HNp();
458 }while(ep!=e0);
459 assert(0); // degenerate loop
460 return 0;
461 }
462
463 public:
474 static void AddHEdge(MeshType &m, HEdgeType * e0, HEdgeType * e1){
475 assert(e1!=e0->HNp());
476 assert(e0!=e1->HNp());
477 bool hasP = MeshType::HEdgeType::HasHPrevAdjacency();
478 assert(e0->HOp() != e1); // the hedge already exists
479 assert(e0!=e1->HNp());
480
481 std::vector<typename MeshType::HEdgePointer* > toUpdate;
482 toUpdate.push_back(&e0);
483 toUpdate.push_back(&e1);
484 HEdgeIterator ei0 = vcg::tri::Allocator<MeshType>::AddHEdges(m,2,toUpdate);
485
486 HEdgeIterator ei1 = ei0; ++ei1;
487 (*ei0).HNp() = e1;(*ei0).HVp() = e0->HVp();
488 (*ei1).HNp() = e0;(*ei1).HVp() = e1->HVp();
489
490 HEdgePointer e0_HEPp = 0,e1_HEPp = 0,ep =0;
491 if(hasP){
492 e0_HEPp = e0->HPp();
493 e1_HEPp = e1->HPp();
494 }else{// does not have pointer to previous, it must be computed
495 ep = e0;
496 do{
497 if(ep->HNp() == e0) e0_HEPp = ep;
498 if(ep->HNp() == e1) e1_HEPp = ep;
499 ep = ep->HNp();
500 }while(ep!=e0);
501 }
502 if(hasP){
503 (*ei0).HPp() = e0->HPp();
504 (*ei1).HPp() = e1->HPp();
505 e0->HPp() = &(*ei1);
506 e1->HPp() = &(*ei0);
507 }
508 e0_HEPp -> HNp() = &(*ei0);
509 e1_HEPp -> HNp() = &(*ei1);
510
511 (*ei0).HOp() = &(*ei1);
512 (*ei1).HOp() = &(*ei0);
513
514
515 if( HEdgeType::HasHFAdjacency() && FaceType::HasFHAdjacency()){
517 m.face.back().ImportData(*e0->HFp());
518 SetRelationsLoopFace(&(*ei0),e1->HFp()); // one loop to the old face
519 SetRelationsLoopFace(&(*ei1),&m.face.back()); // the other to the new face
520 }
521 }
522
533 static void RemoveHEdge(MeshType &m, HEdgeType * e){
534 assert(MeshType::HEdgeType::HasHNextAdjacency());
535 assert(MeshType::HEdgeType::HasHOppAdjacency());
536 assert(MeshType::FaceType::HasFHAdjacency());
537
538 bool hasP = MeshType::HEdgeType::HasHPrevAdjacency();
539 HEdgePointer e_HEPp,eO_HEPp;
540
541 if(hasP){
542 e_HEPp = e->HPp();
543 eO_HEPp = e->HOp()->HPp();
544 }else{
545 e_HEPp = PreviousEdge(e);
546 eO_HEPp = PreviousEdge(e->HOp());
547 }
548
549 assert(e_HEPp->HNp() == e);
550 assert(eO_HEPp->HNp() == e->HOp());
551 e_HEPp->HNp() = e->HOp()->HNp();
552 eO_HEPp->HNp() = e-> HNp();
553
554 if(hasP) {
555 e->HOp()->HNp()->HPp() = e_HEPp;
556 e->HNp()->HPp() = eO_HEPp;
557
558 e->HPp() = NULL;
559 e-> HOp()->HPp() = NULL;
560 }
561
562
563 // take care of the faces
564 if(MeshType::HEdgeType::HasHFAdjacency()){
565 MergeFaces(e_HEPp->HFp(),eO_HEPp->HFp());
567 SetRelationsLoopFace(e_HEPp,e_HEPp->HFp());
568
569 }
572
573 }
574
575 };// end class
576 template <class MeshType >
578 typedef typename MeshType::VertexType VertexType;
579 typedef typename MeshType::VertexPointer VertexPointer;
580 typedef typename MeshType::HEdgePointer HEdgePointer;
581 typedef typename MeshType::HEdgeType HEdgeType;
582 typedef typename MeshType::HEdgeIterator HEdgeIterator;
583 typedef typename MeshType::FaceIterator FaceIterator;
584 typedef typename MeshType::FaceType FaceType;
585
587 VertexPairEdgePtr(VertexPointer _v0,VertexPointer _v1,HEdgePointer _ep):v0(_v0),v1(_v1),ep(_ep){if(v0>v1) std::swap(v0,v1);}
588 bool operator <(const VertexPairEdgePtr &o) const {return (v0 == o.v0)? (v1<o.v1):(v0<o.v0);}
589 bool operator ==(const VertexPairEdgePtr &o) const {return (v0 == o.v0)&& (v1==o.v1);}
590
591 VertexPointer v0,v1;
592 HEdgePointer ep;
593 };
594
601 static void FromHalfEdges( MeshType & m ){
602 assert(HasFVAdjacency(m));
603 assert(MeshType::HEdgeType::HasHNextAdjacency());
604 assert(MeshType::HEdgeType::HasHVAdjacency());
605 assert(MeshType::HEdgeType::HasHOppAdjacency());
606 assert(MeshType::FaceType::HasFHAdjacency());
607 bool hasHEF;
608 //bool createFace,hasHEF,hasFHE;
609
610 // typename MeshType::template PerHEdgeAttributeHandle<bool> hV = Allocator<MeshType>::template AddPerHEdgeAttribute<bool>(m,"");
611
612
613 typename MeshType::HEdgeIterator ei;
614 typename MeshType::FacePointer fp;
615 typename MeshType::FaceIterator fi;
616 typename MeshType::HEdgePointer ep,epF;
617 //int vi = 0;
618 vcg::SimpleTempData<typename MeshType::HEdgeContainer,bool> hV(m.hedge);
619
620 hasHEF = (MeshType::HEdgeType::HasHFAdjacency());
621 assert( !hasHEF || (hasHEF && m.fn>0));
622
623 // if the edgetype has the pointer to face
624 // it is assumed the the edget2face pointer (HEFp) are correct
625 // and the faces are allocated
626 for ( ei = m.hedge.begin(); ei != m.hedge.end(); ++ei)
627 if(!(*ei).IsD()) // it has not been deleted
628 if(!hasHEF || ( hasHEF && (*ei).HFp()!=NULL)) // if it has a pointer to the face it is
629 // not null (i.e. it is not a border edge)
630 if(!hV[(*ei)] ) // it has not be visited yet
631 {
632 if(!hasHEF)// if it has
633 fp = &(* Allocator<MeshType>::AddFaces(m,1));
634 else
635 fp = (*ei).HFp();
636
637 ep = epF = &(*ei);
638 std::vector<VertexPointer> vpts;
639 do{vpts.push_back((*ep).HVp()); ep=ep->HNp();}while(ep!=epF);
640 //int idbg =fp->VN();
641 if(size_t(fp->VN()) != vpts.size()){
642 fp->Dealloc();
643 fp ->Alloc(vpts.size());
644 }
645 //int idbg1 =fp->VN();
646 for(size_t i = 0; i < vpts.size();++i) fp ->V(i) = vpts[i];// set the pointer from face to vertex
647
648 hV[(*ei)] = true;
649 }
650 //Allocator<MeshType>::DeletePerHEdgeAttribute(m,hV);
651 }
652
653 };
654 } // end namespace vcg
655}
656#endif // __VCGLIB_EDGE_SUPPORT
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
static EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater< EdgePointer > &pu)
Add n edges to the mesh. Function to add n edges to the mesh. The elements are added always to the en...
Definition: allocate.h:333
static void DeleteFace(MeshType &m, FaceType &f)
Definition: allocate.h:923
static void DeleteHEdge(MeshType &m, HEdgeType &h)
Definition: allocate.h:957
static FaceIterator AddFaces(MeshType &m, size_t n)
Function to add n faces to the mesh. First wrapper, with no parameters.
Definition: allocate.h:615
static HEdgeIterator AddHEdges(MeshType &m, size_t n, PointerUpdater< HEdgePointer > &pu)
Definition: allocate.h:453
static std::vector< HEdgePointer > get_incident_hedges(VertexPointer vp, HEdgePointer starting_he=NULL)
Definition: halfedge_topology.h:1593
This class is used to build edge based data structure from indexed data structure and viceversa.
Definition: halfedge_indexed.h:40
static void RemoveHEdge(MeshType &m, HEdgeType *e)
Definition: halfedge_indexed.h:533
static void FromIndexed(MeshType &m)
Definition: halfedge_indexed.h:75
static bool CheckConsistency(MeshType &m)
Definition: halfedge_indexed.h:262
static bool CheckConsistency_FHp(MeshType &m)
Definition: halfedge_indexed.h:248
static void AddHEdge(MeshType &m, HEdgeType *e0, HEdgeType *e1)
Definition: halfedge_indexed.h:474
Definition: color4.h:30
Definition: halfedge_indexed.h:62
Definition: halfedge_indexed.h:54
Definition: halfedge_indexed.h:586
Definition: halfedge_indexed.h:577
static void FromHalfEdges(MeshType &m)
Definition: halfedge_indexed.h:601