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();