DGtal 1.4.0
Loading...
Searching...
No Matches
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 **/
50template < typename Space, typename KSpace>
51inline
52DGtal::Board3D<Space, KSpace> &
53DGtal::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 */
68template < typename Space, typename KSpace>
69template <typename TDrawableWithDisplay3D>
70inline
71DGtal::Board3D<Space, KSpace> &
72DGtal::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 */
88template < typename Space, typename KSpace>
89inline
90DGtal::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 */
102template < typename Space, typename KSpace>
103inline
104void
105DGtal::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 */
114template < typename Space, typename KSpace>
115bool
116DGtal::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 */
126template < typename Space, typename KSpace>
127inline
128void 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
696template < typename Space, typename KSpace>
697inline
698void
699DGtal::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///////////////////////////////////////////////////////////////////////////////
730template < typename Space, typename KSpace>
731inline
732unsigned int
733DGtal::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///////////////////////////////////////////////////////////////////////////////