VCG Library
allocate.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 #ifndef __VCGLIB_TRIALLOCATOR
24 #define __VCGLIB_TRIALLOCATOR
25 
26 #ifndef __VCG_MESH
27 #error "This file should not be included alone. It is automatically included by complex.h"
28 #endif
29 
30 namespace vcg {
31 namespace tri {
36 template<class MeshType>
37 size_t Index(MeshType &m, const typename MeshType::VertexType &v) {return &v-&*m.vert.begin();}
38 template<class MeshType>
39 size_t Index(MeshType &m, const typename MeshType::FaceType &f) {return &f-&*m.face.begin();}
40 template<class MeshType>
41 size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();}
42 template<class MeshType>
43 size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();}
44 
45 template<class MeshType>
46 size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();}
47 template<class MeshType>
48 size_t Index(MeshType &m, const typename MeshType::FaceType * fp) {return fp-&*m.face.begin();}
49 template<class MeshType>
50 size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();}
51 template<class MeshType>
52 size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();}
53 
54 template<class MeshType>
55 bool IsValidPointer( MeshType & m, const typename MeshType::VertexType *vp) { return ( m.vert.size() > 0 && (vp >= &*m.vert.begin()) && (vp <= &m.vert.back()) ); }
56 template<class MeshType>
57 bool IsValidPointer(MeshType & m, const typename MeshType::EdgeType *ep) { return ( m.edge.size() > 0 && (ep >= &*m.edge.begin()) && (ep <= &m.edge.back())); }
58 template<class MeshType>
59 bool IsValidPointer(MeshType & m, const typename MeshType::FaceType *fp) { return ( m.face.size() > 0 && (fp >= &*m.face.begin()) && (fp <= &m.face.back())); }
60 template<class MeshType>
61 bool IsValidPointer(MeshType & m, const typename MeshType::HEdgeType *hp) { return ( m.hedge.size() > 0 && (hp >= &*m.hedge.begin()) && (hp <= &m.hedge.back())); }
62 
63 template <class MeshType, class ATTR_CONT>
64 void ReorderAttribute(ATTR_CONT &c, std::vector<size_t> & newVertIndex, MeshType & /* m */){
65  typename std::set<typename MeshType::PointerToAttribute>::iterator ai;
66  for(ai = c.begin(); ai != c.end(); ++ai)
67  ((typename MeshType::PointerToAttribute)(*ai)).Reorder(newVertIndex);
68 }
69 
70 template <class MeshType, class ATTR_CONT>
71 void ResizeAttribute(ATTR_CONT &c, size_t sz, MeshType &/*m*/){
72  typename std::set<typename MeshType::PointerToAttribute>::iterator ai;
73  for(ai =c.begin(); ai != c.end(); ++ai)
74  ((typename MeshType::PointerToAttribute)(*ai)).Resize(sz);
75 }
76 
84 template <class MeshType>
85 class Allocator
86 {
87 
88 public:
89  typedef typename MeshType::VertexType VertexType;
90  typedef typename MeshType::VertexPointer VertexPointer;
91  typedef typename MeshType::VertexIterator VertexIterator;
92  typedef typename MeshType::VertContainer VertContainer;
93 
94  typedef typename MeshType::EdgeType EdgeType;
95  typedef typename MeshType::EdgePointer EdgePointer;
96  typedef typename MeshType::EdgeIterator EdgeIterator;
97  typedef typename MeshType::EdgeContainer EdgeContainer;
98 
99  typedef typename MeshType::FaceType FaceType;
100  typedef typename MeshType::FacePointer FacePointer;
101  typedef typename MeshType::FaceIterator FaceIterator;
102  typedef typename MeshType::FaceContainer FaceContainer;
103 
104  typedef typename MeshType::HEdgeType HEdgeType;
105  typedef typename MeshType::HEdgePointer HEdgePointer;
106  typedef typename MeshType::HEdgeIterator HEdgeIterator;
107  typedef typename MeshType::HEdgeContainer HEdgeContainer;
108 
109  typedef typename MeshType::CoordType CoordType;
110 
111 
112  typedef typename MeshType::PointerToAttribute PointerToAttribute;
113  typedef typename std::set<PointerToAttribute>::iterator AttrIterator;
114  typedef typename std::set<PointerToAttribute>::const_iterator AttrConstIterator;
115  typedef typename std::set<PointerToAttribute >::iterator PAIte;
116 
128  template<class SimplexPointerType>
130  {
131  public:
132  PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; }
133  void Clear(){newBase=oldBase=newEnd=oldEnd=0; remap.clear();}
138  void Update(SimplexPointerType &vp)
139  {
140  //if(vp>=newBase && vp<newEnd) return;
141  if(vp<oldBase || vp>oldEnd) return;
142  assert(vp>=oldBase);
143  assert(vp<oldEnd);
144  vp=newBase+(vp-oldBase);
145  if(!remap.empty())
146  vp = newBase + remap[vp-newBase];
147  }
151  bool NeedUpdate() {if((oldBase && newBase!=oldBase && !preventUpdateFlag) || !remap.empty()) return true; else return false;}
152 
153  SimplexPointerType newBase;
154  SimplexPointerType oldBase;
155  SimplexPointerType newEnd;
156  SimplexPointerType oldEnd;
157  std::vector<size_t> remap; // this vector keep the new position of an element. Uninitialized elements have max_int value to denote an element that has not to be remapped.
158 
159  bool preventUpdateFlag;
160  };
161 
162  /* +++++++++++++++ Add Vertices ++++++++++++++++ */
163 
174  static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater<VertexPointer> &pu)
175  {
176  VertexIterator last;
177  if(n == 0) return m.vert.end();
178  pu.Clear();
179  if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element
180  else {
181  pu.oldBase=&*m.vert.begin();
182  pu.oldEnd=&m.vert.back()+1;
183  }
184 
185  m.vert.resize(m.vert.size()+n);
186  m.vn+=int(n);
187 
188  typename std::set<PointerToAttribute>::iterator ai;
189  for(ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai)
190  ((PointerToAttribute)(*ai)).Resize(m.vert.size());
191 
192  pu.newBase = &*m.vert.begin();
193  pu.newEnd = &m.vert.back()+1;
194  if(pu.NeedUpdate())
195  {
196  for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi)
197  if(!(*fi).IsD())
198  for(int i=0; i < (*fi).VN(); ++i)
199  if ((*fi).cV(i)!=0) pu.Update((*fi).V(i));
200 
201  for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei)
202  if(!(*ei).IsD())
203  {
204  if(HasEVAdjacency (m)) { pu.Update((*ei).V(0)); pu.Update((*ei).V(1));}
205  // if(HasEVAdjacency(m)) pu.Update((*ei).EVp());
206  }
207  HEdgeIterator hi;
208  for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi)
209  if(!(*hi).IsD())
210  {
211  if(HasHVAdjacency (m))
212  {
213  pu.Update((*hi).HVp());
214  }
215  }
216 
217  // e poiche' lo spazio e' cambiato si ricalcola anche last da zero
218  }
219  size_t siz=(size_t)(m.vert.size()-n);
220 
221  last = m.vert.begin();
222  advance(last,siz);
223 
224  return last;// deve restituire l'iteratore alla prima faccia aggiunta;
225  }
226 
229  static VertexIterator AddVertices(MeshType &m, size_t n)
230  {
232  return AddVertices(m, n,pu);
233  }
234 
237  static VertexIterator AddVertices(MeshType &m, size_t n, std::vector<VertexPointer *> &local_vec)
238  {
240  VertexIterator v_ret = AddVertices(m, n,pu);
241 
242  typename std::vector<VertexPointer *>::iterator vi;
243  for(vi=local_vec.begin();vi!=local_vec.end();++vi)
244  pu.Update(**vi);
245  return v_ret;
246  }
247 
250  static VertexIterator AddVertex(MeshType &m, const CoordType &p)
251  {
252  VertexIterator v_ret = AddVertices(m, 1);
253  v_ret->P()=p;
254  return v_ret;
255  }
256 
259  static VertexIterator AddVertex(MeshType &m, const CoordType &p, const CoordType &n)
260  {
261  VertexIterator v_ret = AddVertices(m, 1);
262  v_ret->P()=p;
263  v_ret->N()=n;
264  return v_ret;
265  }
266 
269  static VertexIterator AddVertex(MeshType &m, const CoordType &p, const Color4b &c)
270  {
271  VertexIterator v_ret = AddVertices(m, 1);
272  v_ret->P()=p;
273  v_ret->C()=c;
274  return v_ret;
275  }
276 
277  /* +++++++++++++++ Add Edges ++++++++++++++++ */
278 
288  static EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater<EdgePointer> &pu)
289  {
290  if(n == 0) return m.edge.end();
291  pu.Clear();
292  if(m.edge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element
293  else {
294  pu.oldBase=&*m.edge.begin();
295  pu.oldEnd=&m.edge.back()+1;
296  }
297 
298  m.edge.resize(m.edge.size()+n);
299  m.en+=int(n);
300  size_t siz=(size_t)(m.edge.size()-n);
301  EdgeIterator firstNewEdge = m.edge.begin();
302  advance(firstNewEdge,siz);
303 
304  typename std::set<typename MeshType::PointerToAttribute>::iterator ai;
305  for(ai = m.edge_attr.begin(); ai != m.edge_attr.end(); ++ai)
306  ((typename MeshType::PointerToAttribute)(*ai)).Resize(m.edge.size());
307 
308  pu.newBase = &*m.edge.begin();
309  pu.newEnd = &m.edge.back()+1;
310  if(pu.NeedUpdate())
311  {
312  if(HasFEAdjacency(m))
313  for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi){
314  if(!(*fi).IsD())
315  for(int i=0; i < (*fi).VN(); ++i)
316  if ((*fi).cFEp(i)!=0) pu.Update((*fi).FEp(i));
317  }
318 
319  if(HasVEAdjacency(m)){
320  for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
321  if(!(*vi).IsD())
322  if ((*vi).cVEp()!=0) pu.Update((*vi).VEp());
323  for(EdgeIterator ei=m.edge.begin();ei!=firstNewEdge;++ei)
324  if(!(*ei).IsD())
325  {
326  if ((*ei).cVEp(0)!=0) pu.Update((*ei).VEp(0));
327  if ((*ei).cVEp(1)!=0) pu.Update((*ei).VEp(1));
328  }
329  }
330 
331  if(HasHEAdjacency(m))
332  for (HEdgeIterator hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi)
333  if(!(*hi).IsD())
334  if ((*hi).cHEp()!=0) pu.Update((*hi).HEp());
335  }
336 
337  return firstNewEdge;// deve restituire l'iteratore alla prima faccia aggiunta;
338  }
339 
342  static EdgeIterator AddEdge(MeshType &m, VertexPointer v0, VertexPointer v1)
343  {
344  EdgeIterator ei= AddEdges(m, 1);
345  ei->V(0)=v0;
346  ei->V(1)=v1;
347  return ei;
348  }
349 
352  static EdgeIterator AddEdge(MeshType &m, size_t v0, size_t v1)
353  {
354  assert(v0!=v1);
355  assert(v0>=0 && v0<m.vert.size());
356  assert(v1>=0 && v1<m.vert.size());
357  return AddEdge(m,&(m.vert[v0]),&(m.vert[v1]));
358  }
359 
360 
363  static EdgeIterator AddEdge(MeshType &m, CoordType p0, CoordType p1)
364  {
365  VertexIterator vi = AddVertices(m,2);
366  EdgeIterator ei = AddEdges(m,1);
367  vi->P()=p0;
368  ei->V(0)=&*vi++;
369  vi->P()=p1;
370  ei->V(1)=&*vi++;
371  return ei;
372  }
373 
377  static EdgeIterator AddEdges(MeshType &m, size_t n)
378  {
380  return AddEdges(m, n,pu);
381  }
382 
386  static EdgeIterator AddEdges(MeshType &m, size_t n, std::vector<EdgePointer*> &local_vec)
387  {
389  EdgeIterator v_ret = AddEdges(m, n,pu);
390 
391  typename std::vector<EdgePointer *>::iterator ei;
392  for(ei=local_vec.begin();ei!=local_vec.end();++ei)
393  pu.Update(**ei);
394  return v_ret;
395  }
396 
397  /* +++++++++++++++ Add HalfEdges ++++++++++++++++ */
398 
408  static HEdgeIterator AddHEdges(MeshType &m, size_t n, PointerUpdater<HEdgePointer> &pu)
409  {
410  HEdgeIterator last;
411  if(n == 0) return m.hedge.end();
412  pu.Clear();
413  if(m.hedge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element
414  else {
415  pu.oldBase=&*m.hedge.begin();
416  pu.oldEnd=&m.hedge.back()+1;
417  }
418 
419  m.hedge.resize(m.hedge.size()+n);
420  m.hn+=int(n);
421 
422  pu.newBase = &*m.hedge.begin();
423  pu.newEnd = &m.hedge.back()+1;
424 
425  if(pu.NeedUpdate())
426  {
427  if(HasFHAdjacency(m)) {
428  for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi)
429  {
430  if(!(*fi).IsD() && (*fi).FHp())
431  pu.Update((*fi).FHp());
432  }
433  }
434  if(HasVHAdjacency(m)) {
435  for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
436  if(!(*vi).IsD() && (*vi).cVHp()!=0)
437  pu.Update((*vi).VHp());
438  }
439  if(HasEHAdjacency(m)) {
440  for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei)
441  if(!(*ei).IsD() && (*ei).cEHp()!=0)
442  pu.Update((*ei).EHp());
443  }
444 
445  int ii = 0;
446  HEdgeIterator hi = m.hedge.begin();
447  while(ii < m.hn - int(n))// cycle on all the faces except the new ones
448  {
449  if(!(*hi).IsD())
450  {
451  if(HasHNextAdjacency(m)) pu.Update((*hi).HNp());
452  if(HasHPrevAdjacency(m)) pu.Update((*hi).HPp());
453  if(HasHOppAdjacency(m)) pu.Update((*hi).HOp());
454  ++ii;
455  }
456  ++hi;
457  }
458  }
459  size_t siz = (size_t)(m.hedge.size()-n);
460 
461  last = m.hedge.begin();
462  advance(last,siz);
463 
464  return last;// deve restituire l'iteratore alla prima faccia aggiunta;
465  }
466 
470  static HEdgeIterator AddHEdges(MeshType &m, size_t n)
471  {
473  return AddHEdges(m, n,pu);
474  }
475 
479  static HEdgeIterator AddHEdges(MeshType &m, size_t n, std::vector<HEdgePointer*> &local_vec)
480  {
482  HEdgeIterator v_ret = AddHEdges(m, n,pu);
483 
484  typename std::vector<HEdgePointer *>::iterator ei;
485  for(ei=local_vec.begin();ei!=local_vec.end();++ei)
486  pu.Update(**ei);
487  return v_ret;
488  }
489 
490  /* +++++++++++++++ Add Faces ++++++++++++++++ */
491 
494  static FaceIterator AddFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2)
495  {
496  assert(m.vert.size()>0);
497  assert((v0!=v1) && (v1!=v2) && (v0!=v2));
498  assert(v0>=&m.vert.front() && v0<=&m.vert.back());
499  assert(v1>=&m.vert.front() && v1<=&m.vert.back());
500  assert(v2>=&m.vert.front() && v2<=&m.vert.back());
502  FaceIterator fi = AddFaces(m,1,pu);
503  fi->Alloc(3);
504  fi->V(0)=v0;
505  fi->V(1)=v1;
506  fi->V(2)=v2;
507  return fi;
508  }
509 
512  static FaceIterator AddFace(MeshType &m, size_t v0, size_t v1, size_t v2)
513  {
514  assert((v0!=v1) && (v1!=v2) && (v0!=v2));
515  assert(v0>=0 && v0<m.vert.size());
516  assert(v1>=0 && v1<m.vert.size());
517  assert(v2>=0 && v2<m.vert.size());
518  return AddFace(m,&(m.vert[v0]),&(m.vert[v1]),&(m.vert[v2]));
519  }
522  static FaceIterator AddFace(MeshType &m, CoordType p0, CoordType p1, CoordType p2)
523  {
524  VertexIterator vi = AddVertices(m,3);
525  FaceIterator fi = AddFaces(m,1);
526  fi->Alloc(3);
527  vi->P()=p0;
528  fi->V(0)=&*vi++;
529  vi->P()=p1;
530  fi->V(1)=&*vi++;
531  vi->P()=p2;
532  fi->V(2)=&*vi;
533  return fi;
534  }
535 
540  static FaceIterator AddQuadFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2, VertexPointer v3)
541  {
542  assert(m.vert.size()>0);
543  assert(v0>=&m.vert.front() && v0<=&m.vert.back());
544  assert(v1>=&m.vert.front() && v1<=&m.vert.back());
545  assert(v2>=&m.vert.front() && v2<=&m.vert.back());
546  assert(v3>=&m.vert.front() && v3<=&m.vert.back());
548  if(FaceType::HasPolyInfo())
549  {
550  FaceIterator fi = AddFaces(m,1,pu);
551  fi->Alloc(4);
552  fi->V(0)=v0; fi->V(1)=v1;
553  fi->V(2)=v2; fi->V(3)=v3;
554  return fi;
555  }
556  else
557  {
558  FaceIterator fi = AddFaces(m,2,pu);
559  fi->Alloc(3); fi->V(0)=v0; fi->V(1)=v1; fi->V(2)=v2;
560  fi->SetF(2);
561  ++fi;
562  fi->Alloc(3); fi->V(0)=v0; fi->V(1)=v2; fi->V(2)=v3;
563  fi->SetF(0);
564  return fi;
565  }
566  }
570  static FaceIterator AddFaces(MeshType &m, size_t n)
571  {
573  return AddFaces(m,n,pu);
574  }
575 
579  static FaceIterator AddFaces(MeshType &m, size_t n,std::vector<FacePointer *> &local_vec)
580  {
582  FaceIterator f_ret= AddFaces(m,n,pu);
583 
584  typename std::vector<FacePointer *>::iterator fi;
585  for(fi=local_vec.begin();fi!=local_vec.end();++fi)
586  pu.Update(**fi);
587  return f_ret;
588  }
589 
602  static FaceIterator AddFaces(MeshType &m, size_t n, PointerUpdater<FacePointer> &pu)
603  {
604  pu.Clear();
605  if(n == 0) return m.face.end();
606  if(!m.face.empty()) // if the vector is empty we cannot find the last valid element
607  {
608  pu.oldBase=&*m.face.begin();
609  pu.oldEnd=&m.face.back()+1;
610  }
611  // The actual resize
612  m.face.resize(m.face.size()+n);
613  m.fn+=int(n);
614 
615  size_t siz=(size_t)(m.face.size()-n);
616  FaceIterator firstNewFace = m.face.begin();
617  advance(firstNewFace,siz);
618 
619  typename std::set<PointerToAttribute>::iterator ai;
620  for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai)
621  ((PointerToAttribute)(*ai)).Resize(m.face.size());
622 
623  pu.newBase = &*m.face.begin();
624  pu.newEnd = &m.face.back()+1;
625 
626  if(pu.NeedUpdate())
627  {
628  if(HasFFAdjacency(m))
629  { // cycle on all the faces except the new ones
630  for(FaceIterator fi=m.face.begin();fi!=firstNewFace;++fi)
631  if(!(*fi).IsD())
632  for(int i = 0; i < (*fi).VN(); ++i)
633  if ((*fi).cFFp(i)!=0) pu.Update((*fi).FFp(i));
634  }
635 
636  if(HasPerVertexVFAdjacency(m) && HasPerFaceVFAdjacency(m))
637  { // cycle on all the faces except the new ones
638  for(FaceIterator fi=m.face.begin();fi!=firstNewFace;++fi)
639  if(!(*fi).IsD())
640  for(int i = 0; i < (*fi).VN(); ++i)
641  if ((*fi).cVFp(i)!=0) pu.Update((*fi).VFp(i));
642 
643  for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
644  if(!(*vi).IsD() && (*vi).cVFp()!=0)
645  pu.Update((*vi).VFp());
646  }
647 
648  if(HasEFAdjacency(m))
649  {
650  for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei)
651  if(!(*ei).IsD() && (*ei).cEFp()!=0)
652  pu.Update((*ei).EFp());
653  }
654 
655  if(HasHFAdjacency(m))
656  {
657  for (HEdgeIterator hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi)
658  if(!(*hi).IsD() && (*hi).cHFp()!=0)
659  pu.Update((*hi).HFp());
660  }
661  }
662  return firstNewFace;
663  }
664 
665  /* +++++++++++++++ Deleting ++++++++++++++++ */
666 
670  static void DeleteFace(MeshType &m, FaceType &f)
671  {
672  assert(&f >= &m.face.front() && &f <= &m.face.back());
673  assert(!f.IsD());
674  f.Dealloc();
675  f.SetD();
676  --m.fn;
677  }
678 
682  static void DeleteVertex(MeshType &m, VertexType &v)
683  {
684  assert(&v >= &m.vert.front() && &v <= &m.vert.back());
685  assert(!v.IsD());
686  v.SetD();
687  --m.vn;
688  }
689 
693  static void DeleteEdge(MeshType &m, EdgeType &e)
694  {
695  assert(&e >= &m.edge.front() && &e <= &m.edge.back());
696  assert(!e.IsD());
697  e.SetD();
698  --m.en;
699  }
700 
704  static void DeleteHEdge(MeshType &m, HEdgeType &h)
705  {
706  assert(&h >= &m.hedge.front() && &h <= &m.hedge.back());
707  assert(!h.IsD());
708  h.SetD();
709  --m.hn;
710  }
711 
712  /*
713  Function to rearrange the vertex vector according to a given index permutation
714  the permutation is vector such that after calling this function
715 
716  m.vert[ newVertIndex[i] ] = m.vert[i];
717 
718  e.g. newVertIndex[i] is the new index of the vertex i
719 
720  */
721  static void PermutateVertexVector(MeshType &m, PointerUpdater<VertexPointer> &pu)
722  {
723  if(m.vert.empty()) return;
724  for(size_t i=0;i<m.vert.size();++i)
725  {
726  if(pu.remap[i]<size_t(m.vn))
727  {
728  assert(!m.vert[i].IsD());
729  m.vert[ pu.remap [i] ].ImportData(m.vert[i]);
730  if(HasVFAdjacency(m))
731  {
732  if (m.vert[i].IsVFInitialized())
733  {
734  m.vert[ pu.remap[i] ].VFp() = m.vert[i].cVFp();
735  m.vert[ pu.remap[i] ].VFi() = m.vert[i].cVFi();
736  }
737  else m.vert [ pu.remap[i] ].VFClear();
738  }
739  if(HasVEAdjacency(m))
740  {
741  if (m.vert[i].IsVEInitialized())
742  {
743  m.vert[ pu.remap[i] ].VEp() = m.vert[i].cVEp();
744  m.vert[ pu.remap[i] ].VEi() = m.vert[i].cVEi();
745  }
746  else m.vert [ pu.remap[i] ].VEClear();
747  }
748  }
749  }
750 
751  // reorder the optional atttributes in m.vert_attr to reflect the changes
752  ReorderAttribute(m.vert_attr,pu.remap,m);
753 
754  // setup the pointer updater
755  pu.oldBase = &m.vert[0];
756  pu.oldEnd = &m.vert.back()+1;
757 
758  // resize
759  m.vert.resize(m.vn);
760 
761  // setup the pointer updater
762  pu.newBase = (m.vert.empty())?0:&m.vert[0];
763  pu.newEnd = (m.vert.empty())?0:&m.vert.back()+1;
764 
765  // resize the optional atttributes in m.vert_attr to reflect the changes
766  ResizeAttribute(m.vert_attr,m.vn,m);
767 
768  // Loop on the face to update the pointers FV relation (vertex refs)
769  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
770  if(!(*fi).IsD())
771  for(int i=0;i<fi->VN();++i)
772  {
773  size_t oldIndex = (*fi).V(i) - pu.oldBase;
774  assert(pu.oldBase <= (*fi).V(i) && oldIndex < pu.remap.size());
775  (*fi).V(i) = pu.newBase+pu.remap[oldIndex];
776  }
777  // Loop on the edges to update the pointers EV relation
778  if(HasEVAdjacency(m))
779  for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
780  if(!(*ei).IsD())
781  {
782  pu.Update((*ei).V(0));
783  pu.Update((*ei).V(1));
784  }
785  }
786 
787  static void CompactEveryVector( MeshType &m)
788  {
789  CompactVertexVector(m);
790  CompactEdgeVector(m);
791  CompactFaceVector(m);
792  }
793 
794 
802  static void CompactVertexVector( MeshType &m, PointerUpdater<VertexPointer> &pu )
803  {
804  // If already compacted fast return please!
805  if(m.vn==(int)m.vert.size()) return;
806 
807  // newVertIndex [ <old_vert_position> ] gives you the new position of the vertex in the vector;
808  pu.remap.resize( m.vert.size(),std::numeric_limits<size_t>::max() );
809 
810  size_t pos=0;
811  size_t i=0;
812 
813  for(i=0;i<m.vert.size();++i)
814  {
815  if(!m.vert[i].IsD())
816  {
817  pu.remap[i]=pos;
818  ++pos;
819  }
820  }
821  assert((int)pos==m.vn);
822 
823  PermutateVertexVector(m, pu);
824  }
825 
827  static void CompactVertexVector( MeshType &m ) {
829  CompactVertexVector(m,pu);
830  }
831 
840  static void CompactEdgeVector( MeshType &m, PointerUpdater<EdgePointer> &pu )
841  {
842  // If already compacted fast return please!
843  if(m.en==(int)m.edge.size()) return;
844 
845  // remap [ <old_edge_position> ] gives you the new position of the edge in the vector;
846  pu.remap.resize( m.edge.size(),std::numeric_limits<size_t>::max() );
847 
848  size_t pos=0;
849  size_t i=0;
850 
851  for(i=0;i<m.edge.size();++i)
852  {
853  if(!m.edge[i].IsD())
854  {
855  pu.remap[i]=pos;
856  ++pos;
857  }
858  }
859  assert((int)pos==m.en);
860 
861  // the actual copying of the data.
862  for(size_t i=0;i<m.edge.size();++i)
863  {
864  if(pu.remap[i]<size_t(m.en)) // uninitialized entries in the remap vector has max_int value;
865  {
866  assert(!m.edge[i].IsD());
867  m.edge[ pu.remap [i] ].ImportData(m.edge[i]);
868  // copy the vertex reference (they are not data!)
869  m.edge[ pu.remap[i] ].V(0) = m.edge[i].cV(0);
870  m.edge[ pu.remap[i] ].V(1) = m.edge[i].cV(1);
871  // Now just copy the adjacency pointers (without changing them, to be done later)
872  if(HasVEAdjacency(m))
873  //if (m.edge[i].cVEp(0)!=0)
874  {
875  m.edge[ pu.remap[i] ].VEp(0) = m.edge[i].cVEp(0);
876  m.edge[ pu.remap[i] ].VEi(0) = m.edge[i].cVEi(0);
877  m.edge[ pu.remap[i] ].VEp(1) = m.edge[i].cVEp(1);
878  m.edge[ pu.remap[i] ].VEi(1) = m.edge[i].cVEi(1);
879  }
880  if(HasEEAdjacency(m))
881 // if (m.edge[i].cEEp(0)!=0)
882  {
883  m.edge[ pu.remap[i] ].EEp(0) = m.edge[i].cEEp(0);
884  m.edge[ pu.remap[i] ].EEi(0) = m.edge[i].cEEi(0);
885  m.edge[ pu.remap[i] ].EEp(1) = m.edge[i].cEEp(1);
886  m.edge[ pu.remap[i] ].EEi(1) = m.edge[i].cEEi(1);
887  }
888  }
889  }
890 
891  // reorder the optional attributes in m.vert_attr to reflect the changes
892  ReorderAttribute(m.edge_attr, pu.remap,m);
893 
894  // setup the pointer updater
895  pu.oldBase = &m.edge[0];
896  pu.oldEnd = &m.edge.back()+1;
897 
898  // THE resize
899  m.edge.resize(m.en);
900 
901  // setup the pointer updater
902  pu.newBase = (m.edge.empty())?0:&m.edge[0];
903  pu.newEnd = (m.edge.empty())?0:&m.edge.back()+1;
904 
905  // resize the optional atttributes in m.vert_attr to reflect the changes
906  ResizeAttribute(m.edge_attr,m.en,m);
907 
908  // Loop on the vertices to update the pointers of VE relation
909  if(HasVEAdjacency(m))
910  for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
911  if(!(*vi).IsD()) pu.Update((*vi).VEp());
912 
913  // Loop on the edges to update the pointers EE VE relation
914  for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
915  for(unsigned int i=0;i<2;++i)
916  {
917  if(HasVEAdjacency(m))
918  pu.Update((*ei).VEp(i));
919  if(HasEEAdjacency(m))
920  pu.Update((*ei).EEp(i));
921  }
922  }
923 
925  static void CompactEdgeVector( MeshType &m ) {
927  CompactEdgeVector(m,pu);
928  }
929 
938  static void CompactFaceVector( MeshType &m, PointerUpdater<FacePointer> &pu )
939  {
940  // If already compacted fast return please!
941  if(m.fn==(int)m.face.size()) return;
942 
943  // newFaceIndex [ <old_face_position> ] gives you the new position of the face in the vector;
944  pu.remap.resize( m.face.size(),std::numeric_limits<size_t>::max() );
945 
946  size_t pos=0;
947  for(size_t i=0;i<m.face.size();++i)
948  {
949  if(!m.face[i].IsD())
950  {
951  if(pos!=i)
952  {
953  m.face[pos].ImportData(m.face[i]);
954  if(FaceType::HasPolyInfo())
955  {
956  m.face[pos].Dealloc();
957  m.face[pos].Alloc(m.face[i].VN());
958  }
959  for(int j=0;j<m.face[i].VN();++j)
960  m.face[pos].V(j) = m.face[i].V(j);
961 
962  if(HasVFAdjacency(m))
963  for(int j=0;j<m.face[i].VN();++j)
964  {
965  if (m.face[i].IsVFInitialized(j)) {
966  m.face[pos].VFp(j) = m.face[i].cVFp(j);
967  m.face[pos].VFi(j) = m.face[i].cVFi(j);
968  }
969  else m.face[pos].VFClear(j);
970  }
971  if(HasFFAdjacency(m))
972  for(int j=0;j<m.face[i].VN();++j)
973  {
974  m.face[pos].FFp(j) = m.face[i].cFFp(j);
975  m.face[pos].FFi(j) = m.face[i].cFFi(j);
976  }
977  }
978  pu.remap[i]=pos;
979  ++pos;
980  }
981  }
982  assert((int)pos==m.fn);
983 
984  // reorder the optional atttributes in m.face_attr to reflect the changes
985  ReorderAttribute(m.face_attr,pu.remap,m);
986 
987  FacePointer fbase=&m.face[0];
988 
989  // Loop on the vertices to correct VF relation
990  if(HasVFAdjacency(m))
991  {
992  for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
993  if(!(*vi).IsD())
994  {
995  if ((*vi).IsVFInitialized() && (*vi).VFp()!=0 )
996  {
997  size_t oldIndex = (*vi).cVFp() - fbase;
998  assert(fbase <= (*vi).cVFp() && oldIndex < pu.remap.size());
999  (*vi).VFp() = fbase+pu.remap[oldIndex];
1000  }
1001  }
1002  }
1003 
1004  // Loop on the faces to correct VF and FF relations
1005  pu.oldBase = &m.face[0];
1006  pu.oldEnd = &m.face.back()+1;
1007  for(size_t i=m.fn;i<m.face.size();++i)
1008  m.face[i].Dealloc();
1009  m.face.resize(m.fn);
1010  pu.newBase = (m.face.empty())?0:&m.face[0];
1011  pu.newEnd = (m.face.empty())?0:&m.face.back()+1;
1012 
1013 
1014  // resize the optional atttributes in m.face_attr to reflect the changes
1015  ResizeAttribute(m.face_attr,m.fn,m);
1016 
1017  // now we update the various (not null) face pointers (inside VF and FF relations)
1018  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1019  if(!(*fi).IsD())
1020  {
1021  if(HasVFAdjacency(m))
1022  for(int i=0;i<(*fi).VN();++i)
1023  if ((*fi).IsVFInitialized(i) && (*fi).VFp(i)!=0 )
1024  {
1025  size_t oldIndex = (*fi).VFp(i) - fbase;
1026  assert(fbase <= (*fi).VFp(i) && oldIndex < pu.remap.size());
1027  (*fi).VFp(i) = fbase+pu.remap[oldIndex];
1028  }
1029  if(HasFFAdjacency(m))
1030  for(int i=0;i<(*fi).VN();++i)
1031  if ((*fi).cFFp(i)!=0)
1032  {
1033  size_t oldIndex = (*fi).FFp(i) - fbase;
1034  assert(fbase <= (*fi).FFp(i) && oldIndex < pu.remap.size());
1035  (*fi).FFp(i) = fbase+pu.remap[oldIndex];
1036  }
1037  }
1038 
1039 
1040 
1041  }
1042 
1044  static void CompactFaceVector( MeshType &m ) {
1046  CompactFaceVector(m,pu);
1047  }
1048 
1049 
1050 
1051 public:
1052 
1055  template <class ATTR_TYPE>
1056  static
1057  bool IsValidHandle( MeshType & m, const typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & a){
1058  if(a._handle == NULL) return false;
1059  for(AttrIterator i = m.vert_attr.begin(); i!=m.vert_attr.end();++i)
1060  if ( (*i).n_attr == a.n_attr ) return true;
1061  return false;
1062  }
1063 
1068  template <class ATTR_TYPE>
1069  static
1070  typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
1071  AddPerVertexAttribute( MeshType & m, std::string name){
1072  PAIte i;
1073  PointerToAttribute h;
1074  h._name = name;
1075  if(!name.empty()){
1076  i = m.vert_attr.find(h);
1077  assert(i ==m.vert_attr.end() );// an attribute with this name exists
1078  }
1079 
1080  h._sizeof = sizeof(ATTR_TYPE);
1081  h._padding = 0;
1082  h._handle = new SimpleTempData<VertContainer,ATTR_TYPE>(m.vert);
1083  h._type = typeid(ATTR_TYPE);
1084  m.attrn++;
1085  h.n_attr = m.attrn;
1086  std::pair < AttrIterator , bool> res = m.vert_attr.insert(h);
1087  return typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr );
1088  }
1089 
1090  template <class ATTR_TYPE>
1091  static typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
1092  AddPerVertexAttribute( MeshType & m){
1093  return AddPerVertexAttribute<ATTR_TYPE>(m,std::string(""));
1094  }
1095 
1100  template <class ATTR_TYPE>
1101  static
1102  typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
1103  GetPerVertexAttribute( MeshType & m, std::string name = std::string("")){
1104  typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> h;
1105  if(!name.empty()){
1106  h = FindPerVertexAttribute<ATTR_TYPE>(m,name);
1107  if(IsValidHandle(m,h))
1108  return h;
1109  }
1110  return AddPerVertexAttribute<ATTR_TYPE>(m,name);
1111  }
1112 
1116  template <class ATTR_TYPE>
1117  static typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>
1118  FindPerVertexAttribute( MeshType & m, const std::string & name)
1119  {
1120  assert(!name.empty());
1121  PointerToAttribute h1; h1._name = name;
1122  typename std::set<PointerToAttribute > :: iterator i;
1123 
1124  i =m.vert_attr.find(h1);
1125  if(i!=m.vert_attr.end())
1126  if((*i)._sizeof == sizeof(ATTR_TYPE) ){
1127  if( (*i)._padding != 0 ){
1128  PointerToAttribute attr = (*i); // copy the PointerToAttribute
1129  m.vert_attr.erase(i); // remove it from the set
1130  FixPaddedPerVertexAttribute<ATTR_TYPE>(m,attr);
1131  std::pair<AttrIterator,bool> new_i = m.vert_attr.insert(attr); // insert the modified PointerToAttribute
1132  assert(new_i.second);
1133  i = new_i.first;
1134  }
1135  return typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE>((*i)._handle,(*i).n_attr);
1136  }
1137  return typename MeshType:: template PerVertexAttributeHandle<ATTR_TYPE>(NULL,0);
1138  }
1139 
1143  template <class ATTR_TYPE>
1144  static void GetAllPerVertexAttribute(MeshType & m, std::vector<std::string> &all){
1145  all.clear();
1146  typename std::set<PointerToAttribute > ::const_iterator i;
1147  for(i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i )
1148  if(!(*i)._name.empty())
1149  {
1150  typename MeshType:: template PerVertexAttributeHandle<ATTR_TYPE> hh;
1151  hh = Allocator<MeshType>:: template FindPerVertexAttribute <ATTR_TYPE>(m,(*i)._name);
1152  if(IsValidHandle<ATTR_TYPE>(m,hh))
1153  all.push_back((*i)._name);
1154  }
1155  }
1156 
1157  template <class ATTR_TYPE>
1158  static
1159  void
1160  ClearPerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & h, const ATTR_TYPE & initVal = ATTR_TYPE()){
1161  typename std::set<PointerToAttribute > ::iterator i;
1162  for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i)
1163  if( (*i)._handle == h._handle ){
1164  for(typename MeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1165  h[vi] = initVal;
1166  return;}
1167  assert(0);
1168  }
1169 
1172  template <class ATTR_TYPE>
1173  static
1174  void
1175  DeletePerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & h){
1176  typename std::set<PointerToAttribute > ::iterator i;
1177  for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i)
1178  if( (*i)._handle == h._handle ){
1179  delete ((SimpleTempData<VertContainer,ATTR_TYPE>*)(*i)._handle);
1180  m.vert_attr.erase(i);
1181  return;}
1182  }
1183 
1184  // Generic DeleteAttribute.
1185  // It must not crash if you try to delete a non existing attribute,
1186  // because you do not have a way of asking for a handle of an attribute for which you do not know the type.
1187  static
1188  bool DeletePerVertexAttribute( MeshType & m, std::string name){
1189  AttrIterator i;
1190  PointerToAttribute h1; h1._name = name;
1191  i = m.vert_attr.find(h1);
1192  if(i==m.vert_attr.end()) return false;
1193  delete ((SimpleTempDataBase*)(*i)._handle);
1194  m.vert_attr.erase(i);
1195  return true;
1196  }
1197 
1198 
1199 
1201  template <class ATTR_TYPE>
1202  static
1203  bool IsValidHandle( MeshType & m, const typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> & a){
1204  if(a._handle == NULL) return false;
1205  for(AttrIterator i = m.edge_attr.begin(); i!=m.edge_attr.end();++i)
1206  if ( (*i).n_attr == a.n_attr ) return true;
1207  return false;
1208  }
1209 
1210  template <class ATTR_TYPE>
1211  static
1212  typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
1213  AddPerEdgeAttribute( MeshType & m, std::string name){
1214  PAIte i;
1215  PointerToAttribute h;
1216  h._name = name;
1217  if(!name.empty()){
1218  i = m.edge_attr.find(h);
1219  assert(i ==m.edge_attr.end() );// an attribute with this name exists
1220  }
1221  h._sizeof = sizeof(ATTR_TYPE);
1222  h._padding = 0;
1223  // h._typename = typeid(ATTR_TYPE).name();
1224  h._handle = new SimpleTempData<EdgeContainer,ATTR_TYPE>(m.edge);
1225  h._type = typeid(ATTR_TYPE);
1226  m.attrn++;
1227  h.n_attr = m.attrn;
1228  std::pair < AttrIterator , bool> res = m.edge_attr.insert(h);
1229  return typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr);
1230  }
1231 
1232  template <class ATTR_TYPE>
1233  static
1234  typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
1235  AddPerEdgeAttribute( MeshType & m){
1236  return AddPerEdgeAttribute<ATTR_TYPE>(m,std::string(""));
1237  }
1238 
1243  template <class ATTR_TYPE>
1244  static
1245  typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
1246  GetPerEdgeAttribute( MeshType & m, std::string name = std::string("")){
1247  typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> h;
1248  if(!name.empty()){
1249  h = FindPerEdgeAttribute<ATTR_TYPE>(m,name);
1250  if(IsValidHandle(m,h))
1251  return h;
1252  }
1253  return AddPerEdgeAttribute<ATTR_TYPE>(m,name);
1254  }
1255 
1256 
1257  template <class ATTR_TYPE>
1258  static
1259  typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>
1260  FindPerEdgeAttribute( MeshType & m, const std::string & name){
1261  assert(!name.empty());
1262  PointerToAttribute h1; h1._name = name;
1263  typename std::set<PointerToAttribute > ::const_iterator i;
1264 
1265  i =m.edge_attr.find(h1);
1266  if(i!=m.edge_attr.end())
1267  if((*i)._sizeof == sizeof(ATTR_TYPE) ){
1268  if( (*i)._padding != 0 ){
1269  PointerToAttribute attr = (*i); // copy the PointerToAttribute
1270  m.edge_attr.erase(i); // remove it from the set
1271  FixPaddedPerEdgeAttribute<ATTR_TYPE>(m,attr);
1272  std::pair<AttrIterator,bool> new_i = m.edge_attr.insert(attr); // insert the modified PointerToAttribute
1273  assert(new_i.second);
1274  i = new_i.first;
1275  }
1276  return typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE>((*i)._handle,(*i).n_attr);
1277  }
1278 
1279  return typename MeshType:: template PerEdgeAttributeHandle<ATTR_TYPE>(NULL,0);
1280  }
1281 
1282  template <class ATTR_TYPE>
1283  static void GetAllPerEdgeAttribute(const MeshType & m, std::vector<std::string> &all){
1284  all.clear();
1285  typename std::set<PointerToAttribute > :: const_iterator i;
1286  for(i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i )
1287  if(!(*i)._name.empty())
1288  {
1289  typename MeshType:: template PerEdgeAttributeHandle<ATTR_TYPE> hh;
1290  hh = Allocator<MeshType>:: template FindPerEdgeAttribute <ATTR_TYPE>(m,(*i)._name);
1291  if(IsValidHandle<ATTR_TYPE>(m,hh))
1292  all.push_back((*i)._name);
1293  }
1294  }
1295 
1298  template <class ATTR_TYPE>
1299  static
1300  void
1301  DeletePerEdgeAttribute( MeshType & m,typename MeshType::template PerEdgeAttributeHandle<ATTR_TYPE> & h){
1302  typename std::set<PointerToAttribute > ::iterator i;
1303  for( i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i)
1304  if( (*i)._handle == h._handle ){
1305  delete ((SimpleTempData<FaceContainer,ATTR_TYPE>*)(*i)._handle);
1306  m.edge_attr.erase(i);
1307  return;}
1308  }
1309 
1310  // Generic DeleteAttribute.
1311  // It must not crash if you try to delete a non existing attribute,
1312  // because you do not have a way of asking for a handle of an attribute for which you do not know the type.
1313  static
1314  bool DeletePerEdgeAttribute( MeshType & m, std::string name){
1315  AttrIterator i;
1316  PointerToAttribute h1; h1._name = name;
1317  i = m.edge_attr.find(h1);
1318  if(i==m.edge_attr.end()) return false;
1319  delete ((SimpleTempDataBase*)(*i)._handle);
1320  m.edge_attr.erase(i);
1321  return true;
1322  }
1323 
1325  template <class ATTR_TYPE>
1326  static
1327  bool IsValidHandle( MeshType & m, const typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> & a){
1328  if(a._handle == NULL) return false;
1329  for(AttrIterator i = m.face_attr.begin(); i!=m.face_attr.end();++i)
1330  if ( (*i).n_attr == a.n_attr ) return true;
1331  return false;
1332  }
1333 
1334  template <class ATTR_TYPE>
1335  static
1336  typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
1337  AddPerFaceAttribute( MeshType & m, std::string name){
1338  PAIte i;
1339  PointerToAttribute h;
1340  h._name = name;
1341  if(!name.empty()){
1342  i = m.face_attr.find(h);
1343  assert(i ==m.face_attr.end() );// an attribute with this name exists
1344  }
1345 
1346  h._sizeof = sizeof(ATTR_TYPE);
1347  h._padding = 0;
1348  h._handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face);
1349  h._type = typeid(ATTR_TYPE);
1350  m.attrn++;
1351  h.n_attr = m.attrn;
1352  std::pair < AttrIterator , bool> res = m.face_attr.insert(h);
1353  return typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr);
1354  }
1355 
1356  template <class ATTR_TYPE>
1357  static
1358  typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
1359  AddPerFaceAttribute( MeshType & m){
1360  return AddPerFaceAttribute<ATTR_TYPE>(m,std::string(""));
1361  }
1362 
1367  template <class ATTR_TYPE>
1368  static
1369  typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
1370  GetPerFaceAttribute( MeshType & m, std::string name = std::string("")){
1371  typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> h;
1372  if(!name.empty()){
1373  h = FindPerFaceAttribute<ATTR_TYPE>(m,name);
1374  if(IsValidHandle(m,h))
1375  return h;
1376  }
1377  return AddPerFaceAttribute<ATTR_TYPE>(m,name);
1378  }
1379 
1380  template <class ATTR_TYPE>
1381  static
1382  typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>
1383  FindPerFaceAttribute( MeshType & m, const std::string & name){
1384  assert(!name.empty());
1385  PointerToAttribute h1; h1._name = name;
1386  typename std::set<PointerToAttribute > ::iterator i;
1387 
1388  i =m.face_attr.find(h1);
1389  if(i!=m.face_attr.end())
1390  if((*i)._sizeof == sizeof(ATTR_TYPE) ){
1391  if( (*i)._padding != 0 ){
1392  PointerToAttribute attr = (*i); // copy the PointerToAttribute
1393  m.face_attr.erase(i); // remove it from the set
1394  FixPaddedPerFaceAttribute<ATTR_TYPE>(m,attr);
1395  std::pair<AttrIterator,bool> new_i = m.face_attr.insert(attr); // insert the modified PointerToAttribute
1396  assert(new_i.second);
1397  i = new_i.first;
1398  }
1399  return typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE>((*i)._handle,(*i).n_attr);
1400  }
1401  return typename MeshType:: template PerFaceAttributeHandle<ATTR_TYPE>(NULL,0);
1402  }
1403 
1404  template <class ATTR_TYPE>
1405  static void GetAllPerFaceAttribute(MeshType & m, std::vector<std::string> &all){
1406  all.clear();
1407  typename std::set<PointerToAttribute > :: const_iterator i;
1408  for(i = m.face_attr.begin(); i != m.face_attr.end(); ++i )
1409  if(!(*i)._name.empty())
1410  {
1411  typename MeshType:: template PerFaceAttributeHandle<ATTR_TYPE> hh;
1412  hh = Allocator<MeshType>:: template FindPerFaceAttribute <ATTR_TYPE>(m,(*i)._name);
1413  if(IsValidHandle<ATTR_TYPE>(m,hh))
1414  all.push_back((*i)._name);
1415  }
1416  }
1417 
1420  template <class ATTR_TYPE>
1421  static void DeletePerFaceAttribute( MeshType & m,typename MeshType::template PerFaceAttributeHandle<ATTR_TYPE> & h){
1422  typename std::set<PointerToAttribute > ::iterator i;
1423  for( i = m.face_attr.begin(); i != m.face_attr.end(); ++i)
1424  if( (*i)._handle == h._handle ){
1425  delete ((SimpleTempData<FaceContainer,ATTR_TYPE>*)(*i)._handle);
1426  m.face_attr.erase(i);
1427  return;}
1428 
1429  }
1430 
1431  // Generic DeleteAttribute.
1432  // It must not crash if you try to delete a non existing attribute,
1433  // because you do not have a way of asking for a handle of an attribute for which you do not know the type.
1434  static bool DeletePerFaceAttribute( MeshType & m, std::string name){
1435  AttrIterator i;
1436  PointerToAttribute h1; h1._name = name;
1437  i = m.face_attr.find(h1);
1438  if(i==m.face_attr.end()) return false;
1439  delete ((SimpleTempDataBase*)(*i)._handle);
1440  m.face_attr.erase(i);
1441  return true;
1442  }
1443 
1445  template <class ATTR_TYPE>
1446  static
1447  bool IsValidHandle( MeshType & m, const typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> & a){
1448  if(a._handle == NULL) return false;
1449  for(AttrIterator i = m.mesh_attr.begin(); i!=m.mesh_attr.end();++i)
1450  if ( (*i).n_attr == a.n_attr ) return true;
1451  return false;
1452  }
1453 
1454  template <class ATTR_TYPE>
1455  static
1456  typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>
1457  AddPerMeshAttribute( MeshType & m, std::string name){
1458  PAIte i;
1459  PointerToAttribute h;
1460  h._name = name;
1461  if(!name.empty()){
1462  i = m.mesh_attr.find(h);
1463  assert(i ==m.mesh_attr.end() );// an attribute with this name exists
1464  }
1465  h._sizeof = sizeof(ATTR_TYPE);
1466  h._padding = 0;
1467  h._handle = new Attribute<ATTR_TYPE>();
1468  h._type = typeid(ATTR_TYPE);
1469  m.attrn++;
1470  h.n_attr = m.attrn;
1471  std::pair < AttrIterator , bool> res = m.mesh_attr.insert(h);
1472  return typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>(res.first->_handle,res.first->n_attr);
1473  }
1474 
1479  template <class ATTR_TYPE>
1480  static
1481  typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>
1482  GetPerMeshAttribute( MeshType & m, std::string name = std::string("")){
1483  typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> h;
1484  if(!name.empty()){
1485  h = FindPerMeshAttribute<ATTR_TYPE>(m,name);
1486  if(IsValidHandle(m,h))
1487  return h;
1488  }
1489  return AddPerMeshAttribute<ATTR_TYPE>(m,name);
1490  }
1491 
1492  template <class ATTR_TYPE>
1493  static
1494  typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>
1495  FindPerMeshAttribute( MeshType & m, const std::string & name){
1496  assert(!name.empty());
1497  PointerToAttribute h1; h1._name = name;
1498  typename std::set<PointerToAttribute > ::iterator i;
1499 
1500  i =m.mesh_attr.find(h1);
1501  if(i!=m.mesh_attr.end())
1502  if((*i)._sizeof == sizeof(ATTR_TYPE) ){
1503  if( (*i)._padding != 0 ){
1504  PointerToAttribute attr = (*i); // copy the PointerToAttribute
1505  m.mesh_attr.erase(i); // remove it from the set
1506  FixPaddedPerMeshAttribute<ATTR_TYPE>(m,attr);
1507  std::pair<AttrIterator,bool> new_i = m.mesh_attr.insert(attr); // insert the modified PointerToAttribute
1508  assert(new_i.second);
1509  i = new_i.first;
1510  }
1511 
1512  return typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE>((*i)._handle,(*i).n_attr);
1513  }
1514 
1515  return typename MeshType:: template PerMeshAttributeHandle<ATTR_TYPE>(NULL,0);
1516  }
1517 
1518  template <class ATTR_TYPE>
1519  static void GetAllPerMeshAttribute(const MeshType & m, std::vector<std::string> &all){
1520  typename std::set<PointerToAttribute > :: iterator i;
1521  for(i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i )
1522  if((*i)._sizeof == sizeof(ATTR_TYPE))
1523  all.push_back((*i)._name);
1524  }
1525 
1528  template <class ATTR_TYPE>
1529  static void DeletePerMeshAttribute( MeshType & m,typename MeshType::template PerMeshAttributeHandle<ATTR_TYPE> & h){
1530  typename std::set<PointerToAttribute > ::iterator i;
1531  for( i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i)
1532  if( (*i)._handle == h._handle ){
1533  delete (( Attribute<ATTR_TYPE> *)(*i)._handle);
1534  m.mesh_attr.erase(i);
1535  return;}
1536  }
1537 
1538  // Generic DeleteAttribute.
1539  // It must not crash if you try to delete a non existing attribute,
1540  // because you do not have a way of asking for a handle of an attribute for which you do not know the type.
1541  static bool DeletePerMeshAttribute( MeshType & m, std::string name){
1542  AttrIterator i;
1543  PointerToAttribute h1; h1._name = name;
1544  i = m.mesh_attr.find(h1);
1545  if (i==m.mesh_attr.end())
1546  return false;
1547  delete ((SimpleTempDataBase *)(*i)._handle);
1548  m.mesh_attr.erase(i);
1549  return true;
1550  }
1551 
1552  template <class ATTR_TYPE>
1553  static void FixPaddedPerVertexAttribute (MeshType & m, PointerToAttribute & pa){
1554 
1555  // create the container of the right type
1556  SimpleTempData<VertContainer,ATTR_TYPE>* _handle = new SimpleTempData<VertContainer,ATTR_TYPE>(m.vert);
1557 
1558  // copy the padded container in the new one
1559  _handle->Resize(m.vert.size());
1560  for(size_t i = 0; i < m.vert.size(); ++i){
1561  ATTR_TYPE * dest = &(*_handle)[i];
1562  char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin());
1563  memcpy((void*)dest ,
1564  (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE));
1565  }
1566 
1567  // remove the padded container
1568  delete ((SimpleTempDataBase*) pa._handle);
1569 
1570  // update the pointer to data
1571  pa._sizeof = sizeof(ATTR_TYPE);
1572 
1573  // update the pointer to data
1574  pa._handle = _handle;
1575 
1576  // zero the padding
1577  pa._padding = 0;
1578  }
1579  template <class ATTR_TYPE>
1580  static void FixPaddedPerEdgeAttribute (MeshType & m, PointerToAttribute & pa){
1581 
1582  // create the container of the right type
1583  SimpleTempData<EdgeContainer,ATTR_TYPE>* _handle = new SimpleTempData<EdgeContainer,ATTR_TYPE>(m.edge);
1584 
1585  // copy the padded container in the new one
1586  _handle->Resize(m.edge.size());
1587  for(size_t i = 0; i < m.edge.size(); ++i){
1588  ATTR_TYPE * dest = &(*_handle)[i];
1589  char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin());
1590  memcpy((void*)dest ,
1591  (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE));
1592  }
1593 
1594  // remove the padded container
1595  delete ((SimpleTempDataBase*) pa._handle);
1596 
1597  // update the pointer to data
1598  pa._sizeof = sizeof(ATTR_TYPE);
1599 
1600  // update the pointer to data
1601  pa._handle = _handle;
1602 
1603  // zero the padding
1604  pa._padding = 0;
1605  }
1606 
1607  template <class ATTR_TYPE>
1608  static void FixPaddedPerFaceAttribute ( MeshType & m,PointerToAttribute & pa){
1609 
1610  // create the container of the right type
1611  SimpleTempData<FaceContainer,ATTR_TYPE>* _handle = new SimpleTempData<FaceContainer,ATTR_TYPE>(m.face);
1612 
1613  // copy the padded container in the new one
1614  _handle->Resize(m.face.size());
1615  for(size_t i = 0; i < m.face.size(); ++i){
1616  ATTR_TYPE * dest = &(*_handle)[i];
1617  char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin());
1618  memcpy((void*)dest ,
1619  (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE));
1620  }
1621 
1622  // remove the padded container
1623  delete ((SimpleTempDataBase*) pa._handle);
1624 
1625  // update the pointer to data
1626  pa._sizeof = sizeof(ATTR_TYPE);
1627 
1628  // update the pointer to data
1629  pa._handle = _handle;
1630 
1631  // zero the padding
1632  pa._padding = 0;
1633  }
1634 
1635 
1636  template <class ATTR_TYPE>
1637  static void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){
1638 
1639  // create the container of the right type
1640  Attribute<ATTR_TYPE> * _handle = new Attribute<ATTR_TYPE>();
1641 
1642  // copy the padded container in the new one
1643  char * ptr = (char*)( ((Attribute<ATTR_TYPE> *)pa._handle)->DataBegin());
1644  memcpy((void*)_handle->attribute ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE));
1645 
1646  // remove the padded container
1647  delete ( (Attribute<ATTR_TYPE> *) pa._handle);
1648 
1649  // update the pointer to data
1650  pa._sizeof = sizeof(ATTR_TYPE);
1651 
1652  // update the pointer to data
1653  pa._handle = _handle;
1654 
1655  // zero the padding
1656  pa._padding = 0;
1657  }
1658 
1659 }; // end Allocator class
1660 
1661  // end doxygen group trimesh
1663 } // end namespace tri
1664 } // end namespace vcg
1665 
1666 #endif