$darkmode
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 #include <vcg/complex/allocate.h>
27 #include <vcg/complex/algorithms/update/selection.h>
28 
29 namespace vcg {
30 namespace tri {
38 template<class MeshLeft, class ConstMeshRight>
39 class Append
40 {
41 public:
42  typedef typename MeshLeft::ScalarType ScalarLeft;
43  typedef typename MeshLeft::CoordType CoordLeft;
44  typedef typename MeshLeft::VertexType VertexLeft;
45  typedef typename MeshLeft::EdgeType EdgeLeft;
46  typedef typename MeshLeft::FaceType FaceLeft;
47  typedef typename MeshLeft::HEdgeType HEdgeLeft;
48  typedef typename MeshLeft::TetraType TetraLeft;
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  typedef typename MeshLeft::TetraIterator TetraIteratorLeft;
55 
56 
57  typedef typename ConstMeshRight::ScalarType ScalarRight;
58  typedef typename ConstMeshRight::CoordType CoordRight;
59  typedef typename ConstMeshRight::VertexType VertexRight;
60  typedef typename ConstMeshRight::EdgeType EdgeRight;
61  typedef typename ConstMeshRight::HEdgeType HEdgeRight;
62  typedef typename ConstMeshRight::FaceType FaceRight;
63  typedef typename ConstMeshRight::TetraType TetraRight;
64  typedef typename ConstMeshRight::TetraPointer TetraPointerRight;
65  typedef typename ConstMeshRight::TetraIterator TetraIteratorRight;
66  typedef typename ConstMeshRight::VertexPointer VertexPointerRight;
67  typedef typename ConstMeshRight::VertexIterator VertexIteratorRight;
68  typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight;
69  typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight;
70  typedef typename ConstMeshRight::FaceIterator FaceIteratorRight;
71  typedef typename ConstMeshRight::FacePointer FacePointerRight;
72 
73  struct Remap{
74  static size_t InvalidIndex() { return std::numeric_limits<size_t>::max(); }
75  std::vector<size_t> vert, face, edge, hedge, tetra;
76  };
77 
78  static void ImportVertexAdj(MeshLeft &ml, const ConstMeshRight &mr, VertexLeft &vl, const VertexRight &vr, Remap &remap ){
79  // Vertex to Edge Adj
80  if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){
81  size_t i = Index(mr,vr.cVEp());
82  vl.VEp() = (i>ml.edge.size())? 0 : &ml.edge[remap.edge[i]];
83  vl.VEi() = vr.VEi();
84  }
85 
86  // Vertex to Face Adj
87  if(HasPerVertexVFAdjacency(ml) && HasPerVertexVFAdjacency(mr) && vr.cVFp() != 0 ){
88  size_t i = Index(mr,vr.cVFp());
89  vl.VFp() = (i>ml.face.size())? 0 :&ml.face[remap.face[i]];
90  vl.VFi() = vr.VFi();
91  }
92 
93  // Vertex to HEdge Adj
94  if(HasVHAdjacency(ml) && HasVHAdjacency(mr) && vr.cVHp() != 0){
95  vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]];
96  vl.VHi() = vr.VHi();
97  }
98 
99  // Vertex to Tetra Adj
100  if(HasVTAdjacency(ml) && HasVTAdjacency(mr) && vr.cVTp() != 0){
101  size_t i = Index(mr, vr.cVTp());
102  vl.VTp() = (i > ml.edge.size()) ? 0 : &ml.tetra[remap.tetra[i]];
103  vl.VTi() = vr.VTi();
104  }
105  }
106 
107  static void ImportEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap)
108  {
109  // Edge to Edge Adj
110  if(HasEEAdjacency(ml) && HasEEAdjacency(mr))
111  for(unsigned int vi = 0; vi < 2; ++vi)
112  {
113  size_t idx = Index(mr,er.cEEp(vi));
114  el.EEp(vi) = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
115  el.EEi(vi) = er.cEEi(vi);
116  }
117 
118  // Edge to Face Adj
119  if(HasEFAdjacency(ml) && HasEFAdjacency(mr)){
120  size_t idx = Index(mr,er.cEFp());
121  el.EFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
122  el.EFi() = er.cEFi();
123  }
124 
125  // Edge to HEdge Adj
126  if(HasEHAdjacency(ml) && HasEHAdjacency(mr))
127  el.EHp() = &ml.hedge[remap.hedge[Index(mr,er.cEHp())]];
128  }
129 
130 
131  static void ImportFaceAdj(MeshLeft &ml, const ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap )
132  {
133  // Face to Edge Adj
134  if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){
135  assert(fl.VN() == fr.VN());
136  for( int vi = 0; vi < fl.VN(); ++vi ){
137  size_t idx = remap.edge[Index(mr,fr.cFEp(vi))];
138  if(idx!=Remap::InvalidIndex())
139  fl.FEp(vi) = &ml.edge[idx];
140  }
141  }
142 
143  // Face to Face Adj
144  if(HasFFAdjacency(ml) && HasFFAdjacency(mr)){
145  assert(fl.VN() == fr.VN());
146  for( int vi = 0; vi < fl.VN(); ++vi ){
147  size_t idx = remap.face[Index(mr,fr.cFFp(vi))];
148  if(idx!=Remap::InvalidIndex()){
149  assert(idx >= 0 && idx < ml.face.size());
150  fl.FFp(vi) = &ml.face[idx];
151  fl.FFi(vi) = fr.cFFi(vi);
152  }
153  }
154  }
155 
156  // Vertex to Face Adj
157  if(HasPerFaceVFAdjacency(ml) && HasPerFaceVFAdjacency(mr))
158  {
159  assert(fl.VN() == fr.VN());
160  for (int vi = 0; vi < fl.VN(); ++vi)
161  {
162  const auto * fp = fr.cVFp(vi);
163  const auto vfindex = fr.cVFi(vi);
164  size_t fidx = (fp == nullptr) ? Remap::InvalidIndex() : remap.face[Index(mr,fp)];
165 
166  if (fidx == Remap::InvalidIndex()) // end of VF chain (or not initialized)
167  {
168  fl.VFClear(vi);
169  assert(fl.cVFi(vi) == -1);
170  }
171  else
172  {
173  assert(fidx >= 0 && fidx < ml.face.size());
174  fl.VFp(vi) = &ml.face[fidx];
175  fl.VFi(vi) = vfindex;
176  }
177  }
178  }
179 
180  // Face to HEedge Adj
181  if(HasFHAdjacency(ml) && HasFHAdjacency(mr))
182  fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]];
183  }
184 
185  static void ImportHEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){
186  // HEdge to Vertex Adj
187  if(HasHVAdjacency(ml) && HasHVAdjacency(mr))
188  hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]];
189 
190  // HEdge to Edge Adj
191  if(HasHEAdjacency(ml) && HasHEAdjacency(mr)){
192  size_t idx = Index(mr,hr.cHEp()) ;
193  hl.HEp() = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]];
194  }
195 
196  // HEdge to Face Adj
197  if(HasHFAdjacency(ml) && HasHFAdjacency(mr)){
198  size_t idx = Index(mr,hr.cHFp());
199  hl.HFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]];
200  }
201 
202 
203  // HEdge to Opposite HEdge Adj
204  if(HasHOppAdjacency(ml) && HasHOppAdjacency(mr))
205  hl.HOp() = &ml.hedge[remap.hedge[Index(mr,hr.cHOp())]];
206 
207  // HEdge to Next HEdge Adj
208  if(HasHNextAdjacency(ml) && HasHNextAdjacency(mr))
209  hl.HNp() = &ml.hedge[remap.hedge[Index(mr,hr.cHNp())]];
210 
211  // HEdge to Next HEdge Adj
212  if(HasHPrevAdjacency(ml) && HasHPrevAdjacency(mr))
213  hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]];
214  }
215 
216  static void ImportTetraAdj(MeshLeft &ml, const ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap )
217  {
218  // Tetra to Tetra Adj
219  if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){
220  for( int vi = 0; vi < 4; ++vi ){
221  size_t idx = remap.tetra[Index(mr,tr.cTTp(vi))];
222  if(idx != Remap::InvalidIndex()){
223  tl.TTp(vi) = &ml.tetra[idx];
224  tl.TTi(vi) = tr.cTTi(vi);
225  }
226  }
227  }
228 }
229 
230 // Append Right Mesh to the Left Mesh
231 // Append::Mesh(ml, mr) is equivalent to ml += mr.
232 // Note MeshRigth could be costant...
253 static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, const bool adjFlag = false)
254 {
255  // Note that if the the selection of the vertexes is not consistent with the face selection
256  // the append could build faces referencing non existent vertices
257  // so it is mandatory that the selection of the vertices reflects the loose selection
258  // from edges and faces (e.g. if a face is selected all its vertices must be selected).
259  // note the use of the parameter for preserving existing vertex selection.
260  if(selected)
261  {
262  assert(adjFlag == false || ml.IsEmpty()); // It is rather meaningless to partially copy adj relations.
265  }
266 
267  MeshAppendConst(ml, mr, selected, adjFlag);
268 }
269 
288 static void MeshAppendConst(
289  MeshLeft& ml,
290  const ConstMeshRight& mr,
291  const bool selected = false,
292  const bool adjFlag = false)
293 {
294  // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr
295  // and build the remapping for all
296 
297  Remap remap;
298 
299  // vertex
300  remap.vert.resize(mr.vert.size(), Remap::InvalidIndex());
301  VertexIteratorLeft vp;
302  if(selected){
304  vp=Allocator<MeshLeft>::AddVertices(ml,int(svn));
305  }
306  else
308 
309  ForEachVertex(mr, [&](const VertexRight& v)
310  {
311  if(!selected || v.IsS())
312  {
313  size_t ind=Index(mr,v);
314  remap.vert[ind]=int(Index(ml,*vp));
315  ++vp;
316  }
317  });
318  // edge
319  remap.edge.resize(mr.edge.size(), Remap::InvalidIndex());
320  EdgeIteratorLeft ep;
321  if(selected) {
324  }
325  else ep=Allocator<MeshLeft>::AddEdges(ml,mr.en);
326 
327  ForEachEdge(mr, [&](const EdgeRight& e)
328  {
329  if(!selected || e.IsS()){
330  size_t ind=Index(mr,e);
331  remap.edge[ind]=int(Index(ml,*ep));
332  ++ep;
333  }
334  });
335 
336  // face
337  remap.face.resize(mr.face.size(), Remap::InvalidIndex());
338  FaceIteratorLeft fp;
339  if(selected) {
342  }
343  else fp=Allocator<MeshLeft>::AddFaces(ml,mr.fn);
344 
345  ForEachFace(mr, [&](const FaceRight& f)
346  {
347  if(!selected || f.IsS()){
348  size_t ind=Index(mr,f);
349  remap.face[ind]=int(Index(ml,*fp));
350  ++fp;
351  }
352  });
353 
354  // hedge
355  remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex());
356 
357  ForEachHEdge(mr, [&](const HEdgeRight& he)
358  {
359  if(!selected || he.IsS()){
360  size_t ind=Index(mr,he);
361  assert(remap.hedge[ind]==Remap::InvalidIndex());
362  HEdgeIteratorLeft hp = Allocator<MeshLeft>::AddHEdges(ml,1);
363  (*hp).ImportData(he);
364  remap.hedge[ind]=Index(ml,*hp);
365  }
366  });
367 
368  remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex());
369 
370  ForEachTetra(mr, [&](const TetraRight& t)
371  {
372  if (!selected || t.IsS()) {
373  size_t idx = Index(mr, t);
374  assert (remap.tetra[idx] == Remap::InvalidIndex());
375  TetraIteratorLeft tp = Allocator<MeshLeft>::AddTetras(ml, 1);
376  (*tp).ImportData(t);
377  remap.tetra[idx] = Index(ml, *tp);
378  }
379  });
380 
381  // phase 1.5
382  // manage textures, creating a new one only when necessary
383  // (not making unuseful duplicates on append) and save a mapping
384 
385  // for each texture in the right mesh, it maps it to the texture index in the
386  // left mesh
387  std::vector<unsigned int> mappingTextures(mr.textures.size());
388 
389  unsigned int baseMlT = ml.textures.size();
390  for (unsigned int i = 0; i < mr.textures.size(); ++i) {
391  auto it = std::find(ml.textures.begin(), ml.textures.end(), mr.textures[i]);
392  //if the right texture does not exists in the left mesh
393  if (it == ml.textures.end()) {
394  //add the texture in the left mesh and create the mapping
395  mappingTextures[i] = baseMlT++;
396  ml.textures.push_back(mr.textures[i]);
397  }
398  else {
399  //the ith right texture will map in the texture found in the left mesh
400  mappingTextures[i] = it - ml.textures.begin();
401  }
402  }
403  //ml.textures.insert(ml.textures.end(), mr.textures.begin(),mr.textures.end());
404 
405  // phase 2.
406  // copy data from mr to its corresponding elements in ml and adjacencies
407 
408  //vtexcoords - can copy only if they are enabled both on l and r
409  bool vertTexFlag = HasPerVertexTexCoord(ml) && HasPerVertexTexCoord(mr);
410 
411  // vertex
412  ForEachVertex(mr, [&](const VertexRight& v)
413  {
414  if(!selected || v.IsS()){
415  VertexLeft &vl = ml.vert[remap.vert[Index(mr,v)]];
416  vl.ImportData(v);
417  if(adjFlag)
418  ImportVertexAdj(ml,mr,vl,v,remap);
419  if (vertTexFlag){
420  if (size_t(v.T().n()) < mappingTextures.size()) {
421  //standard case: the texture is contained in the mesh
422  vl.T().n() = mappingTextures[v.T().n()];
423  }
424  else {
425  //the mesh has tex coords, but not the texture...
426  vl.T().n() = v.T().n();
427  }
428  }
429  }
430  });
431 
432  // edge
433  ForEachEdge(mr, [&](const EdgeRight& e)
434  {
435  if(!selected || e.IsS()){
436  ml.edge[remap.edge[Index(mr,e)]].ImportData(e);
437  // Edge to Vertex Adj
438  EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]];
439  if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){
440  el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]];
441  el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]];
442  }
443  if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap);
444  }
445  });
446 
447  //ftexcoords - can copy only if they are enabled both on l and r
448  bool wedgeTexFlag = HasPerWedgeTexCoord(ml) && HasPerWedgeTexCoord(mr);
449 
450  // face
451  ForEachFace(mr, [&](const FaceRight& f)
452  {
453  if(!selected || f.IsS())
454  {
455  FaceLeft &fl = ml.face[remap.face[Index(mr,f)]];
456  fl.Alloc(f.VN());
457  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
458  for(int i = 0; i < fl.VN(); ++i)
459  fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]];
460  }
461  fl.ImportData(f);
462  if(wedgeTexFlag) {
463  for(int i = 0; i < 3; ++i){
464  if (size_t(f.WT(i).n()) < mappingTextures.size()){
465  //standard case: the texture is contained in the mesh
466  fl.WT(i).n() = mappingTextures[f.WT(i).n()];
467  }
468  else {
469  //the mesh has tex coords, but not the texture...
470  fl.WT(i).n() = f.WT(i).n();
471  }
472  }
473  }
474  if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap);
475 
476  }
477  });
478 
479  // hedge
480  ForEachHEdge(mr, [&](const HEdgeRight& he)
481  {
482  if(!selected || he.IsS()){
483  ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he);
484  ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected);
485  }
486  });
487 
488  //tetra
489  ForEachTetra(mr, [&](const TetraRight& t)
490  {
491  if(!selected || t.IsS())
492  {
493  TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]];
494 
495  if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){
496  for(int i = 0; i < 4; ++i)
497  tl.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]];
498  }
499  tl.ImportData(t);
500  if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap);
501 
502  }
503  });
504 
505  // phase 3.
506  // take care of other per mesh data: attributes
507 
508  // Attributes. Copy only those attributes that are present in both meshes
509  // Two attributes in different meshes are considered the same if they have the same
510  // name and the same type. This may be deceiving because they could in fact have
511  // different semantic, but this is up to the developer.
512  // If the left mesh has attributes that are not in the right mesh, their values for the elements
513  // of the right mesh will be uninitialized
514 
515  unsigned int id_r;
516  typename std::set< PointerToAttribute >::iterator al, ar;
517 
518  // per vertex attributes
519  for (al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al)
520  if(!(*al)._name.empty())
521  {
522  ar = mr.vert_attr.find(*al);
523  if (ar != mr.vert_attr.end())
524  {
525  id_r = 0;
526  for (const auto & v : mr.vert)
527  {
528  if( !v.IsD() && (!selected || v.IsS()))
529  (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle);
530  ++id_r;
531  }
532  }
533  }
534 
535  // per edge attributes
536  for (al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al)
537  if (!(*al)._name.empty())
538  {
539  ar = mr.edge_attr.find(*al);
540  if (ar!= mr.edge_attr.end())
541  {
542  id_r = 0;
543  for (const auto & e : mr.edge)
544  {
545  if( !e.IsD() && (!selected || e.IsS()))
546  (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle);
547  ++id_r;
548  }
549  }
550  }
551 
552  // per face attributes
553  for (al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al)
554  if (!(*al)._name.empty())
555  {
556  ar = mr.face_attr.find(*al);
557  if (ar!= mr.face_attr.end())
558  {
559  id_r = 0;
560  for (const auto & f : mr.face)
561  {
562  if( !f.IsD() && (!selected || f.IsS()))
563  (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle);
564  ++id_r;
565  }
566  }
567  }
568 
569  // per tetra attributes
570  for (al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al)
571  if (!(*al)._name.empty())
572  {
573  ar = mr.tetra_attr.find(*al);
574  if (ar!= mr.tetra_attr.end())
575  {
576  id_r = 0;
577  for (const auto & t: mr.tetra)
578  {
579  if( !t.IsD() && (!selected || t.IsS()))
580  (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle);
581  ++id_r;
582  }
583  }
584  }
585 
586  // per mesh attributes
587  // if both ml and mr have an attribute with the same name, no action is done
588  // if mr has an attribute that is NOT present in ml, the attribute is added to ml
589  //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar)
590  // if(!(*ar)._name.empty()){
591  // al = ml.mesh_attr.find(*ar);
592  // if(al== ml.mesh_attr.end())
593  // //...
594  // }
595 }
596 
601 static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false)
602 {
603  ml.Clear();
604  Mesh(ml,mr,selected,adjFlag);
605  ml.bbox.Import(mr.bbox);
606 }
607 
608 static void MeshCopyConst(MeshLeft& ml, const ConstMeshRight& mr, bool selected=false, const bool adjFlag = false)
609 {
610  ml.Clear();
611  MeshAppendConst(ml,mr,selected,adjFlag);
612  ml.bbox.Import(mr.bbox);
613 }
619 static void Selected(MeshLeft& ml, ConstMeshRight& mr)
620 {
621  Mesh(ml,mr,true);
622 }
623 
624 }; // end of class Append
625 
626 
627 
628 
629 
630 } // End Namespace tri
631 } // End Namespace vcg
632 
633 
634 #endif
635 
636 
static EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater< EdgePointer > &pu)
Add n edges to the mesh. Function to add n edges to the mesh. The elements are added always to the en...
Definition: allocate.h:333
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:189
static FaceIterator AddFaces(MeshType &m, size_t n)
Function to add n faces to the mesh. First wrapper, with no parameters.
Definition: allocate.h:615
Class to safely duplicate and append (portion of) meshes.
Definition: append.h:40
static void MeshAppendConst(MeshLeft &ml, const ConstMeshRight &mr, const bool selected=false, const bool adjFlag=false)
MeshAppendConst.
Definition: append.h:288
static void MeshCopy(MeshLeft &ml, ConstMeshRight &mr, bool selected=false, const bool adjFlag=false)
Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected ...
Definition: append.h:601
static void Mesh(MeshLeft &ml, ConstMeshRight &mr, const bool selected=false, const bool adjFlag=false)
Append the second mesh to the first one.
Definition: append.h:253
static void Selected(MeshLeft &ml, ConstMeshRight &mr)
Append only the selected elements of second mesh to the first one.
Definition: append.h:619
static size_t VertexCount(const MeshType &m)
This function returns the number of selected vertices.
Definition: selection.h:300
static size_t EdgeCount(const MeshType &m)
This function returns the number of selected edges.
Definition: selection.h:290
static size_t FaceCount(const MeshType &m)
This function returns the number of selected faces.
Definition: selection.h:280
static size_t VertexFromEdgeLoose(MeshType &m, bool preserveSelection=false)
Select all the vertices that are touched by at least a single selected edge.
Definition: selection.h:399
static size_t VertexFromFaceLoose(MeshType &m, bool preserveSelection=false)
Select all the vertices that are touched by at least a single selected faces.
Definition: selection.h:386
void ForEachTetra(const MeshType &m, Callable action)
Definition: foreach.h:270
void ForEachEdge(const MeshType &m, Callable action)
Definition: foreach.h:222
void ForEachFace(const MeshType &m, Callable action)
Definition: foreach.h:78
void ForEachVertex(const MeshType &m, Callable action)
Definition: foreach.h:126
void ForEachHEdge(const MeshType &m, Callable action)
Definition: foreach.h:174
Definition: namespaces.dox:6
Definition: append.h:73