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 
31 namespace vcg
32 {
33     namespace tri{
34         /// \ingroup trimesh
35         /// \brief This class is used to build edge based data structure from indexed data structure and viceversa
36         /**
37                 */
38 
39         template <class MeshType  >
40                 class UpdateHalfEdges{
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 
54             struct VertexPairEdgePtr{
VertexPairEdgePtrVertexPairEdgePtr55                 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{
FacePtrIntFacePtrInt63                 FacePtrInt ( FaceType * _f,int _i):f(_f),i(_i){}
64                 FaceType * f;
65                 int i;
66             };
67 
68             typedef std::vector<bool> BitVector;
69 
70             /**
71                         build a half-edge data structure from an indexed data structure. Note that the half-edges are allocated here for the first time.
72                         If you have a mesh where there are already edges, they will be removed and the data lost, so do not use this function
73                         to just "update" the topology of half edges.
74                         **/
FromIndexed(MeshType & m)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                                 vector<HEdgePointer> hedges = HalfEdgeTopology<MeshType>::get_incident_hedges((*ei1).V(0));
218 
219                                 for(typename 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 
245             /**
246         Checks pointers FHEp() are valid
247         **/
CheckConsistency_FHp(MeshType & m)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 
259             /**
260         Checks that half edges and face relation are consistent
261         **/
CheckConsistency(MeshType & m)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 
432             /** Set the relations HFp(), FHp() from a loop of edges to a face
433         */
434         private:
SetRelationsLoopFace(HEdgeType * e0,FaceType * f)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 
445             /**
446         Merge the two faces. This will probably become a class template or a functor
447         */
MergeFaces(FaceType *,FaceType *)448             static void MergeFaces(FaceType *, FaceType *){}
449 
450             /**
451         Find previous hedge in the loop
452         */
PreviousEdge(HEdgeType * e0)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:
464             /** Adds an edge between the sources of e0 and e1 and set all the topology relations.
465         If the edges store the pointers to the faces then a new face is created.
466     <--- e1 ---- X <------e1_HEPp---
467                  ^
468                  ||
469              ei0 || ei1
470                  ||
471                   v
472          ----e0_HEPp-> X ----- e0 ------>
473         */
AddHEdge(MeshType & m,HEdgeType * e0,HEdgeType * e1)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()){
516                     FaceIterator fi0  = vcg::tri::Allocator<MeshType>::AddFaces(m,1);
517                     m.face.back().ImportData(*e0->HFp());
518 
519                     SetRelationsLoopFace(&(*ei0),e1->HFp());		// one loop to the old face
520                     SetRelationsLoopFace(&(*ei1),&m.face.back());	// the other  to the new face
521                 }
522             }
523 
524             /** Detach the topology relations of a given edge
525     <--- e->HENPp -X --- <---------eO_HEPp---
526                    ^
527                    ||
528                e   || e->HEOp()
529                    ||
530                     v
531          ----e_HEPp--> X ----- e->HEOp->HENPp() ------>
532 
533         */
RemoveHEdge(MeshType & m,HEdgeType * e)534             static void RemoveHEdge(MeshType &m, HEdgeType * e){
535                 assert(MeshType::HEdgeType::HasHNextAdjacency());
536                 assert(MeshType::HEdgeType::HasHOppAdjacency());
537                 assert(MeshType::FaceType::HasFHAdjacency());
538 
539                 bool hasP =  MeshType::HEdgeType::HasHPrevAdjacency();
540                 HEdgePointer e_HEPp,eO_HEPp;
541 
542                 if(hasP){
543                     e_HEPp = e->HPp();
544                     eO_HEPp = e->HOp()->HPp();
545                 }else{
546                     e_HEPp = PreviousEdge(e);
547                     eO_HEPp = PreviousEdge(e->HOp());
548                 }
549 
550                 assert(e_HEPp->HNp() == e);
551                 assert(eO_HEPp->HNp() == e->HOp());
552                 e_HEPp->HNp() = e->HOp()->HNp();
553                 eO_HEPp->HNp() = e-> HNp();
554 
555                 if(hasP) {
556                     e->HOp()->HNp()->HPp() = e_HEPp;
557                     e->HNp()->HPp() = eO_HEPp;
558 
559                     e->HPp() = NULL;
560                     e-> HOp()->HPp() = NULL;
561                 }
562 
563 
564                 // take care of the faces
565                 if(MeshType::HEdgeType::HasHFAdjacency()){
566                     MergeFaces(e_HEPp->HFp(),eO_HEPp->HFp());
567                     vcg::tri::Allocator<MeshType>::DeleteFace(m,*eO_HEPp->HFp());
568                     SetRelationsLoopFace(e_HEPp,e_HEPp->HFp());
569 
570                 }
571                 vcg::tri::Allocator<MeshType>::DeleteHEdge(m,*e->HOp());
572                 vcg::tri::Allocator<MeshType>::DeleteHEdge(m,*e);
573 
574             }
575 
576         };// end class
577         template <class MeshType  >
578                 struct UpdateIndexed{
579             typedef typename MeshType::VertexType VertexType;
580             typedef typename MeshType::VertexPointer VertexPointer;
581             typedef typename MeshType::HEdgePointer HEdgePointer;
582             typedef typename MeshType::HEdgeType HEdgeType;
583             typedef typename MeshType::HEdgeIterator HEdgeIterator;
584             typedef typename MeshType::FaceIterator FaceIterator;
585             typedef typename MeshType::FaceType FaceType;
586 
587             struct VertexPairEdgePtr{
VertexPairEdgePtrUpdateIndexed::VertexPairEdgePtr588                 VertexPairEdgePtr(VertexPointer _v0,VertexPointer _v1,HEdgePointer _ep):v0(_v0),v1(_v1),ep(_ep){if(v0>v1) std::swap(v0,v1);}
589                 bool operator <(const VertexPairEdgePtr &o) const {return (v0 == o.v0)? (v1<o.v1):(v0<o.v0);}
590                 bool operator ==(const VertexPairEdgePtr &o) const {return (v0 == o.v0)&& (v1==o.v1);}
591 
592                 VertexPointer v0,v1;
593                 HEdgePointer ep;
594             };
595 
596             /**
597                         builds an indexed data structure from a half-edge data structure.
598                         Note: if  the half edge have the pointer to face
599                         their relation FV (face-vertex) will be computed and the data possibly stored in the
600                         face will be preserved.
601                         **/
FromHalfEdgesUpdateIndexed602             static void FromHalfEdges(  MeshType & m ){
603                 assert(HasFVAdjacency(m));
604                 assert(MeshType::HEdgeType::HasHNextAdjacency());
605                 assert(MeshType::HEdgeType::HasHVAdjacency());
606                 assert(MeshType::HEdgeType::HasHOppAdjacency());
607                 assert(MeshType::FaceType::HasFHAdjacency());
608                 bool hasHEF;
609                 //bool createFace,hasHEF,hasFHE;
610 
611                 //				typename MeshType::template PerHEdgeAttributeHandle<bool> hV = Allocator<MeshType>::template AddPerHEdgeAttribute<bool>(m,"");
612 
613 
614                 typename MeshType::HEdgeIterator ei;
615                 typename MeshType::FacePointer fp;
616                 typename MeshType::FaceIterator fi;
617                 typename MeshType::HEdgePointer ep,epF;
618                 //int vi = 0;
619                 vcg::SimpleTempData<typename MeshType::HEdgeContainer,bool> hV(m.hedge);
620 
621                 hasHEF = (MeshType::HEdgeType::HasHFAdjacency());
622                 assert( !hasHEF || (hasHEF && m.fn>0));
623 
624                 // if the edgetype has the pointer to face
625                 // it is assumed the the edget2face pointer (HEFp) are correct
626                 // and the faces are allocated
627                 for ( ei = m.hedge.begin(); ei != m.hedge.end(); ++ei)
628                     if(!(*ei).IsD())								// it has not been deleted
629                         if(!hasHEF || ( hasHEF &&  (*ei).HFp()!=NULL))	// if it has a pointer to the face it is
630                             // not null (i.e. it is not a border edge)
631                             if(!hV[(*ei)] )									// it has not be visited yet
632                             {
633                     if(!hasHEF)// if it has
634                         fp = &(* Allocator<MeshType>::AddFaces(m,1));
635                     else
636                         fp = (*ei).HFp();
637 
638                     ep = epF = &(*ei);
639                     std::vector<VertexPointer> vpts;
640                     do{vpts.push_back((*ep).HVp()); ep=ep->HNp();}while(ep!=epF);
641                     //int idbg  =fp->VN();
642                     if(size_t(fp->VN()) != vpts.size()){
643                         fp->Dealloc();
644                         fp ->Alloc(vpts.size());
645                     }
646                     //int idbg1  =fp->VN();
647                     for(size_t i  = 0; i < vpts.size();++i) fp ->V(i) = vpts[i];// set the pointer from face to vertex
648 
649                     hV[(*ei)] = true;
650                 }
651                 //Allocator<MeshType>::DeletePerHEdgeAttribute(m,hV);
652             }
653 
654         };
655     } // end namespace vcg
656 }
657 #endif // __VCGLIB_EDGE_SUPPORT
658