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  currentIndex++;
471  }
472  else
473  {
474  translateIndexId.push_back(0);
475  myVertexList.erase(myVertexList.begin()+currentIndex);
476  }
477  }
478  for ( MIndex f = 0; f< nbFaces(); f++ )
479  {
480  auto &face = getFace(f);
481  for (MIndex i = 0; i<face.size(); i++)
482  {
483  face[i]=translateIndexId[face[i]];
484  }
485  }
486 }
487 
488 template<typename TPoint>
489 inline
490 void
491 DGtal::Mesh<TPoint>::rescale(const typename TPoint::Component aScale){
492  for(typename VertexStorage::iterator it = vertexBegin(); it != vertexEnd(); it++)
493  {
494  (*it) *= aScale;
495  }
496 }
497 
498 
499 template<typename TPoint>
500 inline
501 double
502 DGtal::Mesh<TPoint>::subDivideTriangularFaces(const double minArea){
503  double maxArea = 0;
504  std::vector<Mesh<TPoint>::MeshFace> facesToAdd;
505  for(unsigned int i =0; i< nbFaces(); i++)
506  {
507  typename Mesh<TPoint>::MeshFace aFace = getFace(i);
508  if(aFace.size()==3)
509  {
510  TPoint p1 = getVertex(aFace[0]);
511  TPoint p2 = getVertex(aFace[1]);
512  TPoint p3 = getVertex(aFace[2]);
513  TPoint c = (p1+p2+p3)/3.0;
514  double a = ((p2-p1).crossProduct(p3-p1)).norm()/2.0;
515  if (a>maxArea)
516  {
517  maxArea = a;
518  }
519 
520  if(a>=minArea)
521  {
522  addVertex(c);
523  MeshFace f1, f2, f3;
524  f1.push_back(aFace[0]);
525  f1.push_back(aFace[1]);
526  f1.push_back(nbVertex()-1);
527  facesToAdd.push_back(f1);
528 
529  f2.push_back(aFace[1]);
530  f2.push_back(aFace[2]);
531  f2.push_back(nbVertex()-1);
532  facesToAdd.push_back(f2);
533 
534  f3.push_back(aFace[2]);
535  f3.push_back(aFace[0]);
536  f3.push_back(nbVertex()-1);
537  facesToAdd.push_back(f3);
538  }
539  else
540  {
541  facesToAdd.push_back(aFace);
542  }
543 
544  }
545  }
546  clearFaces();
547  for(unsigned i=0; i<facesToAdd.size(); i++)
548  {
549  addFace(facesToAdd[i]);
550  }
551  return maxArea;
552 }
553 
554 
555 
556 template<typename TPoint>
557 inline
558 unsigned int
559 DGtal::Mesh<TPoint>::quadToTriangularFaces(){
560  unsigned int nbQuadT=0;
561  std::vector<Mesh<TPoint>::MeshFace> facesToAdd;
562  for(unsigned int i =0; i< nbFaces(); i++)
563  {
564  typename Mesh<TPoint>::MeshFace aFace = getFace(i);
565  if(aFace.size()==4)
566  {
567  MeshFace f1, f2;
568  f1.push_back(aFace[0]);
569  f1.push_back(aFace[1]);
570  f1.push_back(aFace[2]);
571  facesToAdd.push_back(f1);
572 
573  f2.push_back(aFace[2]);
574  f2.push_back(aFace[3]);
575  f2.push_back(aFace[0]);
576  facesToAdd.push_back(f2);
577  nbQuadT++;
578  }
579  else
580  {
581  facesToAdd.push_back(aFace);
582  }
583  }
584  clearFaces();
585  for(unsigned i=0; i<facesToAdd.size(); i++)
586  {
587  addFace(facesToAdd[i]);
588  }
589  return nbQuadT;
590 }
591 
592 
593 
594 
595 //------------------------------------------------------------------------------
596 template<typename TPoint>
597 inline
598 std::string
599 DGtal::Mesh<TPoint>::className() const
600 {
601  return "Mesh";
602 }
603 
604 
605 
606 
607 
608 
609 template <typename TPoint>
610 inline
611 void
612 DGtal::Mesh<TPoint>::createTubularMesh(DGtal::Mesh<TPoint> &aMesh, const std::vector<TPoint> &aSkeleton,
613  const double aRadius,
614  const double angleStep, const DGtal::Color &aMeshColor)
615 {
616  std::vector<double> aVecR;
617  aVecR.push_back(aRadius);
618  DGtal::Mesh<TPoint>::createTubularMesh(aMesh, aSkeleton,
619  aVecR, angleStep, aMeshColor);
620 
621 }
622 
623 
624 template <typename TPoint>
625 inline
626 void
627 DGtal::Mesh<TPoint>::createTubularMesh(DGtal::Mesh<TPoint> &aMesh, const std::vector<TPoint> &aSkeleton,
628  const std::vector<double> &aVectRadius,
629  const double angleStep, const DGtal::Color &aMeshColor)
630 {
631  auto nbVertexInitial = aMesh.nbVertex();
632  ASSERT(aVectRadius.size() > 0);
633  // Generating vertices..
634  for(auto i = 0; i< (int)aSkeleton.size(); i++)
635  {
636  TPoint vectDir;
637  TPoint uDir1, uDirPrec;
638  TPoint uDir2;
639  TPoint firstPoint;
640 
641  if(i != (int)aSkeleton.size()-1)
642  {
643  vectDir = aSkeleton.at(i+1) - aSkeleton.at(i);
644  }
645  else
646  {
647  vectDir = aSkeleton.at(i) - aSkeleton.at(i-1);
648  }
649 
650  double d = -vectDir[0]* aSkeleton.at(i)[0] - vectDir[1]*aSkeleton.at(i)[1]
651  - vectDir[2]*aSkeleton.at(i)[2];
652  TPoint pRefOrigin;
653  if(vectDir[0]!=0)
654  {
655  pRefOrigin [0]= -d/vectDir[0];
656  pRefOrigin [1]= 0.0;
657  pRefOrigin [2]= 0.0;
658  if(aSkeleton.at(i) == pRefOrigin ||
659  (vectDir[1]==0 && vectDir[2]==0))
660  {
661  pRefOrigin[1]=-1.0;
662  }
663 
664  }
665  else if (vectDir[1]!=0)
666  {
667  pRefOrigin [0]= 0.0;
668  pRefOrigin [1]= -d/vectDir[1];
669  pRefOrigin [2]= 0.0;
670  if(aSkeleton.at(i) == pRefOrigin ||
671  (vectDir[0]==0 && vectDir[2]==0))
672  {
673  pRefOrigin[0]=-1.0;
674  }
675  }else if (vectDir[2]!=0)
676  {
677  pRefOrigin [0]= 0.0;
678  pRefOrigin [1]= 0.0;
679  pRefOrigin [2]= -d/vectDir[2];
680  if(aSkeleton.at(i) == pRefOrigin ||
681  (vectDir[0]==0 && vectDir[1]==0))
682  {
683  pRefOrigin[0]=-1.0;
684  }
685  }
686  uDir1=(pRefOrigin-aSkeleton.at(i))/((pRefOrigin-aSkeleton.at(i)).norm());
687  uDir2[0] = uDir1[1]*vectDir[2]-uDir1[2]*vectDir[1];
688  uDir2[1] = uDir1[2]*vectDir[0]-uDir1[0]*vectDir[2];
689  uDir2[2] = uDir1[0]*vectDir[1]-uDir1[1]*vectDir[0];
690  uDir2/=uDir2.norm();
691  for(double a = 0.0; a < 2.0*M_PI; a += angleStep)
692  {
693  TPoint vMove = aVectRadius.at(i%aVectRadius.size())*(uDir1*cos(a) + uDir2*sin(a));
694  aMesh.addVertex(vMove + aSkeleton[i]);
695  if(a==0)
696  {
697  firstPoint = vMove + aSkeleton[i]+vectDir;
698  }
699 
700  }
701  }
702  unsigned int nbPtPerFaces = static_cast<unsigned int>((aMesh.nbVertex()-nbVertexInitial)/aSkeleton.size());
703 
704  // Generating faces...
705  for(auto i = 0; i< (int)aSkeleton.size()-1; i++)
706  {
707  if (aSkeleton.at(i)==aSkeleton.at(i+1)){
708  trace.warning() << "Two skeleton points are identical, ignoring one point." << std::endl;
709  continue;
710  }
711  // Computing best shift between two consecutive ring points to generate tube face.
712  // (criteria defined by the minimal distance between 4 sampling points)
713  double minDistance = std::numeric_limits<double>::max();
714  TPoint ptRefRing1 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces);
715  TPoint ptRefRing2 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+nbPtPerFaces/4);
716  TPoint ptRefRing3 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+2*(nbPtPerFaces/4));
717  TPoint ptRefRing4 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+3*(nbPtPerFaces/4));
718 
719  unsigned int shift = 0;
720  TPoint vectDir;
721  if(i != (int)aSkeleton.size()-1)
722  {
723  vectDir = aSkeleton.at(i+1) - aSkeleton.at(i);
724  }
725  else
726  {
727  vectDir = aSkeleton.at(i) - aSkeleton.at(i-1);
728  }
729 
730  for(unsigned int k=0; k<nbPtPerFaces; k++)
731  {
732  TPoint pScan1 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+k);
733  TPoint pScan2 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
734  (nbPtPerFaces/4+k)%nbPtPerFaces);
735  TPoint pScan3 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
736  (2*(nbPtPerFaces/4)+k)%nbPtPerFaces);
737  TPoint pScan4 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
738  (3*(nbPtPerFaces/4)+k)%nbPtPerFaces);
739  double distance = (ptRefRing1 - pScan1).norm()+(ptRefRing2 - pScan2).norm()+
740  (ptRefRing3 - pScan3).norm()+(ptRefRing4 - pScan4).norm();
741  if(distance<minDistance){
742  shift = k;
743  minDistance = distance;
744  }
745 
746  }
747  for(unsigned int k=0; k<nbPtPerFaces; k++)
748  {
749  Mesh<TPoint>::MeshFace aFace;
750  aMesh.addQuadFace(nbVertexInitial+k+i*nbPtPerFaces,
751  nbVertexInitial+(shift+k)%nbPtPerFaces+nbPtPerFaces*(i+1),
752  nbVertexInitial+(shift+k+1)%nbPtPerFaces+nbPtPerFaces*(i+1),
753  nbVertexInitial+(k+1)%nbPtPerFaces+i*nbPtPerFaces,
754  aMeshColor);
755  }
756  }
757 }
758 
759 
760 
761 
762 
763 template <typename TPoint>
764 template <typename TValue>
765 inline
766 void
767 DGtal::Mesh<TPoint>::createMeshFromHeightSequence(Mesh<TPoint> &aMesh, const std::vector<TValue> & anValueSequence,
768  const unsigned int lengthSequence,
769  double stepX, double stepY, double stepZ,
770  const DGtal::Color &aMeshColor ){
771  const auto nbVertexInitial = aMesh.nbVertex();
772  // Generating vertices..
773  int i = 0;
774  unsigned int posY = 0;
775  while(i+(int)lengthSequence-1 < (int)anValueSequence.size()){
776  for(unsigned int j = 0; j < lengthSequence; j++, i++){
777  aMesh.addVertex(TPoint(j*stepX, posY*stepY, stepZ*anValueSequence.at(i)));
778  }
779  posY++;
780  }
781  // Generating faces...
782  i = 0;
783  posY = 0;
784  while(i+(int)lengthSequence-1 < (int)anValueSequence.size() - (int)lengthSequence){
785  for(auto j = 0; j < (int)lengthSequence-1; j++, i++){
786  aMesh.addQuadFace(nbVertexInitial+i, nbVertexInitial+i+1,
787  nbVertexInitial+i+1+lengthSequence,
788  nbVertexInitial+i+lengthSequence,
789  aMeshColor);
790  }
791  i++;
792  posY++;
793  }
794 }
795 
796 
797 
798 
799 template <typename TPoint>
800 inline
801 std::ostream&
802 DGtal::operator<< ( std::ostream & out,
803  const Mesh<TPoint> & object )
804 {
805  object.selfDisplay( out );
806  return out;
807 }
808 
809 
810 
811 
812 
813 // //
814 ///////////////////////////////////////////////////////////////////////////////
815 
816