DGtal  1.4.beta
Board3D.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 Board3D.ih
19  * @author Martial Tola <http://liris.cnrs.fr/martial.tola/>
20  * @date mercredi 22 juin 2011
21  *
22  * @brief
23  *
24  * Implementation of inline methods defined in Board3D.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 // IMPLEMENTATION of inline methods.
31 ///////////////////////////////////////////////////////////////////////////////
32 
33 //////////////////////////////////////////////////////////////////////////////
34 #include <cstdlib>
35 #include "DGtal/io/CDrawableWithDisplay3D.h"
36 #include "DGtal/io/Color.h"
37 
38 #include <limits>
39 //////////////////////////////////////////////////////////////////////////////
40 
41 ///////////////////////////////////////////////////////////////////////////////
42 // Implementation of inline methods //
43 
44 /**
45  * Set the default color for future drawing.
46  *
47  * @param aColor a DGtal::Color (allow to set a trasnparency value).
48  *
49  **/
50 template < typename Space, typename KSpace>
51 inline
52 DGtal::Board3D<Space, KSpace> &
53 DGtal::Board3D<Space, KSpace>::operator<<(const DGtal::Color & aColor)
54 {
55  myDefaultColor=aColor;
56  return *this;
57 }
58 
59 
60 /**
61  * Draws the drawable [object] in this board. It should satisfy
62  * the concept CDrawableWithBoard3D, which requires for instance a
63  * method setStyle( Board3D & ).
64  *
65  * @param object any drawable object.
66  * @return a reference on 'this'.
67  */
68 template < typename Space, typename KSpace>
69 template <typename TDrawableWithDisplay3D>
70 inline
71 DGtal::Board3D<Space, KSpace> &
72 DGtal::Board3D<Space, KSpace>::operator<<( const TDrawableWithDisplay3D & object )
73 {
74  BOOST_CONCEPT_ASSERT((concepts::CDrawableWithDisplay3D< TDrawableWithDisplay3D, Space, KSpace>));
75 
76  DGtal::Display3DFactory<Space,KSpace>::draw(*this, object);
77  return *this;
78 }
79 
80 
81 
82 ///////////////////////////////////////////////////////////////////////////////
83 // Standard services - public :
84 
85 /*!
86  * \brief Constructor.
87  */
88 template < typename Space, typename KSpace>
89 inline
90 DGtal::Board3D<Space, KSpace>::Board3D() : Display3D<Space,KSpace>()
91 {
92  init();
93 }
94 
95 ///////////////////////////////////////////////////////////////////////////////
96 // Interface - public :
97 
98 /**
99  * Writes/Displays the object on an output stream.
100  * @param outOBJ the output stream where the object is written.
101  */
102 template < typename Space, typename KSpace>
103 inline
104 void
105 DGtal::Board3D<Space, KSpace>::selfDisplay ( std::ostream & outOBJ ) const
106 {
107  outOBJ << "[Board3D]";
108 }
109 
110 /**
111  * Checks the validity/consistency of the object.
112  * @return 'true' if the object is valid, 'false' otherwise.
113  */
114 template < typename Space, typename KSpace>
115 bool
116 DGtal::Board3D<Space, KSpace>::isValid() const
117 {
118  return true;
119 }
120 
121 
122 /**
123  * Save a OBJ image.
124  * @param filename filename of the image to save.
125  */
126 template < typename Space, typename KSpace>
127 inline
128 void DGtal::Board3D<Space, KSpace>::saveOBJ(const std::string & filename, const bool normalization)
129 {
130 
131  size_t k, j; //id of each elements and sub elements of a list for the .OBJ identification
132  std::ofstream outOBJ; //OBJ file where to write
133  std::ofstream outMTL; //MTL file where to write
134 
135  //the filename without OBJ any extention
136  std::string noExt;
137  size_t lastdot = filename.find_last_of(".");
138  if (lastdot != std::string::npos)
139  noExt = filename.substr(0, lastdot);
140  else
141  noExt = filename;
142 
143  std::stringstream nameOBJ;
144  std::stringstream nameMTL;
145  nameOBJ << noExt << ".obj";
146  nameMTL << noExt << ".mtl";
147 
148  outOBJ.open(nameOBJ.str().c_str());
149  outOBJ << "# OBJ format"<< "\n";
150  outOBJ << "# generated from Board3D from the DGtal library"<< "\n";
151  outOBJ << "mtllib " << nameMTL.str() << "\n";
152  outOBJ << "\n";
153 
154  outMTL.open(nameMTL.str().c_str());
155  outMTL << "# MTL format"<< "\n";
156  outMTL << "# generated from Board3D from the DGtal library"<< "\n";
157 
158 
159  //myClippingPlaneList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
160  //std::vector< clippingPlaneD3D >::const_iterator
161  {
162  if(Board3D<Space, KSpace>::myClippingPlaneList.size()> 0)
163  {
164  trace.info() << "number of clipping plane : "
165  << Board3D<Space, KSpace>::myClippingPlaneList.size() << std::endl;
166  }
167  }
168 
169  // normalization -----------------------------------------------------------------------
170  double scale = 1.0;
171  typename Space::RealPoint shift(0.0,0.0,0.0);
172  if (normalization)
173  {
174  //We center the shape W.r.t. its bounding box
175  for(unsigned int i=0; i < 3; i++)
176  shift[i] = (this->myBoundingPtUp[i] + this->myBoundingPtLow[i])/2.0;
177 
178  //We compute the scale of the largest direction so that it fits
179  //in [-1/2,1/2] interval
180  double tmpwidth;
181 
182  int i =0;
183  while ((i<3) && (this->myBoundingPtUp[i] - this->myBoundingPtLow[i] == 0))
184  i++;
185  ASSERT_MSG(i < 3, "Error when computing the scale from the bounding box. The Bbox seems to be empty.");
186 
187  scale = 1.0/(this->myBoundingPtUp[i] - this->myBoundingPtLow[i]);
188  for( ; i < 3; i++)
189  {
190  tmpwidth = (this->myBoundingPtUp[i] - this->myBoundingPtLow[i]);
191  if ((tmpwidth != 0.0) && (scale > 1.0/tmpwidth))
192  scale = 1.0/tmpwidth;
193  }
194  outOBJ << "# Normalization was used. Scale= "<< scale << " and Shift= "<<shift<< "\n";
195  }
196 
197  // Draw the shapes -----------------------------------------------------------------------
198 
199  ///Temporary variables
200  typename Space::RealPoint apoint, apoint1, apoint2, apoint3, apoint4;
201 
202  // myBallSetList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
203  {
204  k=0;//id of each BallSetList for the .OBJ identification
205  for ( typename std::vector< std::vector< typename Board3D<Space, KSpace>::BallD3D> >::const_iterator it = Board3D<Space, KSpace>::myBallSetList.begin();
206  it != Board3D<Space, KSpace>::myBallSetList.end(); it++)
207  {
208  std::ostringstream tmpStream; // checking that points exist before creating an object
209  for (typename std::vector< typename Board3D<Space, KSpace>::BallD3D>::const_iterator s_it = it->begin();
210  s_it != it->end(); s_it++)
211  {
212  //test if a clipping plane do not cut it
213  bool notCut =true;
214  typename std::vector< typename Board3D<Space, KSpace>::ClippingPlaneD3D>::const_iterator itClip = Board3D<Space, KSpace>::myClippingPlaneList.begin();
215  while (itClip !=Board3D<Space, KSpace>::myClippingPlaneList.end() && notCut )
216  {
217  double d2 = ( itClip->a * (*s_it)[0]) + (itClip->b * (*s_it)[1]) + ( itClip->c * (*s_it)[2] ) + itClip->d;
218  notCut = ( d2 >= 0);
219 
220  itClip ++;
221  }
222  if (notCut)
223  {
224  double thetaResolution = s_it->resolution;
225  double thetaStep= (2.0*M_PI)/thetaResolution;
226  double phiResolution = s_it->resolution;
227  double phiStep= M_PI/phiResolution;
228 
229  double radius = s_it->radius*scale;
230  double xCenter = (s_it->center[0]-shift[0])*scale;
231  double yCenter = (s_it->center[1]-shift[0])*scale;
232  double zCenter = (s_it->center[2]-shift[0])*scale;
233 
234  for(unsigned int jj =0; jj < phiResolution; jj++)
235  {
236  double phi0 = M_PI/2.0-jj*phiStep;
237  double phi1 = M_PI/2.0-(jj+1)*phiStep;
238  for(unsigned int i =0; i < thetaResolution; i++)
239  {
240  double theta0 = i * thetaStep;
241  double theta1 = (i+1) * thetaStep;
242  tmpStream << "v " << xCenter+cos(phi0)*cos(theta0)*radius
243  << " " << yCenter+ cos(phi0)*sin(theta0)*radius << " " << zCenter+ sin(phi0)*radius << "\n";
244  tmpStream << "v " << xCenter+cos(phi0)*cos(theta1)*radius
245  << " " << yCenter+ cos(phi0)*sin(theta1)*radius << " " << zCenter+ sin(phi0)*radius << "\n";
246  tmpStream << "v " << xCenter+cos(phi1)*cos(theta0)*radius << " "
247  << yCenter+ cos(phi1)*sin(theta0)*radius << " " <<zCenter+ sin(phi1)*radius << "\n";
248  tmpStream << "f " << "-1" << " " << "-2" << " " << "-3"<< "\n";
249 
250  tmpStream << "v " << xCenter+cos(phi0)*cos(theta1)*radius
251  << " " << yCenter+ cos(phi0)*sin(theta1)*radius << " " << zCenter+ sin(phi0)*radius << "\n";
252  tmpStream << "v " << xCenter+cos(phi1)*cos(theta0)*radius << " "
253  << yCenter+ cos(phi1)*sin(theta0)*radius << " " <<zCenter+ sin(phi1)*radius << "\n";
254  tmpStream << "v " << xCenter+cos(phi1)*cos(theta1)*radius << " "
255  << yCenter+ cos(phi1)*sin(theta1)*radius << " " <<zCenter+ sin(phi1)*radius << "\n";
256  tmpStream << "f " << "-3" << " " << "-2" << " " << "-1"<< "\n";
257  }
258  }
259  }
260  }
261 
262  if (tmpStream.str().size() > 0)
263  {
264  std::stringstream name;
265  name << Board3D<Space, KSpace>::myBallSetNameList.at(k);
266  if ( name.str() == "")
267  {
268  name << "myBallSetList_" << k ;
269  }
270 
271  typename std::vector< typename Board3D<Space, KSpace>::BallD3D>::const_iterator itBegin = it->begin();
272  unsigned int matid = getMaterialIndex(itBegin->color);
273  std::stringstream matName;
274  matName << "Mat_" << matid;
275  outOBJ << "o " << name.str() << "\n";
276  outOBJ << "usemtl " << matName.str() << "\n";
277  outOBJ << tmpStream.str();
278  }
279  k++;
280  }
281  }
282 
283  // myLineSetList+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
284  {
285  j =0;
286  k=0;//id of each LineSetList for the .OBJ identification
287  for(typename std::vector<std::vector< typename Board3D<Space, KSpace>::LineD3D> >::const_iterator it =Board3D<Space, KSpace>::myLineSetList.begin();
288  it!= Board3D<Space, KSpace>::myLineSetList.end(); it++)
289  {
290  std::ostringstream tmpStream;
291  for (typename std::vector< typename Board3D<Space, KSpace>::LineD3D>::const_iterator s_it = it->begin();
292  s_it != it->end();++s_it)
293  {
294 
295  //test if a clipping plane do not cut it
296  bool notCut =true;
297  double width = s_it->width;
298  typename std::vector< typename Board3D<Space, KSpace>::ClippingPlaneD3D>::const_iterator itClip = Board3D<Space, KSpace>::myClippingPlaneList.begin();
299  while (itClip !=Board3D<Space, KSpace>::myClippingPlaneList.end() && notCut )
300  {
301  double a = itClip->a;
302  double b = itClip->b;
303  double c = itClip->c;
304  double d = itClip->d;
305  double d2 ;
306  d2 = ( a * s_it->point1[0]) + (b * (s_it->point1[1] -width)) + ( c * s_it->point1[2] ) + d;
307  notCut = ( d2 >= 0);
308  d2 = ( a * s_it->point1[0]) + (b * (s_it->point1[1] +width)) + ( c * s_it->point1[2] ) + d;
309  notCut = ( notCut && ( d2 >= 0) );
310  d2 = ( a * s_it->point2[0]) + (b * (s_it->point2[1] +width)) + ( c * s_it->point2[2] ) + d;
311  notCut = ( notCut && ( d2 >= 0) );
312  d2 = ( a * s_it->point2[0]) + (b * (s_it->point2[1] -width)) + ( c * s_it->point2[2] ) + d;
313  notCut = ( notCut && ( d2 >= 0) );
314  d2 = ( a * s_it->point1[0]) + (b * s_it->point1[1]) + ( c * (s_it->point1[2] -width )) + d;
315  notCut = ( notCut && ( d2 >= 0) );
316  d2 = ( a * s_it->point1[0]) + (b * s_it->point1[1]) + ( c * (s_it->point1[2] +width )) + d;
317  notCut = ( notCut && ( d2 >= 0) );
318  d2 = ( a * s_it->point2[0]) + (b * s_it->point2[1]) + ( c * (s_it->point2[2] +width )) + d;
319  notCut = ( notCut && ( d2 >= 0) );
320  d2 = ( a * s_it->point2[0]) + (b * s_it->point2[1]) + ( c * (s_it->point2[2] -width )) + d;
321  notCut = ( notCut && ( d2 >= 0) );
322 
323  itClip ++;
324  }
325 
326  if (notCut)
327  {
328  // OBJ dont know how to draw lines, have to make a
329  // cuboid with a depth and height of a pixel width
330 
331  apoint1 = ((s_it->point1) - shift)*scale;
332  apoint2 = ((s_it->point2) - shift)*scale;
333  tmpStream << "v " << apoint1[0] << " " << apoint1[1] -width << " " << apoint1[2] -width << "\n";
334  tmpStream << "v " << apoint1[0] << " " << apoint1[1] -width << " " << apoint1[2] +width << "\n";
335  tmpStream << "v " << apoint1[0] << " " << apoint1[1] +width << " " << apoint1[2] -width << "\n";
336  tmpStream << "v " << apoint1[0] << " " << apoint1[1] +width << " " << apoint1[2] +width<< "\n";
337 
338  tmpStream << "v " << apoint2[0] << " " << apoint2[1] -width << " " << apoint2[2] -width << "\n";
339  tmpStream << "v " << apoint2[0] << " " << apoint2[1] -width << " " << apoint2[2] +width << "\n";
340  tmpStream << "v " << apoint2[0] << " " << apoint2[1] +width << " " << apoint2[2] -width << "\n";
341  tmpStream << "v " << apoint2[0] << " " << apoint2[1] +width << " " << apoint2[2] +width<< "\n";
342 
343  tmpStream << "vn " << "0" << " " << "0" << " " << "1" << "\n";//up
344  tmpStream << "vn " << "0" << " " << "0" << " " << "-1" << "\n";//back
345 
346  tmpStream << "f " << "-7//" << " " << "-8//" << " " << "-4//"<< " " << "-3//" << "\n";//left
347  tmpStream << "f " << "-5//" << " " << "-7//" << " " << "-3//"<< " " << "-1//"<< "\n";//front
348  tmpStream << "f " << "-3//-2" << " " << "-4//-2" << " " << "-2//-2"<< " " << "-1//-2"<< "\n";//up
349  tmpStream << "f " << "-8//-1" << " " << "-7//-1" << " " << "-5//-1"<< " " << "-6//-1"<< "\n";//back
350  tmpStream << "f " << "-2//" << " " << "-4//" << " " << "-8//"<< " " << "-6//"<< "\n";//down
351  tmpStream << "f " << "-1//" << " " << "-2//" << " " << "-6//"<< " " << "-5//"<< "\n";//right
352 
353  j++;
354  }
355  }
356  if (tmpStream.str() != "")
357  {
358  std::stringstream name;
359  name << Board3D<Space, KSpace>::myLineSetNameList.at(k);
360  if ( name.str()== "")
361  {
362  name << "myLineSetList_" << k ;
363  }
364 
365  typename std::vector< typename Board3D<Space, KSpace>::LineD3D>::const_iterator itBegin = it->begin();
366  unsigned int matid = getMaterialIndex(itBegin->color);
367  std::stringstream matName;
368  matName << "Mat_" << matid;
369  outOBJ << "o " << name.str() << "\n";
370  outOBJ << "usemtl " << matName.str() << "\n";
371  outOBJ << tmpStream.str();
372  }
373 
374  k++;
375  }
376  }
377 
378  // myCubeSetList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
379  {
380  j = 0 ; //id of each Cube sub list for the .OBJ identification
381 
382 
383  //Foreach list
384  for(typename Board3D<Space, KSpace>::CubesMap::const_iterator it =Board3D<Space, KSpace>::myCubesMap.begin();
385  it != Board3D<Space, KSpace>::myCubesMap.end(); it++)
386  {
387 
388  std::stringstream name;
389  std::ostringstream tmpStream;
390 
391  name << "myCubeSetList_" << it->first ;
392  outOBJ << "o " << name.str() << "\n";
393 
394 
395  //For each list, we force the cube color to be set in the OBJ file
396  unsigned int prevMaterialIndex = std::numeric_limits<unsigned int>::max(); //index to the last voxel material
397 
398  //Foreach cube in the list
399  for (typename std::vector< typename Board3D<Space, KSpace>::CubeD3D>::const_iterator s_it = it->second.begin();
400  s_it != it->second.end(); ++s_it)
401  {
402  //Color
403  unsigned int matid = getMaterialIndex(s_it->color);
404  if (matid != prevMaterialIndex)
405  {
406  std::stringstream matName;
407  matName << "Mat_" << matid;
408  outOBJ << "usemtl " << matName.str() << "\n";
409  prevMaterialIndex = matid;
410  }
411 
412  double wid = s_it->width;
413  double x = s_it->center[0];
414  double y = s_it->center[1];
415  double z = s_it->center[2];
416 
417  double x1 = x - wid;
418  double x2 = x + wid;
419  double y1 = y - wid;
420  double y2 = y + wid;
421  double z1 = z - wid;
422  double z2 = z + wid;
423  //test if a clipping plane do not cut it
424  bool notCut =true;
425  typename std::vector< typename Board3D<Space, KSpace>::ClippingPlaneD3D>::const_iterator itClip = Board3D<Space, KSpace>::myClippingPlaneList.begin();
426  while (itClip !=Board3D<Space, KSpace>::myClippingPlaneList.end() && notCut )
427  {
428  double a = itClip->a;
429  double b = itClip->b;
430  double c = itClip->c;
431  double d = itClip->d;
432  double d2 = ( a * x1) + (b * y1) + ( c * z2 ) + d;
433  notCut = ( d2 >= 0);
434 
435  d2 = ( a * x2) + (b * y1) + ( c * z2) + d;
436  notCut = ( notCut && ( d2 >= 0) );
437  d2 = ( a * x1) + (b * y1) + ( c * z1) + d;
438  notCut = ( notCut && ( d2 >= 0) );
439  d2 = ( a * x2) + (b * y1) + ( c * z1) + d;
440  notCut = ( notCut && ( d2 >= 0) );
441  d2 = ( a * x1) + (b * y2) + ( c * z2) + d;
442  notCut = ( notCut && ( d2 >= 0) );
443  d2 = ( a * x2) + (b * y2) + ( c * z2) + d;
444  notCut = ( notCut && ( d2 >= 0) );
445  d2 = ( a * x1) + (b * y2) + ( c * z1) + d;
446  notCut = ( notCut && ( d2 >= 0) );
447  d2 = ( a * x2) + (b * y2) + ( c * z1) + d;
448  notCut = ( notCut && ( d2 >= 0) );
449 
450  itClip ++;
451  }
452 
453  //OPT cube
454 
455  if (notCut)
456  {
457  // this version is one cube with (x,y,z) the center of it and wid its distance between it and its faces
458 
459  x1 = (x1-shift[0])*scale;
460  y1 = (y1-shift[1])*scale;
461  z1 = (z1-shift[2])*scale;
462  x2 = (x2-shift[0])*scale;
463  y2 = (y2-shift[1])*scale;
464  z2 = (z2-shift[2])*scale;
465 
466  outOBJ << "v " << x1 << " " << y1 << " " << z1 << "\n";
467  outOBJ << "v " << x1 << " " << y2 << " " << z1 << "\n";
468  outOBJ << "v " << x2 << " " << y2 << " " << z1 << "\n";
469  outOBJ << "v " << x2 << " " << y1 << " " << z1 << "\n";
470  outOBJ << "v " << x1 << " " << y1 << " " << z2 << "\n";
471  outOBJ << "v " << x1 << " " << y2 << " " << z2 << "\n";
472  outOBJ << "v " << x2 << " " << y2 << " " << z2 << "\n";
473  outOBJ << "v " << x2 << " " << y1 << " " << z2 << "\n";
474 
475  outOBJ << "f " << "-8" << " " << "-7" << " " <<"-6" << " " <<"-5" << "\n";//bottom
476  outOBJ << "f " << "-8" << " " << "-4" << " " <<"-3" << " " <<"-7" << "\n";//back
477  outOBJ << "f " << "-2" << " " << "-1" << " " <<"-5" << " " <<"-6" << "\n";//front
478  outOBJ << "f " << "-7" << " " << "-3" << " " <<"-2" << " " <<"-6" << "\n";//right
479  outOBJ << "f " << "-8" << " " << "-5" << " " <<"-1" << " " <<"-4" << "\n";//left
480  outOBJ << "f " << "-4" << " " << "-1" << " " <<"-2" << " " <<"-3" << "\n";//top
481 
482 
483 
484  }
485 
486 
487  j++;
488 
489  }
490  k++;
491  }
492 
493  }
494 
495  //OPT quad
496  // myQuadList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
497  {
498  k = 0; // id of each list
499  Color previousCol;
500  std::stringstream matName;
501  //we init the previousCol var.
502  if (Board3D<Space, KSpace>::myQuadsMap.begin() != Board3D<Space, KSpace>::myQuadsMap.end())
503  previousCol = Board3D<Space, KSpace>::myQuadsMap.begin()->second.begin()->color;
504 
505 
506 
507  //Foreach lists
508  for (typename Board3D<Space, KSpace>::QuadsMap::const_iterator it = Board3D<Space, KSpace>::myQuadsMap.begin();
509  it != Board3D<Space, KSpace>::myQuadsMap.end(); it++)
510  {
511 
512  outOBJ << "o myQuadSetList_" << it->first <<"\n";
513  //For each list, we force the material
514  unsigned int matid = getMaterialIndex(previousCol);
515  outOBJ << "usemtl Mat_" << matid << "\n";
516 
517 
518  //We scan the quads of the list
519  for (typename std::vector<typename Board3D<Space, KSpace>::QuadD3D>::const_iterator aQuad = it->second.begin();
520  aQuad!=it->second.end();aQuad ++)
521  {
522  if (previousCol != aQuad->color)
523  {
524  previousCol = aQuad->color;
525 
526  matid = getMaterialIndex(previousCol);
527  outOBJ << "usemtl Mat_" << matid << "\n";
528  }
529 
530  apoint1 = (aQuad->point1 -shift)*scale;
531  apoint2 = (aQuad->point2 -shift)*scale;
532  apoint3 = (aQuad->point3 -shift)*scale;
533  apoint4 = (aQuad->point4 -shift)*scale;
534 
535  outOBJ << "v " << apoint1[0] << " " << apoint1[1] << " " << apoint1[2] << "\n";
536  outOBJ << "v " << apoint2[0] << " " << apoint2[1] << " " << apoint2[2] << "\n";
537  outOBJ << "v " << apoint3[0] << " " << apoint3[1] << " " << apoint3[2] << "\n";
538  outOBJ << "v " << apoint4[0] << " " << apoint4[1] << " " << apoint4[2] << "\n";
539  outOBJ << "vn " << aQuad->nx << " " << aQuad->ny << " " << aQuad->nz << "\n";
540  outOBJ << "f " << "-4//-1" << " " << "-3//-1" << " " << "-2//-1"<< " " << "-1//-1"<< "\n";
541  }
542 
543  }
544  }
545 
546  //OPT triangle
547 
548  // myTriangleList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
549  {
550  //std::vector<triangleD3D>::const_iterator
551  k = 0; // id of each list
552  for(typename std::vector<std::vector< typename Board3D<Space, KSpace>::TriangleD3D> >::const_iterator it =Board3D<Space, KSpace>::myTriangleSetList.begin();
553  it != Board3D<Space, KSpace>::myTriangleSetList.end(); it++)
554  {
555  std::ostringstream tmpStream;
556  for (typename std::vector< typename Board3D<Space, KSpace>::TriangleD3D>::const_iterator s_it = it->begin();
557  s_it != it->end(); ++s_it)
558  {
559  //test if a clipping plane do not cut it
560  bool notCut =true;
561  typename std::vector< typename Board3D<Space, KSpace>::ClippingPlaneD3D>::const_iterator itClip =
562  Board3D<Space, KSpace>::myClippingPlaneList.begin();
563  while (itClip !=Board3D<Space, KSpace>::myClippingPlaneList.end() && notCut )
564  {
565  double a = itClip->a;
566  double b = itClip->b;
567  double c = itClip->c;
568  double d = itClip->d;
569  double d2 = ( a * s_it->point1[0]) + (b * s_it->point1[1]) + ( c * s_it->point1[2] ) + d;
570  notCut = ( d2 >= 0);
571  d2 = ( a * s_it->point2[0]) + (b * s_it->point2[1]) + ( c * s_it->point2[2]) + d;
572  notCut = ( notCut && ( d2 >= 0) );
573  d2 = ( a * s_it->point3[0]) + (b * s_it->point3[1]) + ( c * s_it->point3[2]) + d;
574  notCut = ( notCut && ( d2 >= 0) );
575 
576  itClip ++;
577  }
578  if (notCut)
579  {
580  apoint1 = (s_it->point1 - shift)*scale;
581  apoint2 = (s_it->point2 - shift)*scale;
582  apoint3 = (s_it->point3 - shift)*scale;
583 
584 
585  tmpStream << "v " << apoint1[0] << " " << apoint1[1] << " " << apoint1[2] << "\n";
586  tmpStream << "v " << apoint2[0] << " " << apoint2[1] << " " << apoint2[2] << "\n";
587  tmpStream << "v " << apoint3[0] << " " << apoint3[1] << " " << apoint3[2] << "\n";
588 
589  tmpStream << "vn " << s_it->nx << " " << s_it->ny << " " << s_it->nz << "\n";
590 
591  tmpStream << "f " << "-3//-1" << " " << "-2//-1"<< " " << "-1//-1"<< "\n";
592  }
593  }
594 
595  if (tmpStream.str() != "")
596  {
597  std::stringstream name;
598  name << Board3D<Space, KSpace>::myTriangleSetNameList.at(k);
599  if ( name.str() == "")
600  {
601  name << "myTriangleSetList_" << k ;
602  }
603  typename std::vector< typename Board3D<Space, KSpace>::TriangleD3D>::const_iterator itBegin = it->begin();
604  unsigned int matid = getMaterialIndex(itBegin->color);
605  std::stringstream matName;
606  matName << "Mat_" << matid;
607  outOBJ << "o " << name.str() << "\n";
608  outOBJ << "usemtl " << matName.str() << "\n";
609  outOBJ << tmpStream.str();
610  }
611  k++;
612  }
613  }
614 
615  //OPT scell
616 
617  // Drawing all Khalimsky Space Cells --------------------------------------------------------------------
618 
619  // Prism (from updateList)+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
620  {
621  j=0;
622  k=0;
623  std::ostringstream tmpStream;
624 
625  for (typename std::vector< typename Board3D<Space, KSpace>::QuadD3D>::iterator s_it = Board3D<Space, KSpace>::myPrismList.begin();
626  s_it != Board3D<Space, KSpace>::myPrismList.end();
627  ++s_it)
628  {
629  //test if a clipping plane do not cut it
630  bool notCut =true;
631  typename std::vector< typename Board3D<Space, KSpace>::ClippingPlaneD3D>::const_iterator itClip = Board3D<Space, KSpace>::myClippingPlaneList.begin();
632  while (itClip !=Board3D<Space, KSpace>::myClippingPlaneList.end() && notCut )
633  {
634  double a = itClip->a;
635  double b = itClip->b;
636  double c = itClip->c;
637  double d = itClip->d;
638  double d2 = ( a * s_it->point1[0]) + (b * s_it->point1[1]) + ( c * s_it->point1[2] ) + d;
639  notCut = ( d2 >= 0);
640  d2 = ( a * s_it->point2[0]) + (b * s_it->point2[1]) + ( c * s_it->point2[2]) + d;
641  notCut = ( notCut && ( d2 >= 0) );
642  d2 = ( a * s_it->point3[0]) + (b * s_it->point3[1]) + ( c * s_it->point3[2]) + d;
643  notCut = ( notCut && ( d2 >= 0) );
644  d2 = ( a * s_it->point4[0]) + (b * s_it->point4[1]) + ( c * s_it->point4[2]) + d;
645  notCut = ( notCut && ( d2 >= 0) );
646 
647  itClip ++;
648  }
649  if (notCut)
650  {
651  apoint1 = (s_it->point1 -shift)*scale;
652  apoint2 = (s_it->point2 -shift)*scale;
653  apoint3 = (s_it->point3 -shift)*scale;
654  apoint4 = (s_it->point4 -shift)*scale;
655 
656  tmpStream << "v " << apoint1[0] << " " << apoint1[1] << " " << apoint1[2] << "\n";
657  tmpStream << "v " << apoint2[0] << " " << apoint2[1] << " " << apoint2[2] << "\n";
658  tmpStream << "v " << apoint3[0] << " " << apoint3[1] << " " << apoint3[2] << "\n";
659  tmpStream << "v " << apoint4[0] << " " << apoint4[1] << " " << apoint4[2] << "\n";
660 
661  tmpStream << "vn " << s_it->nx << " " << s_it->ny << " " << s_it->nz << "\n";
662 
663  tmpStream << "f " << "-4//-1" << " " << "-3//-1" << " " << "-2//-1"<< " " << "-1//-1" << "\n";
664 
665  j++;
666 
667  }
668  if (tmpStream.str() != "")
669  {
670  std::stringstream name;
671  name << "myPrismList" << j;
672  std::stringstream matName;
673  matName << "myPrismList" << j << "MAT";
674  typename std::vector< typename Board3D<Space, KSpace>::QuadD3D>::const_iterator itBegin = Board3D<Space, KSpace>::myPrismList.begin();
675  unsigned int matid = getMaterialIndex(itBegin->color);
676  matName << "Mat_" << matid;
677  outOBJ << "o " << name.str() << "\n";
678  outOBJ << "usemtl " << matName.str() << "\n";
679  outOBJ << tmpStream.str();
680  }
681  }
682 
683 
684  }
685 
686  //end Prism (from updateList)+++++++++++++++++++++++++++++++
687  outMTL << myMTLBuffer.str();
688 
689  outOBJ.close();
690  outMTL.close();
691 }
692 
693 
694 
695 
696 template < typename Space, typename KSpace>
697 inline
698 void
699 DGtal::Board3D<Space, KSpace>::init()
700 {
701 
702  myMaterialIndex = 0;
703 
704  Board3D<Space, KSpace>::createNewCubeList();
705  Board3D<Space, KSpace>::createNewLineList();
706  Board3D<Space, KSpace>::createNewBallList();
707 
708  Board3D<Space, KSpace>::myCurrentFillColor = DGtal::Color (220, 220, 220);
709  Board3D<Space, KSpace>::myCurrentLineColor = DGtal::Color (22, 22, 222, 50);
710  Board3D<Space, KSpace>::myDefaultColor= DGtal::Color(255, 255, 255);
711  Board3D<Space, KSpace>::myModes["Board3D"]="SolidMode";
712 
713  std::string nameLineSet;
714  Board3D<Space, KSpace>::myLineSetNameList.push_back(nameLineSet);
715 
716  std::string nameBallSet;
717  Board3D<Space, KSpace>::myBallSetNameList.push_back(nameBallSet);
718 
719 
720  std::string nameQuad;
721  Board3D<Space, KSpace>::myQuadSetNameList.push_back(nameQuad);
722 
723  std::string nameTriangle;
724  Board3D<Space, KSpace>::myTriangleSetNameList.push_back(nameTriangle);
725 
726  std::string namePolygon;
727  Board3D<Space, KSpace>::myPolygonSetNameList.push_back(namePolygon);
728 }
729 ///////////////////////////////////////////////////////////////////////////////
730 template < typename Space, typename KSpace>
731 inline
732 unsigned int
733 DGtal::Board3D<Space, KSpace>::getMaterialIndex(const DGtal::Color &aColor)
734 {
735  std::map<DGtal::Color, unsigned int>::iterator it;
736 
737  it = myMaterialMap.find(aColor);
738 
739  //The material exists
740  if (it != myMaterialMap.end())
741  return it->second;
742 
743  myMaterialMap.insert( std::pair<DGtal::Color,unsigned int>(aColor,myMaterialIndex) );
744  std::stringstream matName ;
745  matName << "Mat_" <<myMaterialIndex;
746  myMTLBuffer << "newmtl " << matName.str() <<"\n";
747  myMTLBuffer << "Ka " << aColor.red()/255.0 << " " << aColor.green()/255.0 << " " << aColor.blue()/255.0 << "\n";
748  myMTLBuffer << "Kd " << aColor.red()/255.0 << " " << aColor.green()/255.0 << " " << aColor.blue()/255.0 << "\n";
749  myMTLBuffer << "Ks 0 0 0" << "\n";
750  myMTLBuffer << "d " << aColor.alpha()/255.0 << "\n";
751  myMTLBuffer << "illum 2" << std::endl << "\n";
752 
753  myMaterialIndex++;
754  return (myMaterialIndex - 1);
755 }
756 
757 
758 // //
759 ///////////////////////////////////////////////////////////////////////////////