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  fl.FFp(vi) = &ml.face[idx];
151  fl.FFi(vi) = fr.cFFi(vi);
152  }
153  }
154  }
155 
156  // Face to HEedge Adj
157  if(HasFHAdjacency(ml) && HasFHAdjacency(mr))
158  fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]];
159  }
160 
161  static void ImportHEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){
162  // HEdge to Vertex Adj
163  if(HasHVAdjacency(ml) && HasHVAdjacency(mr))
164  hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]];
165 
166  // HEdge to Edge Adj
167  if(HasHEAdjacency(ml) && HasHEAdjacency(mr)){
168  size_t idx = Index(mr,hr.cHEp()) ;
169  hl.HEp() = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
170  }
171 
172  // HEdge to Face Adj
173  if(HasHFAdjacency(ml) && HasHFAdjacency(mr)){
174  size_t idx = Index(mr,hr.cHFp());
175  hl.HFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
176  }
177 
178 
179  // HEdge to Opposite HEdge Adj
180  if(HasHOppAdjacency(ml) && HasHOppAdjacency(mr))
181  hl.HOp() = &ml.hedge[remap.hedge[Index(mr,hr.cHOp())]];
182 
183  // HEdge to Next HEdge Adj
184  if(HasHNextAdjacency(ml) && HasHNextAdjacency(mr))
185  hl.HNp() = &ml.hedge[remap.hedge[Index(mr,hr.cHNp())]];
186 
187  // HEdge to Next HEdge Adj
188  if(HasHPrevAdjacency(ml) && HasHPrevAdjacency(mr))
189  hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]];
190  }
191 
192  static void ImportTetraAdj(MeshLeft &ml, ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap )
193  {
194  // Tetra to Tetra Adj
195  if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){
196  for( int vi = 0; vi < 4; ++vi ){
197  size_t idx = remap.tetra[Index(mr,tr.cTTp(vi))];
198  if(idx != Remap::InvalidIndex()){
199  tl.TTp(vi) = &ml.tetra[idx];
200  tl.TTi(vi) = tr.cTTi(vi);
201  }
202  }
203  }
204 }
205 
206 // Append Right Mesh to the Left Mesh
207 // Append::Mesh(ml, mr) is equivalent to ml += mr.
208 // Note MeshRigth could be costant...
229 static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, const bool adjFlag = false)
230 {
231  // Note that if the the selection of the vertexes is not consistent with the face selection
232  // the append could build faces referencing non existent vertices
233  // so it is mandatory that the selection of the vertices reflects the loose selection
234  // from edges and faces (e.g. if a face is selected all its vertices must be selected).
235  // note the use of the parameter for preserving existing vertex selection.
236  if(selected)
237  {
238  assert(adjFlag == false || ml.IsEmpty()); // It is rather meaningless to partially copy adj relations.
241  }
242 
243  // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr
244  // and build the remapping for all
245 
246  Remap remap;
247 
248  // vertex
249  remap.vert.resize(mr.vert.size(), Remap::InvalidIndex());
250  VertexIteratorLeft vp;
252  if(selected)
253  vp=Allocator<MeshLeft>::AddVertices(ml,int(svn));
254  else
256 
257  for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi)
258  {
259  if(!(*vi).IsD() && (!selected || (*vi).IsS()))
260  {
261  size_t ind=Index(mr,*vi);
262  remap.vert[ind]=int(Index(ml,*vp));
263  ++vp;
264  }
265  }
266  // edge
267  remap.edge.resize(mr.edge.size(), Remap::InvalidIndex());
268  EdgeIteratorLeft ep;
270  if(selected) ep=Allocator<MeshLeft>::AddEdges(ml,sen);
271  else ep=Allocator<MeshLeft>::AddEdges(ml,mr.en);
272 
273  for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei)
274  if(!(*ei).IsD() && (!selected || (*ei).IsS())){
275  size_t ind=Index(mr,*ei);
276  remap.edge[ind]=int(Index(ml,*ep));
277  ++ep;
278  }
279 
280  // face
281  remap.face.resize(mr.face.size(), Remap::InvalidIndex());
282  FaceIteratorLeft fp;
284  if(selected) fp=Allocator<MeshLeft>::AddFaces(ml,sfn);
285  else fp=Allocator<MeshLeft>::AddFaces(ml,mr.fn);
286 
287  for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi)
288  if(!(*fi).IsD() && (!selected || (*fi).IsS())){
289  size_t ind=Index(mr,*fi);
290  remap.face[ind]=int(Index(ml,*fp));
291  ++fp;
292  }
293 
294  // hedge
295  remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex());
296  for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi)
297  if(!(*hi).IsD() && (!selected || (*hi).IsS())){
298  size_t ind=Index(mr,*hi);
299  assert(remap.hedge[ind]==Remap::InvalidIndex());
300  HEdgeIteratorLeft hp = Allocator<MeshLeft>::AddHEdges(ml,1);
301  (*hp).ImportData(*(hi));
302  remap.hedge[ind]=Index(ml,*hp);
303  }
304 
305  remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex());
306  for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti)
307  if (!(*ti).IsD() && (!selected || (*ti).IsS())) {
308  size_t idx = Index(mr, *ti);
309  assert (remap.tetra[idx] == Remap::InvalidIndex());
310  TetraIteratorLeft tp = Allocator<MeshLeft>::AddTetras(ml, 1);
311  (*tp).ImportData(*ti);
312  remap.tetra[idx] = Index(ml, *tp);
313  }
314 
315  // phase 2.
316  // copy data from ml to its corresponding elements in ml and adjacencies
317 
318  // vertex
319  for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi)
320  if( !(*vi).IsD() && (!selected || (*vi).IsS())){
321  ml.vert[remap.vert[Index(mr,*vi)]].ImportData(*vi);
322  if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,*vi)]],*vi,remap);
323  }
324 
325  // edge
326  for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei)
327  if(!(*ei).IsD() && (!selected || (*ei).IsS())){
328  ml.edge[remap.edge[Index(mr,*ei)]].ImportData(*ei);
329  // Edge to Vertex Adj
330  EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]];
331  if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){
332  el.V(0) = &ml.vert[remap.vert[Index(mr,ei->cV(0))]];
333  el.V(1) = &ml.vert[remap.vert[Index(mr,ei->cV(1))]];
334  }
335  if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap);
336  }
337 
338  // face
339  const size_t textureOffset = ml.textures.size();
340  bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0);
341  for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi)
342  if(!(*fi).IsD() && (!selected || (*fi).IsS()))
343  {
344  FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]];
345  fl.Alloc(fi->VN());
346  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
347  for(int i = 0; i < fl.VN(); ++i)
348  fl.V(i) = &ml.vert[remap.vert[Index(mr,fi->cV(i))]];
349  }
350  fl.ImportData(*fi);
351  if(WTFlag)
352  for(int i = 0; i < fl.VN(); ++i)
353  fl.WT(i).n() += short(textureOffset);
354  if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,*fi)]],*fi,remap);
355 
356  }
357 
358  // hedge
359  for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi)
360  if(!(*hi).IsD() && (!selected || (*hi).IsS())){
361  ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi);
362  ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected);
363  }
364 
365  //tetra
366  for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti)
367  if(!(*ti).IsD() && (!selected || (*ti).IsS()))
368  {
369  TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]];
370 
371  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
372  for(int i = 0; i < 4; ++i)
373  tl.V(i) = &ml.vert[remap.vert[Index(mr,ti->cV(i))]];
374  }
375  tl.ImportData(*ti);
376  if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap);
377 
378  }
379 
380  // phase 3.
381  // take care of other per mesh data: textures, attributes
382 
383  // At the end concatenate the vector with texture names.
384  ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end());
385 
386  // Attributes. Copy only those attributes that are present in both meshes
387  // Two attributes in different meshes are considered the same if they have the same
388  // name and the same type. This may be deceiving because they could in fact have
389  // different semantic, but this is up to the developer.
390  // If the left mesh has attributes that are not in the right mesh, their values for the elements
391  // of the right mesh will be uninitialized
392 
393  unsigned int id_r;
394  typename std::set< PointerToAttribute >::iterator al, ar;
395 
396  // per vertex attributes
397  for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al)
398  if(!(*al)._name.empty()){
399  ar = mr.vert_attr.find(*al);
400  if(ar!= mr.vert_attr.end()){
401  id_r = 0;
402  for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r)
403  if( !(*vi).IsD() && (!selected || (*vi).IsS()))
404  memcpy((*al)._handle->At(remap.vert[Index(mr,*vi)]),(*ar)._handle->At(id_r),
405  (*al)._handle->SizeOf());
406  }
407  }
408 
409  // per edge attributes
410  for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al)
411  if(!(*al)._name.empty()){
412  ar = mr.edge_attr.find(*al);
413  if(ar!= mr.edge_attr.end()){
414  id_r = 0;
415  for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r)
416  if( !(*ei).IsD() && (!selected || (*ei).IsS()))
417  memcpy((*al)._handle->At(remap.edge[Index(mr,*ei)]),(*ar)._handle->At(id_r),
418  (*al)._handle->SizeOf());
419  }
420  }
421 
422  // per face attributes
423  for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al)
424  if(!(*al)._name.empty()){
425  ar = mr.face_attr.find(*al);
426  if(ar!= mr.face_attr.end()){
427  id_r = 0;
428  for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r)
429  if( !(*fi).IsD() && (!selected || (*fi).IsS()))
430  memcpy((*al)._handle->At(remap.face[Index(mr,*fi)]),(*ar)._handle->At(id_r),
431  (*al)._handle->SizeOf());
432  }
433  }
434 
435  // per tetra attributes
436  for(al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al)
437  if(!(*al)._name.empty()){
438  ar = mr.tetra_attr.find(*al);
439  if(ar!= mr.tetra_attr.end()){
440  id_r = 0;
441  for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r)
442  if( !(*ti).IsD() && (!selected || (*ti).IsS()))
443  memcpy((*al)._handle->At(remap.tetra[Index(mr, *ti)]),(*ar)._handle->At(id_r),
444  (*al)._handle->SizeOf());
445  }
446  }
447  // per mesh attributes
448  // if both ml and mr have an attribute with the same name, no action is done
449  // if mr has an attribute that is NOT present in ml, the attribute is added to ml
450  //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar)
451  // if(!(*ar)._name.empty()){
452  // al = ml.mesh_attr.find(*ar);
453  // if(al== ml.mesh_attr.end())
454  // //...
455  // }
456 }
457 
461 static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false)
462 {
463  ml.Clear();
464  Mesh(ml,mr,selected,adjFlag);
465  ml.bbox.Import(mr.bbox);
466 }
471 static void Selected(MeshLeft& ml, ConstMeshRight& mr)
472 {
473  Mesh(ml,mr,true);
474 }
475 
476 }; // end of class Append
477 
478 
479 
480 
481 
482 } // End Namespace tri
483 } // End Namespace vcg
484 
485 
486 #endif
487 
488