DGtal  1.4.beta
Mesh.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file Mesh.ih
19  * @author Bertrand Kerautret (\c kerautre@loria.fr )
20  * LORIA (CNRS, UMR 7503), University of Nancy, France
21  *
22  * @date 2012/06/29
23  *
24  * Implementation of inline methods defined in Mesh.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 
30 //////////////////////////////////////////////////////////////////////////////
31 #include <limits>
32 #include <cstdlib>
33 #include <map>
34 #include <DGtal/kernel/BasicPointPredicates.h>
35 //////////////////////////////////////////////////////////////////////////////
36 
37 ///////////////////////////////////////////////////////////////////////////////
38 // IMPLEMENTATION of inline methods.
39 ///////////////////////////////////////////////////////////////////////////////
40 
41 ///////////////////////////////////////////////////////////////////////////////
42 // ----------------------- Standard services ------------------------------
43 
44 
45 /**
46  * Constructor.
47  */
48 template <typename TPoint>
49 inline
50 DGtal::Mesh<TPoint>::Mesh(bool saveFaceColor)
51 {
52  mySaveFaceColor=saveFaceColor;
53  myDefaultColor = DGtal::Color::White;
54 }
55 
56 /**
57  * Constructor.
58  */
59 template <typename TPoint>
60 inline
61 DGtal::Mesh<TPoint>::Mesh(const DGtal::Color &aColor)
62 {
63  mySaveFaceColor=false;
64  myDefaultColor = aColor;
65 }
66 
67 /**
68  * Destructor.
69  */
70 template <typename TPoint>
71 inline
72 DGtal::Mesh<TPoint>::~Mesh()
73 {
74 }
75 
76 
77 template <typename TPoint>
78 inline
79 DGtal::Mesh<TPoint>::Mesh ( const Mesh & other ): myFaceList(other.myFaceList),
80  myVertexList(other.myVertexList),
81  myFaceColorList(other.myFaceColorList),
82  mySaveFaceColor(other.mySaveFaceColor),
83  myDefaultColor(other.myDefaultColor)
84 {
85 
86 }
87 
88 template <typename TPoint>
89 inline
90 DGtal::Mesh<TPoint> &
91 DGtal::Mesh<TPoint>::operator= ( const Mesh & other )
92 {
93  myFaceList = other.myFaceList;
94  myVertexList = other.myVertexList;
95  myFaceColorList = other.myFaceColorList;
96  mySaveFaceColor = other.mySaveFaceColor;
97  myDefaultColor = other. myDefaultColor;
98  return *this;
99 }
100 
101 
102 ///////////////////////////////////////////////////////////////////////////////
103 // Interface - public :
104 
105 /**
106  * Writes/Displays the object on an output stream.
107  * @param out the output stream where the object is written.
108  */
109 template <typename TPoint>
110 inline
111 void
112 DGtal::Mesh<TPoint>::selfDisplay ( std::ostream & out ) const
113 {
114  out << "[Mesh]";
115 }
116 
117 /**
118  * Checks the validity/consistency of the object.
119  * @return 'true' if the object is valid, 'false' otherwise.
120  */
121 template <typename TPoint>
122 inline
123 bool
124 DGtal::Mesh<TPoint>::isValid() const
125 {
126  return true;
127 }
128 
129 
130 
131 
132 ///////////////////////////////////////////////////////////////////////////////
133 // Implementation of inline functions //
134 
135 
136 
137 
138 
139 
140 
141 template<typename TPoint>
142 inline
143 DGtal::Mesh<TPoint>::Mesh(const VertexStorage &vertexSet)
144 {
145  mySaveFaceColor=false;
146  for(int i =0; i< vertexSet.size(); i++)
147  {
148  myVertexList.push_back(vertexSet.at(i));
149  }
150 
151 }
152 
153 
154 
155 template<typename TPoint>
156 inline
157 void
158 DGtal::Mesh<TPoint>::addVertex(const TPoint &point)
159 {
160  myVertexList.push_back(point);
161 }
162 
163 
164 
165 template<typename TPoint>
166 inline
167 void
168 DGtal::Mesh<TPoint>::addTriangularFace(Index indexVertex1, Index indexVertex2,
169  Index indexVertex3, const DGtal::Color &aColor)
170 {
171  MeshFace aFace;
172  aFace.push_back(indexVertex1);
173  aFace.push_back(indexVertex2);
174  aFace.push_back(indexVertex3);
175  myFaceList.push_back(aFace);
176  if(mySaveFaceColor)
177  {
178  myFaceColorList.push_back(aColor);
179  }
180 }
181 
182 
183 
184 
185 template<typename TPoint>
186 inline
187 void
188 DGtal::Mesh<TPoint>::addQuadFace(Index indexVertex1,Index indexVertex2,
189  Index indexVertex3, Index indexVertex4,
190  const DGtal::Color &aColor)
191 {
192  MeshFace aFace;
193  aFace.push_back(indexVertex1);
194  aFace.push_back(indexVertex2);
195  aFace.push_back(indexVertex3);
196  aFace.push_back(indexVertex4);
197  myFaceList.push_back(aFace);
198  if(mySaveFaceColor)
199  {
200  myFaceColorList.push_back(aColor);
201  }
202 }
203 
204 
205 
206 template<typename TPoint>
207 inline
208 void
209 DGtal::Mesh<TPoint>::addFace(const MeshFace &aFace, const DGtal::Color &aColor){
210  myFaceList.push_back(aFace);
211  if(mySaveFaceColor)
212  {
213  myFaceColorList.push_back(aColor);
214  }
215 }
216 
217 
218 
219 template<typename TPoint>
220 inline
221 void
222 DGtal::Mesh<TPoint>::removeFaces(const std::vector<Index> &facesIndex){
223  DGtal::Mesh<TPoint> newMesh(true);
224 
225  std::vector<unsigned int> indexVertexFaceCard(nbVertex());
226  std::vector<bool> indexFaceOK(nbFaces());
227  std::fill(indexVertexFaceCard.begin(), indexVertexFaceCard.end(), 0);
228  std::fill(indexFaceOK.begin(), indexFaceOK.end(), true);
229  for (unsigned int i = 0; i<facesIndex.size(); i++){
230  indexFaceOK[facesIndex[i]]=false;
231  }
232  // for each face remaining in the mesh we add +1 to each vertex used in a face
233  for(unsigned int i = 0; i < nbFaces(); i++){
234  if( indexFaceOK[i] ){
235  DGtal::Mesh<TPoint>::MeshFace aFace = getFace(i);
236  for (unsigned int j=0; j< aFace.size() ; j++) {
237  indexVertexFaceCard[aFace[j]] += 1;
238  }
239  }
240  }
241  // we remove all vertex with a face == 0 and compute the new vertex association:
242  std::vector<unsigned int> newVertexIndex;
243  unsigned int currentIndex=0;
244  for (unsigned int i=0; i< nbVertex(); i++) {
245  if (indexVertexFaceCard[i]!=0){
246  newMesh.addVertex(getVertex(i));
247  newVertexIndex.push_back(currentIndex);
248  currentIndex++;
249  }else{
250  newVertexIndex.push_back(0);
251  }
252  }
253  for (unsigned int i = 0; i < nbFaces(); i++) {
254  if(indexFaceOK[i]){
255  MeshFace aFace = getFace(i);
256  MeshFace aNewFace = aFace;
257  // translate the old face with new index:
258  for (unsigned int j=0; j< aFace.size() ; j++) {
259  aNewFace[j] = newVertexIndex[aFace[j]];
260  }
261  newMesh.addFace(aNewFace);
262  newMesh.setFaceColor(newMesh.nbFaces()-1, getFaceColor(i));
263  }
264  }
265  myFaceList = newMesh.myFaceList;
266  myVertexList = newMesh.myVertexList;
267  myFaceColorList = newMesh.myFaceColorList;
268 }
269 
270 
271 
272 
273 
274 template<typename TPoint>
275 inline
276 const TPoint &
277 DGtal::Mesh<TPoint>::getVertex(Index i) const
278 {
279  return myVertexList.at(i);
280 }
281 
282 
283 
284 template<typename TPoint>
285 inline
286 TPoint &
287 DGtal::Mesh<TPoint>::getVertex(Index i)
288 {
289  return myVertexList.at(i);
290 }
291 
292 
293 
294 template<typename TPoint>
295 inline
296 const typename DGtal::Mesh<TPoint>::MeshFace &
297 DGtal::Mesh<TPoint>::getFace(Index i) const
298 {
299  return myFaceList.at(i);
300 }
301 
302 
303 template<typename TPoint>
304 inline
305 typename DGtal::Mesh<TPoint>::MeshFace &
306 DGtal::Mesh<TPoint>::getFace(Index i)
307 {
308  return myFaceList.at(i);
309 }
310 
311 
312 template<typename TPoint>
313 inline
314 typename DGtal::Mesh<TPoint>::RealPoint
315 DGtal::Mesh<TPoint>::getFaceBarycenter(Index i) const
316 {
317  DGtal::Mesh<TPoint>::RealPoint c;
318  MeshFace aFace = getFace(i);
319  for ( auto &j: aFace){
320  TPoint p = getVertex(j);
321  for (typename TPoint::Dimension k = 0; k < TPoint::dimension; k++){
322  c[k] += static_cast<typename RealPoint::Component>(p[k]) ;
323  }
324  }
325  return c/static_cast<typename RealPoint::Component>(aFace.size());
326 }
327 
328 
329 template<typename TPoint>
330 inline
331 typename DGtal::Mesh<TPoint>::Size
332 DGtal::Mesh<TPoint>::nbFaces() const
333 {
334  return myFaceList.size();
335 }
336 
337 template<typename TPoint>
338 inline
339 typename DGtal::Mesh<TPoint>::Size
340 DGtal::Mesh<TPoint>::nbVertex() const
341 {
342  return myVertexList.size();
343 }
344 
345 
346 template<typename TPoint>
347 inline
348 const DGtal::Color &
349 DGtal::Mesh<TPoint>::getFaceColor(Index i) const
350 {
351  if(mySaveFaceColor)
352  {
353  return myFaceColorList.at(i);
354  }
355  else
356  {
357  return myDefaultColor;
358  }
359 }
360 
361 template <typename TPoint>
362 struct MeshBoundingBoxCompPoints
363 {
364  MeshBoundingBoxCompPoints(typename TPoint::Dimension d): myDim(d){};
365  bool operator() (const TPoint &p1, const TPoint &p2){return p1[myDim]<p2[myDim];};
366  typename TPoint::Dimension myDim;
367 };
368 
369 template<typename TPoint>
370 inline
371 std::pair<TPoint, TPoint>
372 DGtal::Mesh<TPoint>::getBoundingBox() const
373 {
374  std::pair<TPoint, TPoint> theResult;
375  TPoint lowerBound, upperBound;
376  for(unsigned int i=0; i< TPoint::size(); i++)
377  {
378  const MeshBoundingBoxCompPoints<TPoint> cmp_points(i);
379  upperBound[i] = (*(std::max_element(vertexBegin(), vertexEnd(), cmp_points)))[i];
380  lowerBound[i] = (*(std::min_element(vertexBegin(), vertexEnd(), cmp_points)))[i];
381  }
382  theResult.first = lowerBound ;
383  theResult.second = upperBound ;
384  return theResult;
385 }
386 
387 
388 template<typename TPoint>
389 inline
390 void
391 DGtal::Mesh<TPoint>::setFaceColor(const Index index,
392  const DGtal::Color &aColor)
393 {
394  if (!mySaveFaceColor)
395  {
396  for(unsigned int i = 0; i<myFaceList.size(); i++)
397  {
398  myFaceColorList.push_back(myDefaultColor);
399  }
400  mySaveFaceColor=true;
401  }
402  myFaceColorList.at(index) = aColor;
403 }
404 
405 
406 template<typename TPoint>
407 inline
408 bool
409 DGtal::Mesh<TPoint>::isStoringFaceColors() const
410 {
411  return mySaveFaceColor;
412 }
413 
414 
415 
416 
417 template<typename TPoint>
418 inline
419 void
420 DGtal::Mesh<TPoint>::invertVertexFaceOrder(){
421  for(unsigned int i=0; i<myFaceList.size(); i++)
422  {
423  auto aFace = myFaceList.at(i);
424  for(unsigned int j=0; j < aFace.size()/2; j++)
425  {
426  const auto tmp=aFace.at(j);
427  aFace.at(j)=aFace.at(aFace.size()-1-j);
428  aFace.at(aFace.size()-1-j)=tmp;
429  }
430  }
431 }
432 
433 template<typename TPoint>
434 inline
435 void
436 DGtal::Mesh<TPoint>::clearFaces(){
437  myFaceList.clear();
438 }
439 
440 
441 template<typename TPoint>
442 inline
443 void
444 DGtal::Mesh<TPoint>::clearVertices(){
445  myVertexList.clear();
446 }
447 
448 template <typename TPoint>
449 void
450 DGtal::Mesh<TPoint>::removeIsolatedVertices(){
451  typedef typename Mesh<TPoint>::Index MIndex;
452  DGtal::Mesh<TPoint>::VertexStorage vSt;
453  std::vector<bool> vertexUsed (nbVertex(), false);
454  for ( MIndex f = 0; f< nbFaces(); f++ )
455  {
456  auto face = getFace(f);
457  for (MIndex i = 0; i<face.size(); i++)
458  {
459  vertexUsed[face[i]] = true;
460  }
461  }
462  std::vector<MIndex> translateIndexId;
463  MIndex currentIndex = 0;
464  MIndex nbV = nbVertex();
465  for(MIndex i = 0; i < nbV; i++ )
466  {
467  if (vertexUsed[i])
468  {
469  translateIndexId.push_back(currentIndex);
470  vSt.push_back(myVertexList[i]);
471  currentIndex++;
472  }
473  else
474  {
475  translateIndexId.push_back(0);
476  }
477  }
478  myVertexList = vSt;
479  for ( MIndex f = 0; f< nbFaces(); f++ )
480  {
481  auto &face = getFace(f);
482  for (MIndex i = 0; i<face.size(); i++)
483  {
484  face[i]=translateIndexId[face[i]];
485  }
486  }
487 }
488 
489 template<typename TPoint>
490 inline
491 void
492 DGtal::Mesh<TPoint>::rescale(const typename TPoint::Component aScale){
493  for(typename VertexStorage::iterator it = vertexBegin(); it != vertexEnd(); it++)
494  {
495  (*it) *= aScale;
496  }
497 }
498 
499 
500 template<typename TPoint>
501 inline
502 double
503 DGtal::Mesh<TPoint>::subDivideTriangularFaces(const double minArea){
504  double maxArea = 0;
505  std::vector<Mesh<TPoint>::MeshFace> facesToAdd;
506  for(unsigned int i =0; i< nbFaces(); i++)
507  {
508  typename Mesh<TPoint>::MeshFace aFace = getFace(i);
509  if(aFace.size()==3)
510  {
511  TPoint p1 = getVertex(aFace[0]);
512  TPoint p2 = getVertex(aFace[1]);
513  TPoint p3 = getVertex(aFace[2]);
514  TPoint c = (p1+p2+p3)/3.0;
515  double a = ((p2-p1).crossProduct(p3-p1)).norm()/2.0;
516  if (a>maxArea)
517  {
518  maxArea = a;
519  }
520 
521  if(a>=minArea)
522  {
523  addVertex(c);
524  MeshFace f1, f2, f3;
525  f1.push_back(aFace[0]);
526  f1.push_back(aFace[1]);
527  f1.push_back(nbVertex()-1);
528  facesToAdd.push_back(f1);
529 
530  f2.push_back(aFace[1]);
531  f2.push_back(aFace[2]);
532  f2.push_back(nbVertex()-1);
533  facesToAdd.push_back(f2);
534 
535  f3.push_back(aFace[2]);
536  f3.push_back(aFace[0]);
537  f3.push_back(nbVertex()-1);
538  facesToAdd.push_back(f3);
539  }
540  else
541  {
542  facesToAdd.push_back(aFace);
543  }
544 
545  }
546  }
547  clearFaces();
548  for(unsigned i=0; i<facesToAdd.size(); i++)
549  {
550  addFace(facesToAdd[i]);
551  }
552  return maxArea;
553 }
554 
555 
556 
557 template<typename TPoint>
558 inline
559 unsigned int
560 DGtal::Mesh<TPoint>::quadToTriangularFaces(){
561  unsigned int nbQuadT=0;
562  std::vector<Mesh<TPoint>::MeshFace> facesToAdd;
563  for(unsigned int i =0; i< nbFaces(); i++)
564  {
565  typename Mesh<TPoint>::MeshFace aFace = getFace(i);
566  if(aFace.size()==4)
567  {
568  MeshFace f1, f2;
569  f1.push_back(aFace[0]);
570  f1.push_back(aFace[1]);
571  f1.push_back(aFace[2]);
572  facesToAdd.push_back(f1);
573 
574  f2.push_back(aFace[2]);
575  f2.push_back(aFace[3]);
576  f2.push_back(aFace[0]);
577  facesToAdd.push_back(f2);
578  nbQuadT++;
579  }
580  else
581  {
582  facesToAdd.push_back(aFace);
583  }
584  }
585  clearFaces();
586  for(unsigned i=0; i<facesToAdd.size(); i++)
587  {
588  addFace(facesToAdd[i]);
589  }
590  return nbQuadT;
591 }
592 
593 
594 
595 
596 //------------------------------------------------------------------------------
597 template<typename TPoint>
598 inline
599 std::string
600 DGtal::Mesh<TPoint>::className() const
601 {
602  return "Mesh";
603 }
604 
605 
606 
607 
608 
609 
610 template <typename TPoint>
611 inline
612 void
613 DGtal::Mesh<TPoint>::createTubularMesh(DGtal::Mesh<TPoint> &aMesh, const std::vector<TPoint> &aSkeleton,
614  const double aRadius,
615  const double angleStep, const DGtal::Color &aMeshColor)
616 {
617  std::vector<double> aVecR;
618  aVecR.push_back(aRadius);
619  DGtal::Mesh<TPoint>::createTubularMesh(aMesh, aSkeleton,
620  aVecR, angleStep, aMeshColor);
621 
622 }
623 
624 
625 template <typename TPoint>
626 inline
627 void
628 DGtal::Mesh<TPoint>::createTubularMesh(DGtal::Mesh<TPoint> &aMesh, const std::vector<TPoint> &aSkeleton,
629  const std::vector<double> &aVectRadius,
630  const double angleStep, const DGtal::Color &aMeshColor)
631 {
632  auto nbVertexInitial = aMesh.nbVertex();
633  ASSERT(aVectRadius.size() > 0);
634  // Generating vertices..
635  for(auto i = 0; i< (int)aSkeleton.size(); i++)
636  {
637  TPoint vectDir;
638  TPoint uDir1, uDirPrec;
639  TPoint uDir2;
640  TPoint firstPoint;
641 
642  if(i != (int)aSkeleton.size()-1)
643  {
644  vectDir = aSkeleton.at(i+1) - aSkeleton.at(i);
645  }
646  else
647  {
648  vectDir = aSkeleton.at(i) - aSkeleton.at(i-1);
649  }
650 
651  double d = -vectDir[0]* aSkeleton.at(i)[0] - vectDir[1]*aSkeleton.at(i)[1]
652  - vectDir[2]*aSkeleton.at(i)[2];
653  TPoint pRefOrigin;
654  if(vectDir[0]!=0)
655  {
656  pRefOrigin [0]= -d/vectDir[0];
657  pRefOrigin [1]= 0.0;
658  pRefOrigin [2]= 0.0;
659  if(aSkeleton.at(i) == pRefOrigin ||
660  (vectDir[1]==0 && vectDir[2]==0))
661  {
662  pRefOrigin[1]=-1.0;
663  }
664 
665  }
666  else if (vectDir[1]!=0)
667  {
668  pRefOrigin [0]= 0.0;
669  pRefOrigin [1]= -d/vectDir[1];
670  pRefOrigin [2]= 0.0;
671  if(aSkeleton.at(i) == pRefOrigin ||
672  (vectDir[0]==0 && vectDir[2]==0))
673  {
674  pRefOrigin[0]=-1.0;
675  }
676  }else if (vectDir[2]!=0)
677  {
678  pRefOrigin [0]= 0.0;
679  pRefOrigin [1]= 0.0;
680  pRefOrigin [2]= -d/vectDir[2];
681  if(aSkeleton.at(i) == pRefOrigin ||
682  (vectDir[0]==0 && vectDir[1]==0))
683  {
684  pRefOrigin[0]=-1.0;
685  }
686  }
687  uDir1=(pRefOrigin-aSkeleton.at(i))/((pRefOrigin-aSkeleton.at(i)).norm());
688  uDir2[0] = uDir1[1]*vectDir[2]-uDir1[2]*vectDir[1];
689  uDir2[1] = uDir1[2]*vectDir[0]-uDir1[0]*vectDir[2];
690  uDir2[2] = uDir1[0]*vectDir[1]-uDir1[1]*vectDir[0];
691  uDir2/=uDir2.norm();
692  for(double a = 0.0; a < 2.0*M_PI; a += angleStep)
693  {
694  TPoint vMove = aVectRadius.at(i%aVectRadius.size())*(uDir1*cos(a) + uDir2*sin(a));
695  aMesh.addVertex(vMove + aSkeleton[i]);
696  if(a==0)
697  {
698  firstPoint = vMove + aSkeleton[i]+vectDir;
699  }
700 
701  }
702  }
703  unsigned int nbPtPerFaces = static_cast<unsigned int>((aMesh.nbVertex()-nbVertexInitial)/aSkeleton.size());
704 
705  // Generating faces...
706  for(auto i = 0; i< (int)aSkeleton.size()-1; i++)
707  {
708  if (aSkeleton.at(i)==aSkeleton.at(i+1)){
709  trace.warning() << "Two skeleton points are identical, ignoring one point." << std::endl;
710  continue;
711  }
712  // Computing best shift between two consecutive ring points to generate tube face.
713  // (criteria defined by the minimal distance between 4 sampling points)
714  double minDistance = std::numeric_limits<double>::max();
715  TPoint ptRefRing1 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces);
716  TPoint ptRefRing2 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+nbPtPerFaces/4);
717  TPoint ptRefRing3 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+2*(nbPtPerFaces/4));
718  TPoint ptRefRing4 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+3*(nbPtPerFaces/4));
719 
720  unsigned int shift = 0;
721  TPoint vectDir;
722  if(i != (int)aSkeleton.size()-1)
723  {
724  vectDir = aSkeleton.at(i+1) - aSkeleton.at(i);
725  }
726  else
727  {
728  vectDir = aSkeleton.at(i) - aSkeleton.at(i-1);
729  }
730 
731  for(unsigned int k=0; k<nbPtPerFaces; k++)
732  {
733  TPoint pScan1 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+k);
734  TPoint pScan2 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
735  (nbPtPerFaces/4+k)%nbPtPerFaces);
736  TPoint pScan3 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
737  (2*(nbPtPerFaces/4)+k)%nbPtPerFaces);
738  TPoint pScan4 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
739  (3*(nbPtPerFaces/4)+k)%nbPtPerFaces);
740  double distance = (ptRefRing1 - pScan1).norm()+(ptRefRing2 - pScan2).norm()+
741  (ptRefRing3 - pScan3).norm()+(ptRefRing4 - pScan4).norm();
742  if(distance<minDistance){
743  shift = k;
744  minDistance = distance;
745  }
746 
747  }
748  for(unsigned int k=0; k<nbPtPerFaces; k++)
749  {
750  Mesh<TPoint>::MeshFace aFace;
751  aMesh.addQuadFace(nbVertexInitial+k+i*nbPtPerFaces,
752  nbVertexInitial+(shift+k)%nbPtPerFaces+nbPtPerFaces*(i+1),
753  nbVertexInitial+(shift+k+1)%nbPtPerFaces+nbPtPerFaces*(i+1),
754  nbVertexInitial+(k+1)%nbPtPerFaces+i*nbPtPerFaces,
755  aMeshColor);
756  }
757  }
758 }
759 
760 
761 
762 
763 
764 template <typename TPoint>
765 template <typename TValue>
766 inline
767 void
768 DGtal::Mesh<TPoint>::createMeshFromHeightSequence(Mesh<TPoint> &aMesh, const std::vector<TValue> & anValueSequence,
769  const unsigned int lengthSequence,
770  double stepX, double stepY, double stepZ,
771  const DGtal::Color &aMeshColor ){
772  const auto nbVertexInitial = aMesh.nbVertex();
773  // Generating vertices..
774  int i = 0;
775  unsigned int posY = 0;
776  while(i+(int)lengthSequence-1 < (int)anValueSequence.size()){
777  for(unsigned int j = 0; j < lengthSequence; j++, i++){
778  aMesh.addVertex(TPoint(j*stepX, posY*stepY, stepZ*anValueSequence.at(i)));
779  }
780  posY++;
781  }
782  // Generating faces...
783  i = 0;
784  posY = 0;
785  while(i+(int)lengthSequence-1 < (int)anValueSequence.size() - (int)lengthSequence){
786  for(auto j = 0; j < (int)lengthSequence-1; j++, i++){
787  aMesh.addQuadFace(nbVertexInitial+i, nbVertexInitial+i+1,
788  nbVertexInitial+i+1+lengthSequence,
789  nbVertexInitial+i+lengthSequence,
790  aMeshColor);
791  }
792  i++;
793  posY++;
794  }
795 }
796 
797 
798 
799 
800 template <typename TPoint>
801 inline
802 std::ostream&
803 DGtal::operator<< ( std::ostream & out,
804  const Mesh<TPoint> & object )
805 {
806  object.selfDisplay( out );
807  return out;
808 }
809 
810 
811 
812 
813 
814 // //
815 ///////////////////////////////////////////////////////////////////////////////
816 
817