DGtalTools  0.9.4
3dHeightMapViewer.cpp
1 
29 #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 #include <boost/program_options/options_description.hpp>
50 #include <boost/program_options/parsers.hpp>
51 #include <boost/program_options/variables_map.hpp>
52 
53 using namespace std;
54 using namespace DGtal;
55 using namespace Z3i;
56 
58 namespace po = boost::program_options;
59 
60 
101 template < typename Space = DGtal::Z3i::Space, typename KSpace = DGtal::Z3i::KSpace>
102 struct Viewer3DImageSpec: public DGtal::Viewer3D <Space, KSpace>
103 {
104  Viewer3DImageSpec(Z2i::RealPoint pup, Z2i::RealPoint plow): myZScale(1.0), myZposClipping(10.0),
105  myPUpper(pup), myPLower(plow){
107  };
108 
109 virtual void
110 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 " );
117 };
118 
119 
120 protected:
121  double myZScale;
122  double myZposClipping;
123  Z2i::RealPoint myPUpper, myPLower;
124 
125  virtual void draw ( ){
127  glPushMatrix();
128  glMultMatrixd ( DGtal::Viewer3D<>::manipulatedFrame()->matrix() );
129  glPushMatrix();
130  glScalef(1.0, 1.0, myZScale);
131  glEnable( GL_LIGHTING );
132  glBegin( GL_QUADS );
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 );
139  glEnd();
140  glPopMatrix();
141  glPopMatrix();
142  }
143  virtual void keyPressEvent ( QKeyEvent *e ){
144  bool handled = false;
145  if( e->key() == Qt::Key_Up){
146  if((e->modifiers() & Qt::MetaModifier)){
147  myZposClipping+=1;
148  }else{
149  myZposClipping+=5;
150  }
151 
153  handled=true;
154  }
155  if( e->key() == Qt::Key_Down){
156  if((e->modifiers() & Qt::MetaModifier)){
157  myZposClipping-=1;
158  }else{
159  myZposClipping-=5;
160  }
161 
163  handled=true;
164  }
165 
166  if( e->key() == Qt::Key_Plus){
167  myZScale+=0.25;
168  DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
170  handled=true;
171  }
172  if( e->key() == Qt::Key_Minus){
173  myZScale-=0.25;
174  DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
176  handled=true;
177  }
178  if ( !handled )
180  }
181 };
182 
183 
184 
185 
186 // Defining a Helper to get the 3D point functor from an 2DImage
187 template<typename TImage2D, typename TPoint3D >
188 struct Image3DPredicatFrom2DImage{
189  typedef TPoint3D Point3D;
193  Image3DPredicatFrom2DImage(DGtal::ConstAlias<TImage2D> anImage, double aScale):myImageRef(anImage),
194  myScale(aScale){
195  }
196  inline
197  bool operator()(const Point3D &aPoint) const {
199  return (*myImageRef)(projXY(aPoint))*myScale >= aPoint[2];
200  }
202  double myScale;
203 };
204 
205 
206 
207 
208 
209 
210 
211 
212 int main( int argc, char** argv )
213 {
214  // parse command line ----------------------------------------------
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)." );
222 
223  bool parseOK=true;
224  po::variables_map vm;
225  try{
226  po::store(po::parse_command_line(argc, argv, general_opt), vm);
227  }catch(const std::exception& ex){
228  parseOK=false;
229  trace.info()<< "Error checking program options: "<< ex.what()<< endl;
230  }
231  po::notify(vm);
232  if( !parseOK || vm.count("help")||argc<=1)
233  {
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;
238 
239  return 0;
240  }
241 
242  if(! vm.count("input-file"))
243  {
244  trace.error() << " The file name was defined" << endl;
245  return 0;
246  }
247 
248 
249  string inputFilename = vm["input-file"].as<std::string>();
250  double scale = vm["scale"].as<double>();
251 
252 
255 
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;
260 
261  if(vm.count("colorTextureImage")){
262  imageTexture = GenericReader<Image2DCol>::import( vm["colorTextureImage"].as<std::string>() );
263  }
264 
265  QApplication application(argc,argv);
266  Z2i::RealPoint plow (image.domain().lowerBound()[0]-0.5,
267  image.domain().lowerBound()[1]-0.5);
268 
269  Z2i::RealPoint pup (image.domain().upperBound()[0]+0.5,
270  image.domain().upperBound()[1]+0.5);
271 
272  Viewer3DImageSpec<> viewer(plow, pup) ;
273  viewer.setWindowTitle("Height Map Viewer");
274  viewer.show();
275 
276 
277  KSpace K;
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;
285 
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());
289 
290 
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 ));
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))));
300  }else{
301  viewer.setFillColor(grayShade(val));
302  }
303  viewer << *it;
304  }
305 
306  viewer << Viewer3D<>::updateDisplay;
307  return application.exec();
308 }
STL namespace.
SCell sDirectIncident(const SCell &p, Dimension k) const
virtual void draw()
bool init(const Point &lower, const Point &upper, bool isClosed)
Point sCoords(const SCell &c) const
Trace trace(traceWriterTerm)
std::ostream & info()
virtual void keyPressEvent(QKeyEvent *e)
std::ostream & error()
void setGLScale(float sx, float sy, float sz)
virtual void init()