VCG Library
append.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_APPEND
24 #define __VCGLIB_APPEND
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 {
39 template<class MeshLeft, class ConstMeshRight>
40 class Append
41 {
42 public:
43  typedef typename MeshLeft::ScalarType ScalarLeft;
44  typedef typename MeshLeft::CoordType CoordLeft;
45  typedef typename MeshLeft::VertexType VertexLeft;
46  typedef typename MeshLeft::EdgeType EdgeLeft;
47  typedef typename MeshLeft::FaceType FaceLeft;
48  typedef typename MeshLeft::HEdgeType HEdgeLeft;
49  typedef typename MeshLeft::TetraType TetraLeft;
50  typedef typename MeshLeft::VertexPointer VertexPointerLeft;
51  typedef typename MeshLeft::VertexIterator VertexIteratorLeft;
52  typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft;
53  typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft;
54  typedef typename MeshLeft::FaceIterator FaceIteratorLeft;
55  typedef typename MeshLeft::TetraIterator TetraIteratorLeft;
56 
57 
58  typedef typename ConstMeshRight::ScalarType ScalarRight;
59  typedef typename ConstMeshRight::CoordType CoordRight;
60  typedef typename ConstMeshRight::VertexType VertexRight;
61  typedef typename ConstMeshRight::EdgeType EdgeRight;
62  typedef typename ConstMeshRight::HEdgeType HEdgeRight;
63  typedef typename ConstMeshRight::FaceType FaceRight;
64  typedef typename ConstMeshRight::TetraType TetraRight;
65  typedef typename ConstMeshRight::TetraPointer TetraPointerRight;
66  typedef typename ConstMeshRight::TetraIterator TetraIteratorRight;
67  typedef typename ConstMeshRight::VertexPointer VertexPointerRight;
68  typedef typename ConstMeshRight::VertexIterator VertexIteratorRight;
69  typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight;
70  typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight;
71  typedef typename ConstMeshRight::FaceIterator FaceIteratorRight;
72  typedef typename ConstMeshRight::FacePointer FacePointerRight;
73 
74  struct Remap{
75  static size_t InvalidIndex() { return std::numeric_limits<size_t>::max(); }
76  std::vector<size_t> vert, face, edge, hedge, tetra;
77  };
78 
79  static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){
80  // Vertex to Edge Adj
81  if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){
82  size_t i = Index(mr,vr.cVEp());
83  vl.VEp() = (i>ml.edge.size())? 0 : &ml.edge[remap.edge[i]];
84  vl.VEi() = vr.VEi();
85  }
86 
87  // Vertex to Face Adj
88  if(HasPerVertexVFAdjacency(ml) && HasPerVertexVFAdjacency(mr) && vr.cVFp() != 0 ){
89  size_t i = Index(mr,vr.cVFp());
90  vl.VFp() = (i>ml.face.size())? 0 :&ml.face[remap.face[i]];
91  vl.VFi() = vr.VFi();
92  }
93 
94  // Vertex to HEdge Adj
95  if(HasVHAdjacency(ml) && HasVHAdjacency(mr) && vr.cVHp() != 0){
96  vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]];
97  vl.VHi() = vr.VHi();
98  }
99 
100  // Vertex to Tetra Adj
101  if(HasVTAdjacency(ml) && HasVTAdjacency(mr) && vr.cVTp() != 0){
102  size_t i = Index(mr, vr.cVTp());
103  vl.VTp() = (i > ml.edge.size()) ? 0 : &ml.tetra[remap.tetra[i]];
104  vl.VTi() = vr.VTi();
105  }
106  }
107 
108  static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap)
109  {
110  // Edge to Edge Adj
111  if(HasEEAdjacency(ml) && HasEEAdjacency(mr))
112  for(unsigned int vi = 0; vi < 2; ++vi)
113  {
114  size_t idx = Index(mr,er.cEEp(vi));
115  el.EEp(vi) = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
116  el.EEi(vi) = er.cEEi(vi);
117  }
118 
119  // Edge to Face Adj
120  if(HasEFAdjacency(ml) && HasEFAdjacency(mr)){
121  size_t idx = Index(mr,er.cEFp());
122  el.EFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
123  el.EFi() = er.cEFi();
124  }
125 
126  // Edge to HEdge Adj
127  if(HasEHAdjacency(ml) && HasEHAdjacency(mr))
128  el.EHp() = &ml.hedge[remap.hedge[Index(mr,er.cEHp())]];
129  }
130 
131 
132  static void ImportFaceAdj(MeshLeft &ml, ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap )
133  {
134  // Face to Edge Adj
135  if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){
136  assert(fl.VN() == fr.VN());
137  for( int vi = 0; vi < fl.VN(); ++vi ){
138  size_t idx = remap.edge[Index(mr,fr.cFEp(vi))];
139  if(idx!=Remap::InvalidIndex())
140  fl.FEp(vi) = &ml.edge[idx];
141  }
142  }
143 
144  // Face to Face Adj
145  if(HasFFAdjacency(ml) && HasFFAdjacency(mr)){
146  assert(fl.VN() == fr.VN());
147  for( int vi = 0; vi < fl.VN(); ++vi ){
148  size_t idx = remap.face[Index(mr,fr.cFFp(vi))];
149  if(idx!=Remap::InvalidIndex()){
150  assert(idx >= 0 && idx < ml.face.size());
151  fl.FFp(vi) = &ml.face[idx];
152  fl.FFi(vi) = fr.cFFi(vi);
153  }
154  }
155  }
156 
157  // Vertex to Face Adj
158  if(HasPerFaceVFAdjacency(ml) && HasPerFaceVFAdjacency(mr))
159  {
160  assert(fl.VN() == fr.VN());
161  for (int vi = 0; vi < fl.VN(); ++vi)
162  {
163  const auto * fp = fr.cVFp(vi);
164  const auto vfindex = fr.cVFi(vi);
165  size_t fidx = (fp == nullptr) ? Remap::InvalidIndex() : remap.face[Index(mr,fp)];
166 
167  if (fidx == Remap::InvalidIndex()) // end of VF chain (or not initialized)
168  {
169  fl.VFClear(vi);
170  assert(fl.cVFi(vi) == -1);
171  }
172  else
173  {
174  assert(fidx >= 0 && fidx < ml.face.size());
175  fl.VFp(vi) = &ml.face[fidx];
176  fl.VFi(vi) = vfindex;
177  }
178  }
179  }
180 
181  // Face to HEedge Adj
182  if(HasFHAdjacency(ml) && HasFHAdjacency(mr))
183  fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]];
184  }
185 
186  static void ImportHEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){
187  // HEdge to Vertex Adj
188  if(HasHVAdjacency(ml) && HasHVAdjacency(mr))
189  hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]];
190 
191  // HEdge to Edge Adj
192  if(HasHEAdjacency(ml) && HasHEAdjacency(mr)){
193  size_t idx = Index(mr,hr.cHEp()) ;
194  hl.HEp() = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
195  }
196 
197  // HEdge to Face Adj
198  if(HasHFAdjacency(ml) && HasHFAdjacency(mr)){
199  size_t idx = Index(mr,hr.cHFp());
200  hl.HFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
201  }
202 
203 
204  // HEdge to Opposite HEdge Adj
205  if(HasHOppAdjacency(ml) && HasHOppAdjacency(mr))
206  hl.HOp() = &ml.hedge[remap.hedge[Index(mr,hr.cHOp())]];
207 
208  // HEdge to Next HEdge Adj
209  if(HasHNextAdjacency(ml) && HasHNextAdjacency(mr))
210  hl.HNp() = &ml.hedge[remap.hedge[Index(mr,hr.cHNp())]];
211 
212  // HEdge to Next HEdge Adj
213  if(HasHPrevAdjacency(ml) && HasHPrevAdjacency(mr))
214  hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]];
215  }
216 
217  static void ImportTetraAdj(MeshLeft &ml, ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap )
218  {
219  // Tetra to Tetra Adj
220  if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){
221  for( int vi = 0; vi < 4; ++vi ){
222  size_t idx = remap.tetra[Index(mr,tr.cTTp(vi))];
223  if(idx != Remap::InvalidIndex()){
224  tl.TTp(vi) = &ml.tetra[idx];
225  tl.TTi(vi) = tr.cTTi(vi);
226  }
227  }
228  }
229 }
230 
231 // Append Right Mesh to the Left Mesh
232 // Append::Mesh(ml, mr) is equivalent to ml += mr.
233 // Note MeshRigth could be costant...
254 static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, const bool adjFlag = false)
255 {
256  // Note that if the the selection of the vertexes is not consistent with the face selection
257  // the append could build faces referencing non existent vertices
258  // so it is mandatory that the selection of the vertices reflects the loose selection
259  // from edges and faces (e.g. if a face is selected all its vertices must be selected).
260  // note the use of the parameter for preserving existing vertex selection.
261  if(selected)
262  {
263  assert(adjFlag == false || ml.IsEmpty()); // It is rather meaningless to partially copy adj relations.
266  }
267 
268  // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr
269  // and build the remapping for all
270 
271  Remap remap;
272 
273  // vertex
274  remap.vert.resize(mr.vert.size(), Remap::InvalidIndex());
275  VertexIteratorLeft vp;
277  if(selected)
278  vp=Allocator<MeshLeft>::AddVertices(ml,int(svn));
279  else
281 
282  for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi)
283  {
284  if(!(*vi).IsD() && (!selected || (*vi).IsS()))
285  {
286  size_t ind=Index(mr,*vi);
287  remap.vert[ind]=int(Index(ml,*vp));
288  ++vp;
289  }
290  }
291  // edge
292  remap.edge.resize(mr.edge.size(), Remap::InvalidIndex());
293  EdgeIteratorLeft ep;
295  if(selected) ep=Allocator<MeshLeft>::AddEdges(ml,sen);
296  else ep=Allocator<MeshLeft>::AddEdges(ml,mr.en);
297 
298  for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei)
299  if(!(*ei).IsD() && (!selected || (*ei).IsS())){
300  size_t ind=Index(mr,*ei);
301  remap.edge[ind]=int(Index(ml,*ep));
302  ++ep;
303  }
304 
305  // face
306  remap.face.resize(mr.face.size(), Remap::InvalidIndex());
307  FaceIteratorLeft fp;
309  if(selected) fp=Allocator<MeshLeft>::AddFaces(ml,sfn);
310  else fp=Allocator<MeshLeft>::AddFaces(ml,mr.fn);
311 
312  for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi)
313  if(!(*fi).IsD() && (!selected || (*fi).IsS())){
314  size_t ind=Index(mr,*fi);
315  remap.face[ind]=int(Index(ml,*fp));
316  ++fp;
317  }
318 
319  // hedge
320  remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex());
321  for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi)
322  if(!(*hi).IsD() && (!selected || (*hi).IsS())){
323  size_t ind=Index(mr,*hi);
324  assert(remap.hedge[ind]==Remap::InvalidIndex());
325  HEdgeIteratorLeft hp = Allocator<MeshLeft>::AddHEdges(ml,1);
326  (*hp).ImportData(*(hi));
327  remap.hedge[ind]=Index(ml,*hp);
328  }
329 
330  remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex());
331  for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti)
332  if (!(*ti).IsD() && (!selected || (*ti).IsS())) {
333  size_t idx = Index(mr, *ti);
334  assert (remap.tetra[idx] == Remap::InvalidIndex());
335  TetraIteratorLeft tp = Allocator<MeshLeft>::AddTetras(ml, 1);
336  (*tp).ImportData(*ti);
337  remap.tetra[idx] = Index(ml, *tp);
338  }
339 
340  // phase 2.
341  // copy data from mr to its corresponding elements in ml and adjacencies
342 
343  // vertex
344  for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi)
345  if( !(*vi).IsD() && (!selected || (*vi).IsS())){
346  ml.vert[remap.vert[Index(mr,*vi)]].ImportData(*vi);
347  if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,*vi)]],*vi,remap);
348  }
349 
350  // edge
351  for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei)
352  if(!(*ei).IsD() && (!selected || (*ei).IsS())){
353  ml.edge[remap.edge[Index(mr,*ei)]].ImportData(*ei);
354  // Edge to Vertex Adj
355  EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]];
356  if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){
357  el.V(0) = &ml.vert[remap.vert[Index(mr,ei->cV(0))]];
358  el.V(1) = &ml.vert[remap.vert[Index(mr,ei->cV(1))]];
359  }
360  if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap);
361  }
362 
363  // face
364  const size_t textureOffset = ml.textures.size();
365  bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0);
366  for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi)
367  if(!(*fi).IsD() && (!selected || (*fi).IsS()))
368  {
369  FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]];
370  fl.Alloc(fi->VN());
371  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
372  for(int i = 0; i < fl.VN(); ++i)
373  fl.V(i) = &ml.vert[remap.vert[Index(mr,fi->cV(i))]];
374  }
375  fl.ImportData(*fi);
376  if(WTFlag)
377  for(int i = 0; i < fl.VN(); ++i)
378  fl.WT(i).n() += short(textureOffset);
379  if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,*fi)]],*fi,remap);
380 
381  }
382 
383  // hedge
384  for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi)
385  if(!(*hi).IsD() && (!selected || (*hi).IsS())){
386  ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi);
387  ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected);
388  }
389 
390  //tetra
391  for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti)
392  if(!(*ti).IsD() && (!selected || (*ti).IsS()))
393  {
394  TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]];
395 
396  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
397  for(int i = 0; i < 4; ++i)
398  tl.V(i) = &ml.vert[remap.vert[Index(mr,ti->cV(i))]];
399  }
400  tl.ImportData(*ti);
401  if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap);
402 
403  }
404 
405  // phase 3.
406  // take care of other per mesh data: textures, attributes
407 
408  // At the end concatenate the vector with texture names.
409  ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end());
410 
411  // Attributes. Copy only those attributes that are present in both meshes
412  // Two attributes in different meshes are considered the same if they have the same
413  // name and the same type. This may be deceiving because they could in fact have
414  // different semantic, but this is up to the developer.
415  // If the left mesh has attributes that are not in the right mesh, their values for the elements
416  // of the right mesh will be uninitialized
417 
418  unsigned int id_r;
419  typename std::set< PointerToAttribute >::iterator al, ar;
420 
421  // per vertex attributes
422  for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al)
423  if(!(*al)._name.empty()){
424  ar = mr.vert_attr.find(*al);
425  if(ar!= mr.vert_attr.end()){
426  id_r = 0;
427  for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r)
428  if( !(*vi).IsD() && (!selected || (*vi).IsS()))
429  (*al)._handle->CopyValue(remap.vert[Index(mr,*vi)], id_r, (*ar)._handle);
430  }
431  }
432 
433  // per edge attributes
434  for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al)
435  if(!(*al)._name.empty()){
436  ar = mr.edge_attr.find(*al);
437  if(ar!= mr.edge_attr.end()){
438  id_r = 0;
439  for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r)
440  if( !(*ei).IsD() && (!selected || (*ei).IsS()))
441  (*al)._handle->CopyValue(remap.edge[Index(mr,*ei)], id_r, (*ar)._handle);
442  }
443  }
444 
445  // per face attributes
446  for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al)
447  if(!(*al)._name.empty()){
448  ar = mr.face_attr.find(*al);
449  if(ar!= mr.face_attr.end()){
450  id_r = 0;
451  for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r)
452  if( !(*fi).IsD() && (!selected || (*fi).IsS()))
453  (*al)._handle->CopyValue(remap.face[Index(mr,*fi)], id_r, (*ar)._handle);
454  }
455  }
456 
457  // per tetra attributes
458  for(al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al)
459  if(!(*al)._name.empty()){
460  ar = mr.tetra_attr.find(*al);
461  if(ar!= mr.tetra_attr.end()){
462  id_r = 0;
463  for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r)
464  if( !(*ti).IsD() && (!selected || (*ti).IsS()))
465  (*al)._handle->CopyValue(remap.tetra[Index(mr, *ti)], id_r, (*ar)._handle);
466  }
467  }
468  // per mesh attributes
469  // if both ml and mr have an attribute with the same name, no action is done
470  // if mr has an attribute that is NOT present in ml, the attribute is added to ml
471  //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar)
472  // if(!(*ar)._name.empty()){
473  // al = ml.mesh_attr.find(*ar);
474  // if(al== ml.mesh_attr.end())
475  // //...
476  // }
477 }
478 
482 static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false)
483 {
484  ml.Clear();
485  Mesh(ml,mr,selected,adjFlag);
486  ml.bbox.Import(mr.bbox);
487 }
492 static void Selected(MeshLeft& ml, ConstMeshRight& mr)
493 {
494  Mesh(ml,mr,true);
495 }
496 
497 }; // end of class Append
498 
499 
500 
501 
502 
503 } // End Namespace tri
504 } // End Namespace vcg
505 
506 
507 #endif
508 
509