DGtalTools  1.2.0
3dHeightMapViewer.cpp
1 
30 #include <iostream>
31 #include <climits>
32 
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>
41 
42 #include "DGtal/io/Color.h"
43 
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>
48 
49 using namespace std;
50 using namespace DGtal;
51 using namespace Z3i;
52 
53 #include "CLI11.hpp"
54 
55 
56 
98 template < typename Space = DGtal::Z3i::Space, typename KSpace = DGtal::Z3i::KSpace>
99 struct Viewer3DImageSpec: public DGtal::Viewer3D <Space, KSpace>
100 {
101  Viewer3DImageSpec(Z2i::RealPoint pup, Z2i::RealPoint plow): myZScale(1.0), myZposClipping(10.0),
102  myPUpper(pup), myPLower(plow){
103  DGtal::Viewer3D<>::update();
104  };
105 
106 virtual void
107 init(){
108  DGtal::Viewer3D<>::init();
109  QGLViewer::setKeyDescription ( Qt::Key_Up, "Move Up the cutting plane in the Z axis direction." );
110  QGLViewer::setKeyDescription ( Qt::Key_Down, "Move Down the cutting plane in the Z axis direction." );
111  QGLViewer::setKeyDescription ( Qt::Key_Shift, "Change the cutting plane move with step 1 (5 by default)" );
112  QGLViewer::setKeyDescription ( Qt::Key_Plus, "Increase the openGL scale by 0.25 " );
113  QGLViewer::setKeyDescription ( Qt::Key_Minus, "Decrease the openGL scale by 0.25 " );
114 };
115 
116 
117 protected:
118  double myZScale;
119  double myZposClipping;
120  Z2i::RealPoint myPUpper, myPLower;
121 
122  virtual void draw ( ){
123  DGtal::Viewer3D<>::draw();
124  glPushMatrix();
125  glMultMatrixd ( DGtal::Viewer3D<>::manipulatedFrame()->matrix() );
126  glPushMatrix();
127  glScalef(1.0, 1.0, myZScale);
128  glEnable( GL_LIGHTING );
129  glBegin( GL_QUADS );
130  glColor4ub( 50, 50, 240, 150 );
131  glNormal3f( 0, 0 , 1.0 );
132  glVertex3f( myPLower[0], myPLower[1] , myZposClipping );
133  glVertex3f( myPUpper[0], myPLower[1] , myZposClipping );
134  glVertex3f( myPUpper[0], myPUpper[1], myZposClipping );
135  glVertex3f( myPLower[0], myPUpper[1], myZposClipping );
136  glEnd();
137  glPopMatrix();
138  glPopMatrix();
139  }
140  virtual void keyPressEvent ( QKeyEvent *e ){
141  bool handled = false;
142  if( e->key() == Qt::Key_Up){
143  if((e->modifiers() & Qt::MetaModifier)){
144  myZposClipping+=1;
145  }else{
146  myZposClipping+=5;
147  }
148 
149  DGtal::Viewer3D<>::update();
150  handled=true;
151  }
152  if( e->key() == Qt::Key_Down){
153  if((e->modifiers() & Qt::MetaModifier)){
154  myZposClipping-=1;
155  }else{
156  myZposClipping-=5;
157  }
158 
159  DGtal::Viewer3D<>::update();
160  handled=true;
161  }
162 
163  if( e->key() == Qt::Key_Plus){
164  myZScale+=0.25;
165  DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
166  DGtal::Viewer3D<Space, KSpace>::update();
167  handled=true;
168  }
169  if( e->key() == Qt::Key_Minus){
170  myZScale-=0.25;
171  DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
172  DGtal::Viewer3D<>::update();
173  handled=true;
174  }
175  if ( !handled )
176  DGtal::Viewer3D<>::keyPressEvent ( e );
177  }
178 };
179 
180 // Defining a Helper to get the 3D point functor from an 2DImage
181 template<typename TImage2D, typename TPoint3D >
182 struct Image3DPredicatFrom2DImage{
183  typedef TPoint3D Point3D;
187  Image3DPredicatFrom2DImage(DGtal::ConstAlias<TImage2D> anImage, double aScale):myImageRef(anImage),
188  myScale(aScale){
189  }
190  inline
191  bool operator()(const Point3D &aPoint) const {
192  functors::Projector<SpaceND<2, typename TImage2D::Integer> > projXY;
193  return (*myImageRef)(projXY(aPoint))*myScale >= aPoint[2];
194  }
195  CountedConstPtrOrConstPtr<TImage2D> myImageRef;
196  double myScale;
197 };
198 
199 
200 
201 
202 
203 
204 
205 
206 int main( int argc, char** argv )
207 {
208 
209  // parse command line using CLI ----------------------------------------------
210  CLI::App app;
211  std::string inputFileName;
212  double scale {1.0};
213  bool colorMap {false};
214  std::string colorTextureImage;
215  app.description("Displays 2D image as heightmap by using QGLviewer.\n Exemple of use: visualisation/3dHeightMapViewer ${DGtal}/examples/samples/church.pgm -s 0.2");
216 
217  app.add_option("-i,--input,1", inputFileName, "2d input image representing the height map (given as grayscape image cast into 8 bits)." )
218  ->required()
219  ->check(CLI::ExistingFile);
220  app.add_option("--scale,-s",scale, "set the scale of the maximal level. (default 1.0)");
221  app.add_flag("--colorMap,-c", colorMap, "define the heightmap color with a pre-defined colormap (GradientColorMap)");
222  app.add_option("--colorTextureImage,-t", colorTextureImage, "define the heightmap color from a given color image (32 bits image).");
223 
224 
225 
226  app.get_formatter()->column_width(40);
227  CLI11_PARSE(app, argc, argv);
228  // END parse command line using CLI ----------------------------------------------
229 
230 
231  typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned char> Image2DG ;
232  typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned int> Image2DCol ;
233 
234  Image2DG image = GenericReader<Image2DG>::import( inputFileName );
235  Image2DCol imageTexture(image.domain());
236  int maxHeight = (int)(std::numeric_limits<Image2DG::Value>::max()*scale);
237  trace.info()<< "Max height from scale:" << maxHeight << std::endl;
238 
239  if(colorTextureImage != ""){
240  imageTexture = GenericReader<Image2DCol>::import( colorTextureImage );
241  }
242 
243  QApplication application(argc,argv);
244  Z2i::RealPoint plow (image.domain().lowerBound()[0]-0.5,
245  image.domain().lowerBound()[1]-0.5);
246 
247  Z2i::RealPoint pup (image.domain().upperBound()[0]+0.5,
248  image.domain().upperBound()[1]+0.5);
249 
250  Viewer3DImageSpec<> viewer(plow, pup) ;
251  viewer.setWindowTitle("Height Map Viewer");
252  viewer.show();
253 
254 
255  KSpace K;
256  K.init(Z3i::Point(0,0,0),Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1), true);
257  std::set<KSpace::SCell> boundVect;
258  Image3DPredicatFrom2DImage<Image2DG, Z3i::Point> image3Dpredicate(image, scale);
259  trace.info() << "Constructing boundary... ";
260  Surfaces<KSpace>::sMakeBoundary (boundVect, K, image3Dpredicate, Z3i::Point(0,0,0),
261  Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1));
262  trace.info() << "[done]"<< std::endl;
263 
264  viewer << SetMode3D((*(boundVect.begin())).className(), "Basic" );
265  GradientColorMap<Image2DG::Value,CMAP_JET> gradientShade( 0, std::numeric_limits<Image2DG::Value>::max());
266  GrayscaleColorMap<Image2DG::Value> grayShade(0, std::numeric_limits<Image2DG::Value>::max());
267 
268 
269  for(std::set<KSpace::SCell>::const_iterator it = boundVect.begin();
270  it!= boundVect.end(); it++){
271  Z3i::Point pt = K.sCoords(K.sDirectIncident( *it, 2 ));
272  functors::Projector<SpaceND<2,int> > proj;
273  Image2DG::Value val = image(proj(pt));
274  if(colorMap){
275  viewer.setFillColor(gradientShade(val));
276  }else if (colorTextureImage != "") {
277  viewer.setFillColor(Color(imageTexture(proj(pt))));
278  }else{
279  viewer.setFillColor(grayShade(val));
280  }
281  viewer << *it;
282  }
283 
284  viewer << Viewer3D<>::updateDisplay;
285  return application.exec();
286 }
Definition: ATu0v1.h:57