DGtal  0.9.2
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 <boost/bind.hpp>
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(unsigned int indexVertex1, unsigned int indexVertex2,
169  unsigned int 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(unsigned int indexVertex1, unsigned int indexVertex2,
189  unsigned int indexVertex3, unsigned int 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<unsigned int> &facesIndex){
223  DGtal::Mesh<TPoint> newMesh(true);
224  std::vector<unsigned int> indexVertexFaceCard(nbVertex());
225  std::vector<bool> indexFaceOK(nbFaces());
226  std::fill(indexVertexFaceCard.begin(), indexVertexFaceCard.end(), 0);
227  std::fill(indexFaceOK.begin(), indexFaceOK.end(), true);
228  for (unsigned int i = 0; i<facesIndex.size(); i++){
229  indexFaceOK[facesIndex[i]]=false;
230  }
231  // for each face remaining in the mesh we add +1 to each vertex used in a face
232  for(unsigned int i = 0; i < nbFaces(); i++){
233  if( indexFaceOK[i] ){
234  DGtal::Mesh<TPoint>::MeshFace aFace = getFace(i);
235  for (unsigned int j=0; j< aFace.size() ; j++) {
236  indexVertexFaceCard[aFace[j]] += 1;
237  }
238  }
239  }
240  // we remove all vertex with a face == 0 and compute the new vertex association:
241  std::vector<unsigned int> newVertexIndex;
242  unsigned int currentIndex=0;
243  for (unsigned int i=0; i< nbVertex(); i++) {
244  if (indexVertexFaceCard[i]!=0){
245  newMesh.addVertex(getVertex(i));
246  newVertexIndex.push_back(currentIndex);
247  currentIndex++;
248  }else{
249  newVertexIndex.push_back(0);
250  }
251  }
252  for (unsigned int i = 0; i < nbFaces(); i++) {
253  if(indexFaceOK[i]){
254  MeshFace aFace = getFace(i);
255  MeshFace aNewFace = aFace;
256  // translate the old face with new index:
257  for (unsigned int j=0; j< aFace.size() ; j++) {
258  aNewFace[j] = newVertexIndex[aFace[j]];
259  }
260  newMesh.addFace(aNewFace);
261  newMesh.setFaceColor(newMesh.nbFaces()-1, getFaceColor(i));
262  }
263  }
264  myFaceList = newMesh.myFaceList;
265  myVertexList = newMesh.myVertexList;
266  myFaceColorList = newMesh.myFaceColorList;
267 }
268 
269 
270 
271 
272 
273 template<typename TPoint>
274 inline
275 const TPoint &
276 DGtal::Mesh<TPoint>::getVertex(unsigned int i) const
277 {
278  return myVertexList.at(i);
279 }
280 
281 
282 
283 template<typename TPoint>
284 inline
285 TPoint &
286 DGtal::Mesh<TPoint>::getVertex(unsigned int i)
287 {
288  return myVertexList.at(i);
289 }
290 
291 
292 
293 template<typename TPoint>
294 inline
295 const typename DGtal::Mesh<TPoint>::MeshFace &
296 DGtal::Mesh<TPoint>::getFace(unsigned int i) const
297 {
298  return myFaceList.at(i);
299 }
300 
301 
302 template<typename TPoint>
303 inline
304 typename DGtal::Mesh<TPoint>::MeshFace &
305 DGtal::Mesh<TPoint>::getFace(unsigned int i)
306 {
307  return myFaceList.at(i);
308 }
309 
310 
311 template<typename TPoint>
312 inline
313 typename DGtal::Mesh<TPoint>::RealPoint
314 DGtal::Mesh<TPoint>::getFaceBarycenter(unsigned int i) const
315 {
316  DGtal::Mesh<TPoint>::RealPoint c;
317  MeshFace aFace = getFace(i);
318  for ( auto &j: aFace){
319  TPoint p = getVertex(j);
320  for (typename TPoint::Dimension k = 0; k < TPoint::dimension; k++){
321  c[k] += static_cast<typename RealPoint::Component>(p[k]) ;
322  }
323  }
324  return c/static_cast<typename RealPoint::Component>(aFace.size());
325 }
326 
327 
328 template<typename TPoint>
329 inline
330 unsigned int
331 DGtal::Mesh<TPoint>::nbFaces() const
332 {
333  return myFaceList.size();
334 }
335 
336 template<typename TPoint>
337 inline
338 unsigned int
339 DGtal::Mesh<TPoint>::nbVertex() const
340 {
341  return myVertexList.size();
342 }
343 
344 
345 template<typename TPoint>
346 inline
347 const DGtal::Color &
348 DGtal::Mesh<TPoint>::getFaceColor(unsigned int i) const
349 {
350  if(mySaveFaceColor)
351  {
352  return myFaceColorList.at(i);
353  }
354  else
355  {
356  return myDefaultColor;
357  }
358 }
359 
360 template <typename TPoint>
361 struct MeshBoundingBoxCompPoints
362 {
363 MeshBoundingBoxCompPoints(typename TPoint::Dimension d): myDim(d){};
364 bool operator() (const TPoint &p1, const TPoint &p2){return p1[myDim]<p2[myDim];};
365 typename TPoint::Dimension myDim;
366 };
367 
368 template<typename TPoint>
369 inline
370 std::pair<TPoint, TPoint>
371 DGtal::Mesh<TPoint>::getBoundingBox() const
372 {
373  std::pair<TPoint, TPoint> theResult;
374  TPoint lowerBound, upperBound;
375  for(unsigned int i=0; i< TPoint::size(); i++)
376  {
377  const MeshBoundingBoxCompPoints<TPoint> cmp_points(i);
378  upperBound[i] = (*(std::max_element(vertexBegin(), vertexEnd(), cmp_points)))[i];
379  lowerBound[i] = (*(std::min_element(vertexBegin(), vertexEnd(), cmp_points)))[i];
380  }
381  theResult.first = lowerBound ;
382  theResult.second = upperBound ;
383  return theResult;
384 }
385 
386 
387 template<typename TPoint>
388 inline
389 void
390 DGtal::Mesh<TPoint>::setFaceColor(const unsigned int index,
391  const DGtal::Color &aColor)
392 {
393  if (!mySaveFaceColor)
394  {
395  for(unsigned int i = 0; i<myFaceList.size(); i++)
396  {
397  myFaceColorList.push_back(myDefaultColor);
398  }
399  mySaveFaceColor=true;
400  }
401  myFaceColorList.at(index) = aColor;
402 }
403 
404 
405 template<typename TPoint>
406 inline
407 bool
408 DGtal::Mesh<TPoint>::isStoringFaceColors() const
409 {
410  return mySaveFaceColor;
411 }
412 
413 
414 
415 
416 template<typename TPoint>
417 inline
418 void
419 DGtal::Mesh<TPoint>::invertVertexFaceOrder(){
420  for(unsigned int i=0; i<myFaceList.size(); i++)
421  {
422  std::vector<unsigned int> & aFace = myFaceList.at(i);
423  for(unsigned int j=0; j < aFace.size()/2; j++)
424  {
425  unsigned int tmp=aFace.at(j);
426  aFace.at(j)=aFace.at(aFace.size()-1-j);
427  aFace.at(aFace.size()-1-j)=tmp;
428  }
429  }
430 }
431 
432 template<typename TPoint>
433 inline
434 void
435 DGtal::Mesh<TPoint>::clearFaces(){
436  myFaceList.clear();
437 }
438 
439 template<typename TPoint>
440 inline
441 void
442 DGtal::Mesh<TPoint>::changeScale(const double aScale){
443  for(typename VertexStorage::iterator it = vertexBegin(); it != vertexEnd(); it++)
444  {
445  (*it) *= aScale;
446  }
447 }
448 
449 
450 template<typename TPoint>
451 inline
452 double
453 DGtal::Mesh<TPoint>::subDivideTriangularFaces(const double minArea){
454  double maxArea = 0;
455  std::vector<Mesh<TPoint>::MeshFace> facesToAdd;
456  for(unsigned int i =0; i< nbFaces(); i++)
457  {
458  typename Mesh<TPoint>::MeshFace aFace = getFace(i);
459  if(aFace.size()==3)
460  {
461  TPoint p1 = getVertex(aFace[0]);
462  TPoint p2 = getVertex(aFace[1]);
463  TPoint p3 = getVertex(aFace[2]);
464  TPoint c = (p1+p2+p3)/3.0;
465  double a = ((p2-p1).crossProduct(p3-p1)).norm()/2.0;
466  if (a>maxArea)
467  {
468  maxArea = a;
469  }
470 
471  if(a>minArea)
472  {
473  addVertex(c);
474  MeshFace f1, f2, f3;
475  f1.push_back(aFace[0]);
476  f1.push_back(aFace[1]);
477  f1.push_back(nbVertex()-1);
478  facesToAdd.push_back(f1);
479 
480  f2.push_back(aFace[1]);
481  f2.push_back(aFace[2]);
482  f2.push_back(nbVertex()-1);
483  facesToAdd.push_back(f2);
484 
485  f3.push_back(aFace[2]);
486  f3.push_back(aFace[0]);
487  f3.push_back(nbVertex()-1);
488  facesToAdd.push_back(f3);
489  }
490  else
491  {
492  facesToAdd.push_back(aFace);
493  }
494 
495  }
496  }
497  clearFaces();
498  for(unsigned i=0; i<facesToAdd.size(); i++)
499  {
500  addFace(facesToAdd[i]);
501  }
502  return maxArea;
503 }
504 
505 
506 
507 template<typename TPoint>
508 inline
509 unsigned int
510 DGtal::Mesh<TPoint>::quadToTriangularFaces(){
511  unsigned int nbQuadT=0;
512  std::vector<Mesh<TPoint>::MeshFace> facesToAdd;
513  for(unsigned int i =0; i< nbFaces(); i++)
514  {
515  typename Mesh<TPoint>::MeshFace aFace = getFace(i);
516  if(aFace.size()==4)
517  {
518  MeshFace f1, f2;
519  f1.push_back(aFace[0]);
520  f1.push_back(aFace[1]);
521  f1.push_back(aFace[2]);
522  facesToAdd.push_back(f1);
523 
524  f2.push_back(aFace[2]);
525  f2.push_back(aFace[3]);
526  f2.push_back(aFace[0]);
527  facesToAdd.push_back(f2);
528  nbQuadT++;
529  }
530  else
531  {
532  facesToAdd.push_back(aFace);
533  }
534  }
535  clearFaces();
536  for(unsigned i=0; i<facesToAdd.size(); i++)
537  {
538  addFace(facesToAdd[i]);
539  }
540  return nbQuadT;
541 }
542 
543 
544 
545 
546 //------------------------------------------------------------------------------
547 template<typename TPoint>
548 inline
549 std::string
550 DGtal::Mesh<TPoint>::className() const
551 {
552  return "Mesh";
553 }
554 
555 
556 
557 
558 
559 
560 template <typename TPoint>
561 inline
562 void
563 DGtal::Mesh<TPoint>::createTubularMesh(DGtal::Mesh<TPoint> &aMesh, const std::vector<TPoint> &aSkeleton,
564  const double aRadius,
565  const double angleStep, const DGtal::Color &aMeshColor)
566 {
567  std::vector<double> aVecR;
568  aVecR.push_back(aRadius);
569  DGtal::Mesh<TPoint>::createTubularMesh(aMesh, aSkeleton,
570  aVecR, angleStep, aMeshColor);
571 
572 }
573 
574 
575 template <typename TPoint>
576 inline
577 void
578 DGtal::Mesh<TPoint>::createTubularMesh(DGtal::Mesh<TPoint> &aMesh, const std::vector<TPoint> &aSkeleton,
579  const std::vector<double> &aVectRadius,
580  const double angleStep, const DGtal::Color &aMeshColor)
581 {
582  unsigned int nbVertexInitial = aMesh.nbVertex();
583  ASSERT(aVectRadius.size() > 0);
584  // Generating vertices..
585  for(unsigned int i = 0; i< aSkeleton.size(); i++)
586  {
587  TPoint vectDir;
588  TPoint uDir1, uDirPrec;
589  TPoint uDir2;
590  TPoint firstPoint;
591 
592  if(i != aSkeleton.size()-1)
593  {
594  vectDir = aSkeleton.at(i+1) - aSkeleton.at(i);
595  }
596  else
597  {
598  vectDir = aSkeleton.at(i) - aSkeleton.at(i-1);
599  }
600 
601  double d = -vectDir[0]* aSkeleton.at(i)[0] - vectDir[1]*aSkeleton.at(i)[1]
602  - vectDir[2]*aSkeleton.at(i)[2];
603  TPoint pRefOrigin;
604  if(vectDir[0]!=0)
605  {
606  pRefOrigin [0]= -d/vectDir[0];
607  pRefOrigin [1]= 0.0;
608  pRefOrigin [2]= 0.0;
609  if(aSkeleton.at(i) == pRefOrigin ||
610  (vectDir[1]==0 && vectDir[2]==0))
611  {
612  pRefOrigin[1]=-1.0;
613  }
614 
615  }
616  else if (vectDir[1]!=0)
617  {
618  pRefOrigin [0]= 0.0;
619  pRefOrigin [1]= -d/vectDir[1];
620  pRefOrigin [2]= 0.0;
621  if(aSkeleton.at(i) == pRefOrigin ||
622  (vectDir[0]==0 && vectDir[2]==0))
623  {
624  pRefOrigin[0]=-1.0;
625  }
626  }else if (vectDir[2]!=0)
627  {
628  pRefOrigin [0]= 0.0;
629  pRefOrigin [1]= 0.0;
630  pRefOrigin [2]= -d/vectDir[2];
631  if(aSkeleton.at(i) == pRefOrigin ||
632  (vectDir[0]==0 && vectDir[1]==0))
633  {
634  pRefOrigin[0]=-1.0;
635  }
636  }
637  uDir1=(pRefOrigin-aSkeleton.at(i))/((pRefOrigin-aSkeleton.at(i)).norm());
638  uDir2[0] = uDir1[1]*vectDir[2]-uDir1[2]*vectDir[1];
639  uDir2[1] = uDir1[2]*vectDir[0]-uDir1[0]*vectDir[2];
640  uDir2[2] = uDir1[0]*vectDir[1]-uDir1[1]*vectDir[0];
641  uDir2/=uDir2.norm();
642  for(double a = 0.0; a < 2.0*M_PI; a += angleStep)
643  {
644  TPoint vMove = aVectRadius.at(i%aVectRadius.size())*(uDir1*cos(a) + uDir2*sin(a));
645  aMesh.addVertex(vMove + aSkeleton[i]);
646  if(a==0)
647  {
648  firstPoint = vMove + aSkeleton[i]+vectDir;
649  }
650 
651  }
652  }
653  unsigned int nbPtPerFaces = (aMesh.nbVertex()-nbVertexInitial)/aSkeleton.size();
654 
655  // Generating faces...
656  for(unsigned int i = 0; i< aSkeleton.size()-1; i++)
657  {
658  if (aSkeleton.at(i)==aSkeleton.at(i+1)){
659  trace.warning() << "Two skeleton points are identical, ignoring one point." << std::endl;
660  continue;
661  }
662  // Computing best shift between two consecutive ring points to generate tube face.
663  // (criteria defined by the minimal distance between 4 sampling points)
664  double minDistance = std::numeric_limits<double>::max();
665  TPoint ptRefRing1 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces);
666  TPoint ptRefRing2 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+nbPtPerFaces/4);
667  TPoint ptRefRing3 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+2*(nbPtPerFaces/4));
668  TPoint ptRefRing4 = aMesh.getVertex(nbVertexInitial+i*nbPtPerFaces+3*(nbPtPerFaces/4));
669 
670  unsigned int shift = 0;
671  TPoint vectDir;
672  if(i != aSkeleton.size()-1)
673  {
674  vectDir = aSkeleton.at(i+1) - aSkeleton.at(i);
675  }
676  else
677  {
678  vectDir = aSkeleton.at(i) - aSkeleton.at(i-1);
679  }
680 
681  for(unsigned int k=0; k<nbPtPerFaces; k++)
682  {
683  TPoint pScan1 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+k);
684  TPoint pScan2 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
685  (nbPtPerFaces/4+k)%nbPtPerFaces);
686  TPoint pScan3 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
687  (2*(nbPtPerFaces/4)+k)%nbPtPerFaces);
688  TPoint pScan4 = aMesh.getVertex(nbVertexInitial+(i+1)*nbPtPerFaces+
689  (3*(nbPtPerFaces/4)+k)%nbPtPerFaces);
690  double distance = (ptRefRing1 - pScan1).norm()+(ptRefRing2 - pScan2).norm()+
691  (ptRefRing3 - pScan3).norm()+(ptRefRing4 - pScan4).norm();
692  if(distance<minDistance){
693  shift = k;
694  minDistance = distance;
695  }
696 
697  }
698  for(unsigned int k=0; k<nbPtPerFaces; k++)
699  {
700  Mesh<TPoint>::MeshFace aFace;
701  aMesh.addQuadFace(nbVertexInitial+k+i*nbPtPerFaces,
702  nbVertexInitial+(shift+k)%nbPtPerFaces+nbPtPerFaces*(i+1),
703  nbVertexInitial+(shift+k+1)%nbPtPerFaces+nbPtPerFaces*(i+1),
704  nbVertexInitial+(k+1)%nbPtPerFaces+i*nbPtPerFaces,
705  aMeshColor);
706  }
707  }
708 }
709 
710 
711 
712 
713 
714 template <typename TPoint>
715 template <typename TValue>
716 inline
717 void
718 DGtal::Mesh<TPoint>::createMeshFromHeightSequence(Mesh<TPoint> &aMesh, const std::vector<TValue> & anValueSequence,
719  const unsigned int lengthSequence,
720  double stepX, double stepY, double stepZ,
721  const DGtal::Color &aMeshColor ){
722  unsigned int nbVertexInitial = aMesh.nbVertex();
723  // Generating vertices..
724  unsigned int i = 0;
725  unsigned int posY = 0;
726  while(i+lengthSequence-1 < anValueSequence.size()){
727  for(unsigned int j = 0; j < lengthSequence; j++, i++){
728  aMesh.addVertex(TPoint(j*stepX, posY*stepY, stepZ*anValueSequence.at(i)));
729  }
730  posY++;
731  }
732  // Generating faces...
733  i = 0, posY = 0;
734  while(i+lengthSequence-1 < anValueSequence.size() - lengthSequence){
735  for(unsigned int j = 0; j < lengthSequence-1; j++, i++){
736  aMesh.addQuadFace(nbVertexInitial+i, nbVertexInitial+i+1,
737  nbVertexInitial+i+1+lengthSequence,
738  nbVertexInitial+i+lengthSequence,
739  aMeshColor);
740  }
741  i++;
742  posY++;
743  }
744 }
745 
746 
747 
748 
749 template <typename TPoint>
750 inline
751 std::ostream&
752 DGtal::operator<< ( std::ostream & out,
753  const Mesh<TPoint> & object )
754 {
755  object.selfDisplay( out );
756  return out;
757 }
758 
759 
760 
761 
762 
763 // //
764 ///////////////////////////////////////////////////////////////////////////////
765 
766