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>
50 using namespace DGtal;
98 template <
typename Space = DGtal::Z3i::Space,
typename KSpace = DGtal::Z3i::KSpace>
99 struct Viewer3DImageSpec:
public DGtal::Viewer3D <Space, KSpace>
101 Viewer3DImageSpec(Z2i::RealPoint pup, Z2i::RealPoint plow): myZScale(1.0), myZposClipping(10.0),
102 myPUpper(pup), myPLower(plow){
103 DGtal::Viewer3D<>::update();
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 " );
119 double myZposClipping;
120 Z2i::RealPoint myPUpper, myPLower;
122 virtual void draw ( ){
123 DGtal::Viewer3D<>::draw();
125 glMultMatrixd ( DGtal::Viewer3D<>::manipulatedFrame()->matrix() );
127 glScalef(1.0, 1.0, myZScale);
128 glEnable( GL_LIGHTING );
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 );
140 virtual void keyPressEvent ( QKeyEvent *e ){
141 bool handled =
false;
142 if( e->key() == Qt::Key_Up){
143 if((e->modifiers() & Qt::MetaModifier)){
149 DGtal::Viewer3D<>::update();
152 if( e->key() == Qt::Key_Down){
153 if((e->modifiers() & Qt::MetaModifier)){
159 DGtal::Viewer3D<>::update();
163 if( e->key() == Qt::Key_Plus){
165 DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
166 DGtal::Viewer3D<Space, KSpace>::update();
169 if( e->key() == Qt::Key_Minus){
171 DGtal::Viewer3D<Space, KSpace>::setGLScale(1.0, 1.0, myZScale);
172 DGtal::Viewer3D<>::update();
176 DGtal::Viewer3D<>::keyPressEvent ( e );
181 template<
typename TImage2D,
typename TPo
int3D >
182 struct Image3DPredicatFrom2DImage{
183 typedef TPoint3D Point3D;
187 Image3DPredicatFrom2DImage(DGtal::ConstAlias<TImage2D> anImage,
double aScale):myImageRef(anImage),
191 bool operator()(
const Point3D &aPoint)
const {
192 functors::Projector<SpaceND<2, typename TImage2D::Integer> > projXY;
193 return (*myImageRef)(projXY(aPoint))*myScale >= aPoint[2];
195 CountedConstPtrOrConstPtr<TImage2D> myImageRef;
206 int main(
int argc,
char** argv )
211 std::string inputFileName;
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");
217 app.add_option(
"-i,--input,1", inputFileName,
"2d input image representing the height map (given as grayscape image cast into 8 bits)." )
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).");
226 app.get_formatter()->column_width(40);
227 CLI11_PARSE(app, argc, argv);
231 typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned char> Image2DG ;
232 typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned int> Image2DCol ;
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;
239 if(colorTextureImage !=
""){
240 imageTexture = GenericReader<Image2DCol>::import( colorTextureImage );
243 QApplication application(argc,argv);
244 Z2i::RealPoint plow (image.domain().lowerBound()[0]-0.5,
245 image.domain().lowerBound()[1]-0.5);
247 Z2i::RealPoint pup (image.domain().upperBound()[0]+0.5,
248 image.domain().upperBound()[1]+0.5);
250 Viewer3DImageSpec<> viewer(plow, pup) ;
251 viewer.setWindowTitle(
"Height Map Viewer");
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;
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());
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));
275 viewer.setFillColor(gradientShade(val));
276 }
else if (colorTextureImage !=
"") {
277 viewer.setFillColor(Color(imageTexture(proj(pt))));
279 viewer.setFillColor(grayShade(val));
284 viewer << Viewer3D<>::updateDisplay;
285 return application.exec();