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.
 
    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.
 
   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/>.
 
   19 * @author Martial Tola <http://liris.cnrs.fr/martial.tola/>
 
   20 * @date   mercredi 22 juin 2011
 
   24 * Implementation of inline methods defined in Board3D.h
 
   26 * This file is part of the DGtal library.
 
   29///////////////////////////////////////////////////////////////////////////////
 
   30// IMPLEMENTATION of inline methods.
 
   31///////////////////////////////////////////////////////////////////////////////
 
   33//////////////////////////////////////////////////////////////////////////////
 
   35#include "DGtal/io/CDrawableWithDisplay3D.h"
 
   36#include "DGtal/io/Color.h"
 
   39//////////////////////////////////////////////////////////////////////////////
 
   41///////////////////////////////////////////////////////////////////////////////
 
   42// Implementation of inline methods                                          //
 
   45 * Set the default color for future drawing.
 
   47 * @param aColor a DGtal::Color (allow to set a trasnparency value).
 
   50template < typename Space, typename KSpace>
 
   52DGtal::Board3D<Space, KSpace> &
 
   53DGtal::Board3D<Space, KSpace>::operator<<(const DGtal::Color & aColor)
 
   55  myDefaultColor=aColor;
 
   61 * Draws the drawable [object] in this board. It should satisfy
 
   62 * the concept CDrawableWithBoard3D, which requires for instance a
 
   63 * method setStyle( Board3D & ).
 
   65 * @param object any drawable object.
 
   66 * @return a reference on 'this'.
 
   68template < typename Space, typename KSpace>
 
   69template <typename TDrawableWithDisplay3D>
 
   71DGtal::Board3D<Space, KSpace> &
 
   72DGtal::Board3D<Space, KSpace>::operator<<( const TDrawableWithDisplay3D & object )
 
   74  BOOST_CONCEPT_ASSERT((concepts::CDrawableWithDisplay3D< TDrawableWithDisplay3D, Space, KSpace>));
 
   76  DGtal::Display3DFactory<Space,KSpace>::draw(*this, object);
 
   82///////////////////////////////////////////////////////////////////////////////
 
   83// Standard services - public :
 
   88template < typename Space, typename KSpace>
 
   90DGtal::Board3D<Space, KSpace>::Board3D() : Display3D<Space,KSpace>()
 
   95///////////////////////////////////////////////////////////////////////////////
 
   96// Interface - public :
 
   99 * Writes/Displays the object on an output stream.
 
  100 * @param outOBJ the output stream where the object is written.
 
  102template < typename Space, typename KSpace>
 
  105DGtal::Board3D<Space, KSpace>::selfDisplay ( std::ostream & outOBJ ) const
 
  107  outOBJ << "[Board3D]";
 
  111 * Checks the validity/consistency of the object.
 
  112 * @return 'true' if the object is valid, 'false' otherwise.
 
  114template < typename Space, typename KSpace>
 
  116DGtal::Board3D<Space, KSpace>::isValid() const
 
  124 * @param filename filename of the image to save.
 
  126template < typename Space, typename KSpace>
 
  128void DGtal::Board3D<Space, KSpace>::saveOBJ(const std::string & filename, const bool normalization)
 
  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
 
  135  //the filename without OBJ any extention
 
  137  size_t lastdot = filename.find_last_of(".");
 
  138  if (lastdot != std::string::npos)
 
  139    noExt = filename.substr(0, lastdot);
 
  143  std::stringstream nameOBJ;
 
  144  std::stringstream nameMTL;
 
  145  nameOBJ << noExt << ".obj";
 
  146  nameMTL << noExt << ".mtl";
 
  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";
 
  154  outMTL.open(nameMTL.str().c_str());
 
  155  outMTL << "#  MTL format"<< "\n";
 
  156  outMTL << "# generated from Board3D from the DGtal library"<< "\n";
 
  159  //myClippingPlaneList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  160  //std::vector< clippingPlaneD3D >::const_iterator
 
  162    if(Board3D<Space, KSpace>::myClippingPlaneList.size()> 0)
 
  164      trace.info() << "number of clipping plane : "
 
  165      << Board3D<Space, KSpace>::myClippingPlaneList.size() << std::endl;
 
  169  // normalization -----------------------------------------------------------------------
 
  171  typename Space::RealPoint shift(0.0,0.0,0.0);
 
  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;
 
  178    //We compute the scale of the largest direction so that it fits
 
  179    //in [-1/2,1/2] interval
 
  183    while ((i<3) && (this->myBoundingPtUp[i]  - this->myBoundingPtLow[i] == 0))
 
  185    ASSERT_MSG(i < 3, "Error when computing the scale from the bounding box. The Bbox seems to be empty.");
 
  187    scale = 1.0/(this->myBoundingPtUp[i]  - this->myBoundingPtLow[i]);
 
  190      tmpwidth =  (this->myBoundingPtUp[i]  - this->myBoundingPtLow[i]);
 
  191      if ((tmpwidth != 0.0) && (scale  > 1.0/tmpwidth))
 
  192        scale = 1.0/tmpwidth;
 
  194    outOBJ << "# Normalization was used. Scale= "<< scale << " and Shift= "<<shift<< "\n";
 
  197  // Draw the shapes -----------------------------------------------------------------------
 
  199  ///Temporary variables
 
  200  typename Space::RealPoint apoint, apoint1, apoint2, apoint3, apoint4;
 
  202  // myBallSetList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  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++)
 
  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++)
 
  212        //test if a clipping plane do not cut it
 
  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 )
 
  217          double d2 = ( itClip->a * (*s_it)[0]) + (itClip->b * (*s_it)[1]) + ( itClip->c * (*s_it)[2] ) + itClip->d;
 
  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;
 
  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;
 
  234          for(unsigned int jj =0; jj < phiResolution; jj++)
 
  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++)
 
  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";
 
  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";
 
  262      if (tmpStream.str().size() > 0)
 
  264        std::stringstream name;
 
  265        name << Board3D<Space, KSpace>::myBallSetNameList.at(k);
 
  266        if ( name.str() == "")
 
  268          name << "myBallSetList_" << k ;
 
  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();
 
  283  // myLineSetList+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  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++)
 
  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)
 
  295        //test if a clipping plane do not cut it
 
  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 )
 
  301          double a = itClip->a;
 
  302          double b = itClip->b;
 
  303          double c = itClip->c;
 
  304          double d = itClip->d;
 
  306          d2 = ( a * s_it->point1[0]) + (b * (s_it->point1[1] -width)) + ( c * s_it->point1[2] ) + d;
 
  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) );
 
  328          // OBJ dont know how to draw lines, have to make a
 
  329          // cuboid with a depth and height of a pixel width
 
  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";
 
  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";
 
  343          tmpStream  << "vn " <<  "0"  << " " << "0" << " " << "1" << "\n";//up
 
  344          tmpStream  << "vn " <<  "0"  << " " << "0" << " " << "-1" << "\n";//back
 
  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
 
  356      if (tmpStream.str() != "")
 
  358        std::stringstream name;
 
  359        name << Board3D<Space, KSpace>::myLineSetNameList.at(k);
 
  360        if ( name.str()== "")
 
  362          name << "myLineSetList_" << k ;
 
  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();
 
  378  // myCubeSetList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  380    j  = 0 ; //id of each Cube sub list for the .OBJ identification
 
  384    for(typename Board3D<Space, KSpace>::CubesMap::const_iterator it =Board3D<Space, KSpace>::myCubesMap.begin();
 
  385        it != Board3D<Space, KSpace>::myCubesMap.end();   it++)
 
  388        std::stringstream name;
 
  389        std::ostringstream tmpStream;
 
  391        name << "myCubeSetList_" << it->first ;
 
  392        outOBJ << "o  " << name.str() << "\n";
 
  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
 
  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)
 
  403        unsigned int matid = getMaterialIndex(s_it->color);
 
  404        if (matid != prevMaterialIndex)
 
  406          std::stringstream matName;
 
  407          matName <<  "Mat_" << matid;
 
  408          outOBJ << "usemtl " << matName.str() << "\n";
 
  409          prevMaterialIndex = matid;
 
  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];
 
  423        //test if a clipping plane do not cut it
 
  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 )
 
  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;
 
  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) );
 
  457          // this version is  one cube with (x,y,z) the center of it and wid its distance between it and its faces
 
  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;
 
  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";
 
  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
 
  496  // myQuadList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  498    k = 0; // id of each list
 
  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;
 
  508    for (typename Board3D<Space, KSpace>::QuadsMap::const_iterator it = Board3D<Space, KSpace>::myQuadsMap.begin();
 
  509         it != Board3D<Space, KSpace>::myQuadsMap.end(); it++)
 
  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";
 
  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 ++)
 
  522        if (previousCol != aQuad->color)
 
  524          previousCol = aQuad->color;
 
  526          matid = getMaterialIndex(previousCol);
 
  527          outOBJ << "usemtl Mat_" << matid << "\n";
 
  530        apoint1 = (aQuad->point1 -shift)*scale;
 
  531        apoint2 = (aQuad->point2 -shift)*scale;
 
  532        apoint3 = (aQuad->point3 -shift)*scale;
 
  533        apoint4 = (aQuad->point4 -shift)*scale;
 
  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";
 
  548  // myTriangleList++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  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++)
 
  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)
 
  559        //test if a clipping plane do not cut it
 
  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 )
 
  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;
 
  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) );
 
  580          apoint1 = (s_it->point1 - shift)*scale;
 
  581          apoint2 = (s_it->point2 - shift)*scale;
 
  582          apoint3 = (s_it->point3 - shift)*scale;
 
  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";
 
  589          tmpStream << "vn " << s_it->nx    << " " << s_it->ny     << " " << s_it->nz << "\n";
 
  591          tmpStream << "f " << "-3//-1" << " " << "-2//-1"<< " " << "-1//-1"<< "\n";
 
  595      if (tmpStream.str() != "")
 
  597        std::stringstream name;
 
  598        name << Board3D<Space, KSpace>::myTriangleSetNameList.at(k);
 
  599        if ( name.str() == "")
 
  601          name << "myTriangleSetList_" << k ;
 
  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();
 
  617  // Drawing all Khalimsky Space Cells --------------------------------------------------------------------
 
  619  // Prism (from updateList)+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  623    std::ostringstream tmpStream;
 
  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();
 
  629      //test if a clipping plane do not cut it
 
  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 )
 
  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;
 
  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) );
 
  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;
 
  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";
 
  661        tmpStream << "vn " << s_it->nx    << " " << s_it->ny     << " " << s_it->nz << "\n";
 
  663        tmpStream << "f " << "-4//-1" << " " << "-3//-1" << " " << "-2//-1"<< " " << "-1//-1" << "\n";
 
  668      if (tmpStream.str() != "")
 
  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();
 
  686  //end Prism (from updateList)+++++++++++++++++++++++++++++++
 
  687  outMTL  << myMTLBuffer.str();
 
  696template < typename Space, typename KSpace>
 
  699DGtal::Board3D<Space, KSpace>::init()
 
  704  Board3D<Space, KSpace>::createNewCubeList();
 
  705  Board3D<Space, KSpace>::createNewLineList();
 
  706  Board3D<Space, KSpace>::createNewBallList();
 
  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";
 
  713  std::string nameLineSet;
 
  714  Board3D<Space, KSpace>::myLineSetNameList.push_back(nameLineSet);
 
  716  std::string nameBallSet;
 
  717  Board3D<Space, KSpace>::myBallSetNameList.push_back(nameBallSet);
 
  720  std::string nameQuad;
 
  721  Board3D<Space, KSpace>::myQuadSetNameList.push_back(nameQuad);
 
  723  std::string nameTriangle;
 
  724  Board3D<Space, KSpace>::myTriangleSetNameList.push_back(nameTriangle);
 
  726  std::string namePolygon;
 
  727  Board3D<Space, KSpace>::myPolygonSetNameList.push_back(namePolygon);
 
  729///////////////////////////////////////////////////////////////////////////////
 
  730template < typename Space, typename KSpace>
 
  733DGtal::Board3D<Space, KSpace>::getMaterialIndex(const DGtal::Color &aColor)
 
  735  std::map<DGtal::Color, unsigned int>::iterator it;
 
  737  it = myMaterialMap.find(aColor);
 
  739  //The material exists
 
  740  if (it != myMaterialMap.end())
 
  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";
 
  754  return (myMaterialIndex - 1);
 
  759///////////////////////////////////////////////////////////////////////////////