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::VertexPointer VertexPointerLeft;
50  typedef typename MeshLeft::VertexIterator VertexIteratorLeft;
51  typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft;
52  typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft;
53  typedef typename MeshLeft::FaceIterator FaceIteratorLeft;
54 
55 
56  typedef typename ConstMeshRight::ScalarType ScalarRight;
57  typedef typename ConstMeshRight::CoordType CoordRight;
58  typedef typename ConstMeshRight::VertexType VertexRight;
59  typedef typename ConstMeshRight::EdgeType EdgeRight;
60  typedef typename ConstMeshRight::HEdgeType HEdgeRight;
61  typedef typename ConstMeshRight::FaceType FaceRight;
62  typedef typename ConstMeshRight::VertexPointer VertexPointerRight;
63  typedef typename ConstMeshRight::VertexIterator VertexIteratorRight;
64  typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight;
65  typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight;
66  typedef typename ConstMeshRight::FaceIterator FaceIteratorRight;
67  typedef typename ConstMeshRight::FacePointer FacePointerRight;
68 
69  struct Remap{
70  static size_t InvalidIndex() { return std::numeric_limits<size_t>::max(); }
71  std::vector<size_t> vert,face,edge, hedge;
72  };
73 
74  static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){
75  // Vertex to Edge Adj
76  if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){
77  size_t i = Index(mr,vr.cVEp());
78  vl.VEp() = (i>ml.edge.size())? 0 : &ml.edge[remap.edge[i]];
79  vl.VEi() = vr.VEi();
80  }
81 
82  // Vertex to Face Adj
83  if(HasPerVertexVFAdjacency(ml) && HasPerVertexVFAdjacency(mr) && vr.cVFp() != 0 ){
84  size_t i = Index(mr,vr.cVFp());
85  vl.VFp() = (i>ml.face.size())? 0 :&ml.face[remap.face[i]];
86  vl.VFi() = vr.VFi();
87  }
88 
89  // Vertex to HEdge Adj
90  if(HasVHAdjacency(ml) && HasVHAdjacency(mr) && vr.cVHp() != 0){
91  vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]];
92  vl.VHi() = vr.VHi();
93  }
94  }
95 
96  static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap)
97  {
98  // Edge to Edge Adj
99  if(HasEEAdjacency(ml) && HasEEAdjacency(mr))
100  for(unsigned int vi = 0; vi < 2; ++vi)
101  {
102  size_t idx = Index(mr,er.cEEp(vi));
103  el.EEp(vi) = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
104  el.EEi(vi) = er.cEEi(vi);
105  }
106 
107  // Edge to Face Adj
108  if(HasEFAdjacency(ml) && HasEFAdjacency(mr)){
109  size_t idx = Index(mr,er.cEFp());
110  el.EFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
111  el.EFi() = er.cEFi();
112  }
113 
114  // Edge to HEdge Adj
115  if(HasEHAdjacency(ml) && HasEHAdjacency(mr))
116  el.EHp() = &ml.hedge[remap.hedge[Index(mr,er.cEHp())]];
117  }
118 
119 
120  static void ImportFaceAdj(MeshLeft &ml, ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap )
121  {
122  // Face to Edge Adj
123  if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){
124  assert(fl.VN() == fr.VN());
125  for( int vi = 0; vi < fl.VN(); ++vi ){
126  size_t idx = remap.edge[Index(mr,fr.cFEp(vi))];
127  if(idx!=Remap::InvalidIndex())
128  fl.FEp(vi) = &ml.edge[idx];
129  }
130  }
131 
132  // Face to Face Adj
133  if(HasFFAdjacency(ml) && HasFFAdjacency(mr)){
134  assert(fl.VN() == fr.VN());
135  for( int vi = 0; vi < fl.VN(); ++vi ){
136  size_t idx = remap.face[Index(mr,fr.cFFp(vi))];
137  if(idx!=Remap::InvalidIndex()){
138  fl.FFp(vi) = &ml.face[idx];
139  fl.FFi(vi) = fr.cFFi(vi);
140  }
141  }
142  }
143 
144  // Face to HEedge Adj
145  if(HasFHAdjacency(ml) && HasFHAdjacency(mr))
146  fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]];
147  }
148 
149  static void ImportHEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){
150  // HEdge to Vertex Adj
151  if(HasHVAdjacency(ml) && HasHVAdjacency(mr))
152  hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]];
153 
154  // HEdge to Edge Adj
155  if(HasHEAdjacency(ml) && HasHEAdjacency(mr)){
156  size_t idx = Index(mr,hr.cHEp()) ;
157  hl.HEp() = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
158  }
159 
160  // HEdge to Face Adj
161  if(HasHFAdjacency(ml) && HasHFAdjacency(mr)){
162  size_t idx = Index(mr,hr.cHFp());
163  hl.HFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
164  }
165 
166 
167  // HEdge to Opposite HEdge Adj
168  if(HasHOppAdjacency(ml) && HasHOppAdjacency(mr))
169  hl.HOp() = &ml.hedge[remap.hedge[Index(mr,hr.cHOp())]];
170 
171  // HEdge to Next HEdge Adj
172  if(HasHNextAdjacency(ml) && HasHNextAdjacency(mr))
173  hl.HNp() = &ml.hedge[remap.hedge[Index(mr,hr.cHNp())]];
174 
175  // HEdge to Next HEdge Adj
176  if(HasHPrevAdjacency(ml) && HasHPrevAdjacency(mr))
177  hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]];
178  }
179 
180 // Append Right Mesh to the Left Mesh
181 // Append::Mesh(ml, mr) is equivalent to ml += mr.
182 // Note MeshRigth could be costant...
203 static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, const bool adjFlag = false)
204 {
205  // Note that if the the selection of the vertexes is not consistent with the face selection
206  // the append could build faces referencing non existent vertices
207  // so it is mandatory that the selection of the vertices reflects the loose selection
208  // from edges and faces (e.g. if a face is selected all its vertices must be selected).
209  // note the use of the parameter for preserving existing vertex selection.
210  if(selected)
211  {
212  assert(adjFlag == false || ml.IsEmpty()); // It is rather meaningless to partially copy adj relations.
215  }
216 
217  // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr
218  // and build the remapping for all
219 
220  Remap remap;
221 
222  // vertex
223  remap.vert.resize(mr.vert.size(), Remap::InvalidIndex());
224  VertexIteratorLeft vp;
226  if(selected)
227  vp=Allocator<MeshLeft>::AddVertices(ml,int(svn));
228  else
230 
231  for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi)
232  {
233  if(!(*vi).IsD() && (!selected || (*vi).IsS()))
234  {
235  size_t ind=Index(mr,*vi);
236  remap.vert[ind]=int(Index(ml,*vp));
237  ++vp;
238  }
239  }
240  // edge
241  remap.edge.resize(mr.edge.size(), Remap::InvalidIndex());
242  EdgeIteratorLeft ep;
244  if(selected) ep=Allocator<MeshLeft>::AddEdges(ml,sen);
245  else ep=Allocator<MeshLeft>::AddEdges(ml,mr.en);
246 
247  for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei)
248  if(!(*ei).IsD() && (!selected || (*ei).IsS())){
249  size_t ind=Index(mr,*ei);
250  remap.edge[ind]=int(Index(ml,*ep));
251  ++ep;
252  }
253 
254  // face
255  remap.face.resize(mr.face.size(), Remap::InvalidIndex());
256  FaceIteratorLeft fp;
258  if(selected) fp=Allocator<MeshLeft>::AddFaces(ml,sfn);
259  else fp=Allocator<MeshLeft>::AddFaces(ml,mr.fn);
260 
261  for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi)
262  if(!(*fi).IsD() && (!selected || (*fi).IsS())){
263  size_t ind=Index(mr,*fi);
264  remap.face[ind]=int(Index(ml,*fp));
265  ++fp;
266  }
267 
268  // hedge
269  remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex());
270  for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi)
271  if(!(*hi).IsD() && (!selected || (*hi).IsS())){
272  size_t ind=Index(mr,*hi);
273  assert(remap.hedge[ind]==Remap::InvalidIndex());
274  HEdgeIteratorLeft hp = Allocator<MeshLeft>::AddHEdges(ml,1);
275  (*hp).ImportData(*(hi));
276  remap.hedge[ind]=Index(ml,*hp);
277  }
278 
279  // phase 2.
280  // copy data from ml to its corresponding elements in ml and adjacencies
281 
282  // vertex
283  for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi)
284  if( !(*vi).IsD() && (!selected || (*vi).IsS())){
285  ml.vert[remap.vert[Index(mr,*vi)]].ImportData(*vi);
286  if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,*vi)]],*vi,remap);
287  }
288 
289  // edge
290  for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei)
291  if(!(*ei).IsD() && (!selected || (*ei).IsS())){
292  ml.edge[remap.edge[Index(mr,*ei)]].ImportData(*ei);
293  // Edge to Vertex Adj
294  EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]];
295  if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){
296  el.V(0) = &ml.vert[remap.vert[Index(mr,ei->cV(0))]];
297  el.V(1) = &ml.vert[remap.vert[Index(mr,ei->cV(1))]];
298  }
299  if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap);
300  }
301 
302  // face
303  const size_t textureOffset = ml.textures.size();
304  bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0);
305  for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi)
306  if(!(*fi).IsD() && (!selected || (*fi).IsS()))
307  {
308  FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]];
309  fl.Alloc(fi->VN());
310  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
311  for(int i = 0; i < fl.VN(); ++i)
312  fl.V(i) = &ml.vert[remap.vert[Index(mr,fi->cV(i))]];
313  }
314  fl.ImportData(*fi);
315  if(WTFlag)
316  for(int i = 0; i < fl.VN(); ++i)
317  fl.WT(i).n() += short(textureOffset);
318  if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,*fi)]],*fi,remap);
319 
320  }
321 
322  // hedge
323  for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi)
324  if(!(*hi).IsD() && (!selected || (*hi).IsS())){
325  ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi);
326  ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected);
327  }
328 
329  // phase 3.
330  // take care of other per mesh data: textures, attributes
331 
332  // At the end concatenate the vector with texture names.
333  ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end());
334 
335  // Attributes. Copy only those attributes that are present in both meshes
336  // Two attributes in different meshes are considered the same if they have the same
337  // name and the same type. This may be deceiving because they could in fact have
338  // different semantic, but this is up to the developer.
339  // If the left mesh has attributes that are not in the right mesh, their values for the elements
340  // of the right mesh will be uninitialized
341 
342  unsigned int id_r;
343  typename std::set< PointerToAttribute >::iterator al, ar;
344 
345  // per vertex attributes
346  for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al)
347  if(!(*al)._name.empty()){
348  ar = mr.vert_attr.find(*al);
349  if(ar!= mr.vert_attr.end()){
350  id_r = 0;
351  for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r)
352  if( !(*vi).IsD() && (!selected || (*vi).IsS()))
353  memcpy((*al)._handle->At(remap.vert[Index(mr,*vi)]),(*ar)._handle->At(id_r),
354  (*al)._handle->SizeOf());
355  }
356  }
357 
358  // per edge attributes
359  for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al)
360  if(!(*al)._name.empty()){
361  ar = mr.edge_attr.find(*al);
362  if(ar!= mr.edge_attr.end()){
363  id_r = 0;
364  for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r)
365  if( !(*ei).IsD() && (!selected || (*ei).IsS()))
366  memcpy((*al)._handle->At(remap.edge[Index(mr,*ei)]),(*ar)._handle->At(id_r),
367  (*al)._handle->SizeOf());
368  }
369  }
370 
371  // per face attributes
372  for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al)
373  if(!(*al)._name.empty()){
374  ar = mr.face_attr.find(*al);
375  if(ar!= mr.face_attr.end()){
376  id_r = 0;
377  for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r)
378  if( !(*fi).IsD() && (!selected || (*fi).IsS()))
379  memcpy((*al)._handle->At(remap.face[Index(mr,*fi)]),(*ar)._handle->At(id_r),
380  (*al)._handle->SizeOf());
381  }
382  }
383 
384  // per mesh attributes
385  // if both ml and mr have an attribute with the same name, no action is done
386  // if mr has an attribute that is NOT present in ml, the attribute is added to ml
387  //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar)
388  // if(!(*ar)._name.empty()){
389  // al = ml.mesh_attr.find(*ar);
390  // if(al== ml.mesh_attr.end())
391  // //...
392  // }
393 }
394 
398 static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false)
399 {
400  ml.Clear();
401  Mesh(ml,mr,selected,adjFlag);
402  ml.bbox.Import(mr.bbox);
403 }
408 static void Selected(MeshLeft& ml, ConstMeshRight& mr)
409 {
410  Mesh(ml,mr,true);
411 }
412 
413 }; // end of class Append
414 
415 
416 
417 
418 
419 } // End Namespace tri
420 } // End Namespace vcg
421 
422 
423 #endif
424 
425