33 #include "DGtal/base/Common.h"    34 #include "DGtal/base/BasicFunctors.h"    35 #include "DGtal/helpers/StdDefs.h"    36 #include "DGtal/io/readers/GenericReader.h"    37 #include "DGtal/io/viewers/Viewer3D.h"    38 #include <DGtal/io/colormaps/GradientColorMap.h>    39 #include <DGtal/io/colormaps/GrayscaleColorMap.h>    40 #include <DGtal/images/ImageContainerBySTLVector.h>    42 #include "DGtal/io/Color.h"    44 #include <DGtal/base/ConstAlias.h>    45 #include <DGtal/kernel/BasicPointFunctors.h>    46 #include <DGtal/topology/helpers/Surfaces.h>    47 #include <DGtal/io/colormaps/GradientColorMap.h>    49 #include <boost/program_options/options_description.hpp>    50 #include <boost/program_options/parsers.hpp>    51 #include <boost/program_options/variables_map.hpp>    54 using namespace DGtal;
    58 namespace po = boost::program_options;
   101 template < 
typename Space = DGtal::Z3i::Space, 
typename KSpace = DGtal::Z3i::KSpace>
   102 struct Viewer3DImageSpec: 
public DGtal::Viewer3D <Space, KSpace>
   104   Viewer3DImageSpec(Z2i::RealPoint pup, Z2i::RealPoint plow): myZScale(1.0), myZposClipping(10.0),
   105                                                               myPUpper(pup), myPLower(plow){
   106     DGtal::Viewer3D<>::update();
   111    DGtal::Viewer3D<>::init();
   112    QGLViewer::setKeyDescription ( Qt::Key_Up, 
"Move Up the cutting plane in the Z axis direction." );
   113    QGLViewer::setKeyDescription ( Qt::Key_Down, 
"Move Down the cutting plane in the Z axis direction." );
   114    QGLViewer::setKeyDescription ( Qt::Key_Shift, 
"Change the cutting plane move with step 1 (5 by default)" );
   115    QGLViewer::setKeyDescription ( Qt::Key_Plus, 
"Increase the openGL scale by 0.25 " );
   116    QGLViewer::setKeyDescription ( Qt::Key_Minus, 
"Decrease the openGL scale by 0.25 " );
   122   double myZposClipping;
   123   Z2i::RealPoint myPUpper, myPLower;
   125   virtual void draw (  ){
   126     DGtal::Viewer3D<>::draw();
   128     glMultMatrixd ( DGtal::Viewer3D<>::manipulatedFrame()->matrix() );
   130     glScalef(1.0, 1.0, myZScale);
   131     glEnable( GL_LIGHTING );
   133     glColor4ub( 50, 50, 240,  150 );
   134     glNormal3f( 0, 0 , 1.0 );
   135     glVertex3f( myPLower[0], myPLower[1] , myZposClipping );
   136     glVertex3f( myPUpper[0], myPLower[1] , myZposClipping );
   137     glVertex3f( myPUpper[0], myPUpper[1], myZposClipping );
   138     glVertex3f( myPLower[0], myPUpper[1],  myZposClipping );
   143   virtual void keyPressEvent ( QKeyEvent *e ){
   144     bool handled = 
false;
   145     if( e->key() == Qt::Key_Up){
   146       if((e->modifiers() & Qt::MetaModifier)){
   152       DGtal::Viewer3D<>::update();
   155     if( e->key() == Qt::Key_Down){
   156       if((e->modifiers() & Qt::MetaModifier)){
   162       DGtal::Viewer3D<>::update();
   166     if( e->key() == Qt::Key_Plus){
   168       DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
   169       DGtal::Viewer3D<Space, KSpace>::update();
   172     if( e->key() == Qt::Key_Minus){
   174       DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
   175       DGtal::Viewer3D<>::update();
   179       DGtal::Viewer3D<>::keyPressEvent ( e );
   187 template<
typename TImage2D, 
typename TPo
int3D >
   188 struct Image3DPredicatFrom2DImage{
   189   typedef  TPoint3D Point3D;
   193   Image3DPredicatFrom2DImage(DGtal::ConstAlias<TImage2D> anImage, 
double aScale):myImageRef(anImage),
   197   bool operator()(
const Point3D &aPoint)
  const {
   198     functors::Projector<SpaceND<2, typename TImage2D::Integer> > projXY;
   199     return  (*myImageRef)(projXY(aPoint))*myScale >= aPoint[2];
   201   CountedConstPtrOrConstPtr<TImage2D> myImageRef;
   212 int main( 
int argc, 
char** argv )
   215   po::options_description general_opt(
"Allowed options are: ");
   216   general_opt.add_options()
   217     (
"help,h", 
"display this message")
   218     (
"scale,s", po::value<double>()->default_value(1.0), 
"set the scale of the maximal level. (default 1.0)")
   219     (
"colorMap,c", 
"define the heightmap color with a pre-defined colormap (GradientColorMap)")
   220     (
"colorTextureImage,t",po::value<std::string>(),  
"define the heightmap color from a given color image (32 bits image).")
   221     (
"input-file,i", po::value<std::string>(), 
"2d input image representing the height map (given as grayscape image cast into 8 bits)." );
   224   po::variables_map vm;
   226     po::store(po::parse_command_line(argc, argv, general_opt), vm);
   227   }
catch(
const std::exception& ex){
   229     trace.info()<< 
"Error checking program options: "<< ex.what()<< endl;
   232   if( !parseOK || vm.count(
"help")||argc<=1)
   234       std::cout << 
"Usage: " << argv[0] << 
" [input-file]\n"   235                 << 
"Displays 2D image as heightmap by using QGLviewer. "<< endl
   236                 << general_opt << 
"\n" <<
   237                 "Exemple of use:  visualisation/3dHeightMapViewer -i ${DGtal}/examples/samples/church.pgm -s 0.2" << std::endl;
   242   if(! vm.count(
"input-file"))
   244       trace.error() << 
" The file name was defined" << endl;
   249   string inputFilename = vm[
"input-file"].as<std::string>();
   250   double scale = vm[
"scale"].as<
double>();
   253   typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned char> Image2DG ;
   254   typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned int> Image2DCol ;
   256   Image2DG image = GenericReader<Image2DG>::import( inputFilename );
   257   Image2DCol imageTexture(image.domain());
   258   int maxHeight = (int)(std::numeric_limits<Image2DG::Value>::max()*scale);
   259   trace.info()<< 
"Max height from scale:" << maxHeight << std::endl;
   261   if(vm.count(
"colorTextureImage")){
   262     imageTexture =  GenericReader<Image2DCol>::import( vm[
"colorTextureImage"].as<std::string>() );
   265   QApplication application(argc,argv);
   266   Z2i::RealPoint plow (image.domain().lowerBound()[0]-0.5,
   267                        image.domain().lowerBound()[1]-0.5);
   269   Z2i::RealPoint pup (image.domain().upperBound()[0]+0.5,
   270                       image.domain().upperBound()[1]+0.5);
   272   Viewer3DImageSpec<> viewer(plow, pup) ;
   273   viewer.setWindowTitle(
"Height Map Viewer");
   278   K.init(Z3i::Point(0,0,0),Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1), 
true);
   279   std::set<KSpace::SCell> boundVect;
   280   Image3DPredicatFrom2DImage<Image2DG, Z3i::Point> image3Dpredicate(image, scale);
   281   trace.info() << 
"Constructing boundary... ";
   282   Surfaces<KSpace>::sMakeBoundary (boundVect, K, image3Dpredicate, Z3i::Point(0,0,0),
   283                                    Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1)  );
   284   trace.info() << 
"[done]"<< std::endl;
   286   viewer << SetMode3D((*(boundVect.begin())).className(), 
"Basic" );
   287   GradientColorMap<Image2DG::Value,CMAP_JET>  gradientShade( 0, std::numeric_limits<Image2DG::Value>::max());
   288   GrayscaleColorMap<Image2DG::Value>  grayShade(0, std::numeric_limits<Image2DG::Value>::max());
   291   for(std::set<KSpace::SCell>::const_iterator it = boundVect.begin();
   292       it!= boundVect.end(); it++){
   293     Z3i::Point pt = K.sCoords(K.sDirectIncident( *it, 2 ));
   294     functors::Projector<SpaceND<2,int> > proj;
   295     Image2DG::Value val = image(proj(pt));
   296     if(vm.count(
"colorMap")){
   297       viewer.setFillColor(gradientShade(val));
   298     }
else if (vm.count(
"colorTextureImage")) {
   299       viewer.setFillColor(Color(imageTexture(proj(pt))));
   301       viewer.setFillColor(grayShade(val));
   306   viewer << Viewer3D<>::updateDisplay;
   307   return application.exec();