DGtalTools 2.1.0
Loading...
Searching...
No Matches
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/PolyscopeViewer.h"
38#include <DGtal/images/ImageContainerBySTLVector.h>
39
40#include "DGtal/io/Color.h"
41#include "DGtal/images/ImageLinearCellEmbedder.h"
42#include "DGtal/images/ImageSelector.h"
43#include <DGtal/base/ConstAlias.h>
44#include <DGtal/kernel/BasicPointFunctors.h>
45#include <DGtal/topology/helpers/Surfaces.h>
46#include <DGtal/io/colormaps/GradientColorMap.h>
47#include <DGtal/io/colormaps/GrayscaleColorMap.h>
48#include <DGtal/topology/SetOfSurfels.h>
49#include <DGtal/topology/DigitalSurface.h>
50#include "DGtal/shapes/TriangulatedSurface.h"
51#include "DGtal/shapes/MeshHelpers.h"
52
53using namespace std;
54using namespace DGtal;
55using namespace Z3i;
56
57#include "CLI11.hpp"
58
59
60
104static int posSliceZ = 0;
105static int maxPosSliceZ = 0;
106static Z2i::Point imagePtInf;
107static Z2i::Point imagePtSup;
108static float startTime = 0.0;
109static bool showText = true;
110static bool show_ui = false;
111static string message = "Press W to display interface";
112
113// Defining a Helper to get the 3D point functor from an 2DImage
114template<typename TImage2D, typename TPoint3D >
115struct Image3DPredicatFrom2DImage{
116 typedef TPoint3D Point3D;
120 Image3DPredicatFrom2DImage(DGtal::ConstAlias<TImage2D> anImage, double aScale):myImageRef(anImage),
121 myScale(aScale){
122 }
123 inline
124 bool operator()(const Point3D &aPoint) const {
125 functors::Projector<SpaceND<2, typename TImage2D::Integer> > projXY;
126 return (*myImageRef)(projXY(aPoint))*myScale >= aPoint[2];
127 }
128 CountedConstPtrOrConstPtr<TImage2D> myImageRef;
129 double myScale;
130};
131
132
133
134polyscope::SurfaceMesh *
135initSlice(string name, const Z2i::Point &ptLow, const Z2i::Point &ptUp) {
136 polyscope::SurfaceMesh * res;
137 std::vector<glm::vec3> vertices = {{ptLow[0], ptLow[1], 0},
138 {ptUp[0], ptLow[1], 0},
139 {ptUp[0], ptUp[1], 0},
140 {ptLow[0], ptUp[1], 0}};
141
142 std::vector<std::vector<size_t>> faces = {{0, 1, 2, 3}};
143 res = polyscope::registerSurfaceMesh(name, vertices, faces);
144 res->setSurfaceColor({0.2, 0.2, .9});
145 res->setTransparency(0.5);
146 return res;
147}
148void updateSlice(string name, const Z2i::Point &ptLow, const Z2i::Point &ptUp){
149 polyscope::SurfaceMesh * sm = polyscope::getSurfaceMesh(name);
150 std::vector<glm::vec3> vertices = {{ptLow[0], ptLow[1], posSliceZ},
151 {ptUp[0], ptLow[1], posSliceZ},
152 {ptUp[0], ptUp[1], posSliceZ},
153 {ptLow[0], ptUp[1], posSliceZ}};
154 sm->updateVertexPositions(vertices);
155 stringstream ss; ss << "Slice position: "; ss << posSliceZ;
156 message = ss.str();
157 startTime = ImGui::GetTime();
158 showText = true;
159
160}
161
162
163void callbackFaceID() {
164 ImGuiIO& io = ImGui::GetIO();
165 if (ImGui::IsKeyPressed(ImGuiKey_W))
166 {
167 show_ui = !show_ui;
168 }
169 if (ImGui::IsKeyPressed(ImGuiKey_UpArrow))
170 {
171 if (posSliceZ <= maxPosSliceZ) {
172 posSliceZ++;
173 updateSlice("sliceplane", imagePtInf, imagePtSup);
174 }
175 }
176 if (ImGui::IsKeyPressed(ImGuiKey_DownArrow))
177 {
178 if (posSliceZ > 0) {
179 posSliceZ--;
180 updateSlice("sliceplane", imagePtInf, imagePtSup);
181 }
182 }
183
184
185 if (show_ui){
186 float totalWidth = ImGui::GetContentRegionAvail().x;
187 float sliderWidth = (totalWidth - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
188 ImGui::Begin("Editing tools");
189 ImGui::Text("Slice positio, :");
190 ImGui::PushItemWidth(sliderWidth);
191 if (ImGui::SliderInt("##z axis", &posSliceZ, 0,
192 maxPosSliceZ, "slice %i"))
193 {
194 updateSlice("sliceplane", imagePtInf, imagePtSup);
195 }
196 ImGui::SameLine();
197
198 ImGui::PopItemWidth();
199 ImGui::Separator();
200 ImGui::Text("Polyscope interface:");
201
202 if (ImGui::Button("show "))
203 {
204 polyscope::options::buildGui=true;
205 }
206 ImGui::SameLine();
207 if (ImGui::Button("hide"))
208 {
209 polyscope::options::buildGui=false;
210 }
211 ImGui::Separator();
212 ImGui::Text("Keys:");
213 ImGui::Text("UP/DOWN arrow : Move slice");
214 ImGui::Text("W: Hide/Show this panel");
215
216 ImGui::End();
217 }
218
219 if (showText)
220 {
221 ImVec2 pos(20, 20);
222 ImDrawList* drawList = ImGui::GetBackgroundDrawList();
223 drawList->AddText(pos, IM_COL32(25, 25, 255, 255), message.c_str());
224 if (ImGui::GetTime() - startTime > 10.0 )
225 {
226 showText = false;
227 }
228
229 }
230}
231
232typedef ImageSelector < Domain, int>::Type Image;
233
234
235
236int main( int argc, char** argv )
237{
238
239 // parse command line using CLI ----------------------------------------------
240 CLI::App app;
241 std::string inputFileName;
242 double scale {1.0};
243 bool colorMap {false};
244 std::string colorTextureImage;
245 app.description("Displays 2D image as heightmap by using QGLviewer.\n Exemple of use: visualisation/3dHeightMapViewer ${DGtal}/examples/samples/church.pgm -s 0.2");
246
247 app.add_option("-i,--input,1", inputFileName, "2d input image representing the height map (given as grayscape image cast into 8 bits)." )
248 ->required()
249 ->check(CLI::ExistingFile);
250 app.add_option("--scale,-s",scale, "set the scale of the maximal level. (default 1.0)");
251 app.add_flag("--colorMap,-c", colorMap, "define the heightmap color with a pre-defined colormap (GradientColorMap)");
252 app.add_option("--colorTextureImage,-t", colorTextureImage, "define the heightmap color from a given color image (32 bits image).");
253
254
255
256 app.get_formatter()->column_width(40);
257 CLI11_PARSE(app, argc, argv);
258 // END parse command line using CLI ----------------------------------------------
259
260
261 typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned char> Image2DG ;
262 typedef DGtal::ImageContainerBySTLVector<Z2i::Domain, unsigned int> Image2DCol ;
263
264 Image2DG image = GenericReader<Image2DG>::import( inputFileName );
265 Image2DCol imageTexture(image.domain());
266 Image2DG::Value maxHeight = *std::max_element(image.begin(), image.end()) * scale;
267 trace.info()<< "Max height from scale:" << maxHeight << std::endl;
268 GradientColorMap<Image2DG::Value,CMAP_JET> gradientShade( 0, std::numeric_limits<Image2DG::Value>::max());
269 GrayscaleColorMap<Image2DG::Value> grayShade(0, std::numeric_limits<Image2DG::Value>::max());
270
271 if(colorTextureImage != ""){
272 imageTexture = GenericReader<Image2DCol>::import( colorTextureImage );
273 }
274
275 imagePtInf = Z2i::Point(image.domain().lowerBound()[0],
276 image.domain().lowerBound()[1]);
277
278 imagePtSup = Z2i::Point(image.domain().upperBound()[0],
279 image.domain().upperBound()[1]);
280 maxPosSliceZ = maxHeight;
281
282 stringstream s;
283 s << "3dHeightMapViewer - DGtalTools: ";
284 string name = inputFileName.substr(inputFileName.find_last_of("/")+1,inputFileName.size()) ;
285 s << " " << name << " (W key to display settings)";
286 polyscope::options::programName = s.str();
287 polyscope::options::buildGui=false;
288 polyscope::options::groundPlaneMode = polyscope::GroundPlaneMode::None;
289 polyscope::view::setNavigateStyle(polyscope::NavigateStyle::Free);
290
291 PolyscopeViewer viewer;
292 bool intAdjacency = true;
293 polyscope::SurfaceMesh *slicePlane;
294 typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
295 typedef KSpace::SurfelSet SurfelSet;
296 typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
297 typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;
298
299 typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
300 MySurfelAdjacency surfAdj( intAdjacency ); // interior in all directions.
301
302
303 KSpace K;
304 K.init(Z3i::Point(0,0,0),Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1), true);
305 SurfelSet boundVect;
306 Image3DPredicatFrom2DImage<Image2DG, Z3i::Point> image3Dpredicate(image, scale);
307 trace.info() << "Constructing boundary... ";
308 MySetOfSurfels theSetOfSurfels( K, surfAdj );
309
310 Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
311 K, image3Dpredicate, Z3i::Point(0,0,0),
312 Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1) );
313 trace.info() << "[done]"<< std::endl;
314
315 MyDigitalSurface digSurf( theSetOfSurfels );
316 trace.info() << "Digital surface has " << digSurf.size() << " surfels."
317 << std::endl;
318
319 trace.beginBlock( "Making triangulated surface. " );
320 typedef CanonicEmbedder< Space > TrivialEmbedder;
321 typedef ImageLinearCellEmbedder< KSpace,Image , TrivialEmbedder > CellEmbedder;
322 typedef CellEmbedder::Value RealPoint;
323 typedef TriangulatedSurface< RealPoint > TriMesh;
324 typedef Mesh< RealPoint > ViewMesh;
325 typedef std::map< MyDigitalSurface::Vertex, TriMesh::Index > VertexMap;
326 TriMesh trimesh;
327 ViewMesh viewmesh;
328 TrivialEmbedder trivialEmbedder;
329 CellEmbedder cellEmbedder;
330 Image::Domain d (Z3i::Point(0,0,0),Z3i::Point(image.domain().upperBound()[0], image.domain().upperBound()[1], maxHeight+1));
331 Image imageE(d);
332 for (auto p : imageE.domain()){
333 imageE.setValue(p, image3Dpredicate(p));
334 }
335 cellEmbedder.init(K, imageE, trivialEmbedder, 0);
336 VertexMap vmap;
337 MeshHelpers::digitalSurface2DualTriangulatedSurface
338 ( digSurf, cellEmbedder, trimesh, vmap );
339 MeshHelpers::triangulatedSurface2Mesh( trimesh, viewmesh );
340 trace.info() << "Mesh has " << viewmesh.nbVertex()
341 << " vertices and " << viewmesh.nbFaces() << " faces." << std::endl;
342 trace.endBlock();
343 for (unsigned int i = 0; i < viewmesh.nbFaces(); i++){
344 auto b = viewmesh.getFaceBarycenter(i);
345 auto bp = Z2i::Point(b[0], b[1]);
346 auto val = image(bp);
347 if (image.domain().isInside(bp)){
348 if(colorMap){
349 viewmesh.setFaceColor(i,gradientShade(val));
350 }else if (colorTextureImage != "") {
351 viewmesh.setFaceColor(i, DGtal::Color(imageTexture(bp)));
352 }else{
353 viewmesh.setFaceColor(i, grayShade(val));
354 }
355
356 }
357 }
358 slicePlane = initSlice("sliceplane", image.domain().lowerBound(), image.domain().upperBound());
359
360 viewer.drawColor(Color(150,0,0,254));
361 viewer << viewmesh;
362 polyscope::state::userCallback = callbackFaceID;
363 viewer.show();
364 return 0;
365}
366
Definition ATu0v1.h:57