DGtalTools 2.0.0
Loading...
Searching...
No Matches
3dImageViewer.cpp
1
30#include <iostream>
31
32#include "DGtal/base/Common.h"
33#include "DGtal/base/BasicFunctors.h"
34#include "DGtal/helpers/StdDefs.h"
35#include "DGtal/io/readers/VolReader.h"
36#include "DGtal/io/viewers/PolyscopeViewer.h"
37#include "DGtal/io/readers/PointListReader.h"
38#include "DGtal/io/readers/MeshReader.h"
39#include "DGtal/topology/helpers/Surfaces.h"
40#include "DGtal/topology/SurfelAdjacency.h"
41
42#include "DGtal/io/Color.h"
43#include "DGtal/io/colormaps/GradientColorMap.h"
44#include "DGtal/io/readers/GenericReader.h"
45#ifdef DGTAL_WITH_ITK
46#include "DGtal/io/readers/DicomReader.h"
47#endif
48
49#include "DGtal/images/ImageSelector.h"
50
51
52
53// #include "specificClasses/Viewer3DImage.cpp"
54
55#include "CLI11.hpp"
56
57
58
59using namespace std;
60using namespace DGtal;
61using namespace Z3i;
62
63
124enum TypeSlice {SliceX, SliceY, SliceZ};
125
126
127typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
128typedef DGtal::ImageContainerBySTLVector<DGtal::Z3i::Domain, unsigned char > Image3D;
129typedef DGtal::ImageContainerBySTLVector<DGtal::Z2i::Domain, unsigned char > Image2D;
130typedef DGtal::ConstImageAdapter<Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space>,
131Image3D::Value, DGtal::functors::Identity > SliceImageAdapter;
132typedef DGtal::ConstImageAdapter<Image3D, DGtal::Z2i::Domain, DGtal::functors::SliceRotator2D< DGtal::Z3i::Domain >,
133Image3D::Value, DGtal::functors::Identity > MyRotatorSliceImageAdapter;
134static DGtal::Z2i::Domain domain2DX;
135static DGtal::Z2i::Domain domain2DY;
136static DGtal::Z2i::Domain domain2DZ;
137
138const DGtal::functors::Identity identityFunctor{};
139
140static polyscope::SurfaceTextureScalarQuantity* texSliceX = nullptr;
141static polyscope::SurfaceTextureScalarQuantity* texSliceY = nullptr;
142static polyscope::SurfaceTextureScalarQuantity* texSliceZ = nullptr;
143
144static int sliceXNum = 0;
145static int sliceYNum = 0;
146static int sliceZNum = 0;
147static float rotX = 0.0;
148static float rotY = 0.0;
149static float rotZ = 0.0;
150static bool showText = true;
151static double startTime = 0.0;
152static std::string message = "Press W to display interface";
153static TypeSlice mainAxisKeySelect = SliceX;
154static polyscope::SurfaceTextureScalarQuantity* g_qScalarSliceX = nullptr;
155static polyscope::SurfaceTextureScalarQuantity* g_qScalarSliceY = nullptr;
156static polyscope::SurfaceTextureScalarQuantity* g_qScalarSliceZ = nullptr;
157static bool show_ui = false;
158static polyscope::SurfaceTextureScalarQuantity* g_qScalar[] = {g_qScalarSliceX, g_qScalarSliceY, g_qScalarSliceZ};
159Image3D image = Image3D(DGtal::Z3i::Domain());
160DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorX;
161DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorY;
162DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorZ;
163
164polyscope::SurfaceMesh *slicePlaneX;
165polyscope::SurfaceMesh *slicePlaneY;
166polyscope::SurfaceMesh *slicePlaneZ;
167
168
169std::vector<glm::vec3>
170getVertices(const MyRotatorSliceImageAdapter &sliceIm,
171 const Z2i::Point &ptInf, const Z2i::Point &ptSup,
172 const DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> &func){
173 Z2i::Point p0 = ptInf;
174 Z2i::Point p1(ptSup[0], ptInf[1]);
175 Z2i::Point p2 = ptSup;
176 Z2i::Point p3(ptInf[0], ptSup[1]);
177 return {{
178 { func(p0)[0], func(p0)[1],func(p0)[2]},
179 { func(p1)[0], func(p1)[1],func(p1)[2]},
180 { func(p2)[0], func(p2)[1],func(p2)[2]},
181 { func(p3)[0], func(p3)[1],func(p3)[2]}
182 }
183 };
184}
185
186
187
188polyscope::SurfaceMesh *
189initSlices(const MyRotatorSliceImageAdapter &sliceIm, string name, TypeSlice aTypeSlice,
190 const DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> &func) {
191 polyscope::SurfaceMesh * res;
192 auto ptInf = sliceIm.sourceDomainPoint(sliceIm.domain().lowerBound());
193 auto ptSup = sliceIm.sourceDomainPoint(sliceIm.domain().upperBound());
194 auto dim = sliceIm.domain().upperBound() - sliceIm.domain().lowerBound();
195 auto dimX = dim[0];
196 auto dimY = dim[1];
197 auto maxDim = max(dimX, dimY);
198 std::vector<glm::vec3> vertices = getVertices(sliceIm, sliceIm.domain().lowerBound(),
199 sliceIm.domain().upperBound(), func);
200 std::vector<std::vector<size_t>> faces = {{0, 1, 2, 3}};
201 res = polyscope::registerSurfaceMesh(name, vertices, faces);
202 std::vector<glm::vec2> param = {
203 {0.0f, 0.0f},
204 {1.0f, 0.0f},
205 {1.0f, 1.0f},
206 {0.0f, 1.0f}
207 };
208
209 auto qParam = res->addParameterizationQuantity("param", param);
210 std::vector<float> valuesTex;
211 for(unsigned int y = 0; y< dimY; y++)
212 {
213 for(unsigned int x = 0; x< dimX; x++)
214 {
215 valuesTex.push_back(((float)sliceIm(Z2i::Point(x,y))));
216 }
217 }
218
219 float minV = *std::min_element(valuesTex.begin(), valuesTex.end());
220 float maxV = *std::max_element(valuesTex.begin(), valuesTex.end());
221 for (float& v : valuesTex)
222 {
223 v = (v - minV) / (maxV - minV );
224 }
225 g_qScalar[aTypeSlice] = res->addTextureScalarQuantity("tScalar", *qParam, dimX, dimY,
226 valuesTex, polyscope::ImageOrigin::LowerLeft);
227 g_qScalar[aTypeSlice]->setFilterMode(polyscope::FilterMode::Nearest); // change filter for sampling
228 g_qScalar[aTypeSlice]->setEnabled(true);
229 return res;
230}
231
232
233
234void
235updateSlices(const MyRotatorSliceImageAdapter &sliceIm, string name, TypeSlice aTypeSlice,
236 const DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> &func) {
237 polyscope::SurfaceMesh * sm = polyscope::getSurfaceMesh(name);
238 auto ptInf = sliceIm.sourceDomainPoint(sliceIm.domain().lowerBound());
239 auto ptSup = sliceIm.sourceDomainPoint(sliceIm.domain().upperBound());
240 auto dim = sliceIm.domain().upperBound() - sliceIm.domain().lowerBound();
241 auto dimX = dim[0];
242 auto dimY = dim[1];
243 std::vector<float> valuesTex;
244 for(unsigned int y = 0; y< dimY; y++)
245 {
246 for(unsigned int x = 0; x< dimX; x++)
247 {
248 valuesTex.push_back(((float)sliceIm(Z2i::Point(x,y))));
249 }
250 }
251
252 float minV = *std::min_element(valuesTex.begin(), valuesTex.end());
253 float maxV = *std::max_element(valuesTex.begin(), valuesTex.end());
254 for (float& v : valuesTex)
255 {
256 v = (v - minV) / (maxV - minV );
257 }
258 g_qScalar[aTypeSlice] -> updateData(valuesTex);
259 auto nV = getVertices(sliceIm, sliceIm.domain().lowerBound(),
260 sliceIm.domain().upperBound(), func);
261 sm->updateVertexPositions(nV);
262
263}
264
265void callbackFaceID() {
266 ImGuiIO& io = ImGui::GetIO();
267 auto iDom = image.domain();
268 bool needRedisSX = false;
269 bool needRedisSY = false;
270 bool needRedisSZ = false;
271
272 if (ImGui::IsKeyPressed(ImGuiKey_W))
273 {
274 show_ui = !show_ui;
275 }
276 bool updateSlice = false;
277 if (ImGui::IsKeyPressed(ImGuiKey_X))
278 {
279 mainAxisKeySelect = TypeSlice::SliceX;
280 message = "Slice X selected";
281 startTime = ImGui::GetTime();
282 showText = true;
283 }
284 if (ImGui::IsKeyPressed(ImGuiKey_Y))
285 {
286 mainAxisKeySelect = TypeSlice::SliceY;
287 message = "Slice Y selected";
288 startTime = ImGui::GetTime();
289 showText = true;
290 }
291 if (ImGui::IsKeyPressed(ImGuiKey_Z))
292 {
293 mainAxisKeySelect = TypeSlice::SliceZ;
294 message = "Slice Z selected";
295 startTime = ImGui::GetTime();
296 showText = true;
297 }
298
299 if (ImGui::IsKeyPressed(ImGuiKey_UpArrow))
300 {
301 if (mainAxisKeySelect == TypeSlice::SliceX)
302 {
303 if (!io.KeyShift)
304 sliceXNum++;
305 else
306 rotX += 0.01;
307 needRedisSX = true;
308 }
309 if (mainAxisKeySelect == TypeSlice::SliceY)
310 {
311 if (!io.KeyShift)
312 sliceYNum++;
313 else
314 rotY += 0.01;
315 needRedisSY = true;
316 }
317 if (mainAxisKeySelect == TypeSlice::SliceZ)
318 {
319 if (!io.KeyShift)
320 sliceZNum++;
321 else
322 rotZ += 0.01;
323 needRedisSZ = true;
324 }
325 }
326 if (ImGui::IsKeyPressed(ImGuiKey_DownArrow))
327 {
328 if (mainAxisKeySelect == TypeSlice::SliceX)
329 {
330 if (!io.KeyShift)
331 sliceXNum--;
332 else
333 rotX -= 0.01;
334 needRedisSX = true;
335 }
336 if (mainAxisKeySelect == TypeSlice::SliceY)
337 {
338 if (!io.KeyShift)
339 sliceYNum--;
340 else
341 rotY -= 0.01;
342 needRedisSY = true;
343 }
344 if (mainAxisKeySelect == TypeSlice::SliceZ)
345 {
346 if (!io.KeyShift)
347 sliceZNum--;
348 else
349 rotZ -= 0.01;
350 needRedisSZ = true;
351 }
352 }
353
354
355 if (show_ui){
356 float totalWidth = ImGui::GetContentRegionAvail().x;
357 float sliderWidth = (totalWidth - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
358 ImGui::Begin("Editing tools");
359 ImGui::Text("Slice X :");
360 ImGui::PushItemWidth(sliderWidth);
361 if (ImGui::SliderInt("##x axis", &sliceXNum, iDom.lowerBound()[0],
362 iDom.upperBound()[0], "slice X %i"))
363 {
364 needRedisSX = true;
365 }
366 ImGui::SameLine();
367 if (ImGui::SliderFloat("##rotateX", &rotX, 0, 3.14, "angle = %f"))
368 {
369 needRedisSX = true;
370 }
371 ImGui::PopItemWidth();
372 ImGui::PushItemWidth(sliderWidth);
373
374 ImGui::Text("Slice Y :");
375 if (ImGui::SliderInt("##slice y", &sliceYNum, iDom.lowerBound()[1],
376 iDom.upperBound()[1], "slice Y %i"))
377 {
378 needRedisSY = true;
379 }
380 ImGui::SameLine();
381 if (ImGui::SliderFloat("##rotateY", &rotY, 0, 3.14, "angle = %f"))
382 {
383 needRedisSY = true;
384 }
385 ImGui::PopItemWidth();
386 ImGui::PushItemWidth(sliderWidth);
387 ImGui::Text("Slice Z :");
388 if (ImGui::SliderInt("##slice z", &sliceZNum, iDom.lowerBound()[2],
389 iDom.upperBound()[2], "slice Z %i"))
390 {
391 needRedisSZ = true;
392 }
393 ImGui::SameLine();
394 if (ImGui::SliderFloat("##rotateZ", &rotZ, 0, 3.14, "angle = %f"))
395 {
396 needRedisSZ = true;
397 }
398 ImGui::PopItemWidth();
399 ImGui::Separator();
400 ImGui::Text("Polyscope interface:");
401
402 if (ImGui::Button("show "))
403 {
404 polyscope::options::buildGui=true;
405 }
406 ImGui::SameLine();
407 if (ImGui::Button("hide"))
408 {
409 polyscope::options::buildGui=false;
410 }
411 ImGui::Separator();
412 ImGui::Text("Touches:");
413 ImGui::Text("X: select X slice plane");
414 ImGui::Text("Y: select Y slice plane");
415 ImGui::Text("Z: select Z slice plane");
416 ImGui::Text("UP/DOWN arrow : Move selected slice (+SHIFT to rotate)");
417 ImGui::End();
418 }
419 if (needRedisSX)
420 {
421 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorX(0, iDom, sliceXNum, 2, rotX, false );
422 MyRotatorSliceImageAdapter sliceImageX( image, domain2DX, aSliceFunctorX, identityFunctor );
423 updateSlices(sliceImageX, "slicex", TypeSlice::SliceX, aSliceFunctorX);
424 }
425 if (needRedisSY)
426 {
427 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorY(1, iDom, sliceYNum, 2, rotY, false );
428 MyRotatorSliceImageAdapter sliceImageY( image, domain2DY, aSliceFunctorY, identityFunctor );
429 updateSlices(sliceImageY, "slicey", TypeSlice::SliceY, aSliceFunctorY);
430 }
431 if (needRedisSZ)
432 {
433 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorZ(2, iDom, sliceZNum, 0, rotZ, false );
434 MyRotatorSliceImageAdapter sliceImageZ( image, domain2DZ, aSliceFunctorZ, identityFunctor );
435 updateSlices(sliceImageZ, "slicez", TypeSlice::SliceZ, aSliceFunctorZ);
436 }
437 if (showText)
438 {
439 ImVec2 pos(20, 20);
440 ImDrawList* drawList = ImGui::GetBackgroundDrawList();
441 drawList->AddText(pos, IM_COL32(25, 25, 255, 255), message.c_str());
442 if (ImGui::GetTime() - startTime > 10.0 )
443 {
444 showText = false;
445 }
446
447 }
448}
449
450
451
452int main( int argc, char** argv )
453{
454
455
456
457 // parse command line using CLI ----------------------------------------------
458 CLI::App app;
459 std::string inputFileName;
460 std::string inputFileNameSDP;
461 std::string inputFileNameMesh;
462
463 DGtal::int64_t rescaleInputMin {0};
464 DGtal::int64_t rescaleInputMax {255};
465 bool grid {false};
466 bool intergrid {false};
467 bool emptyMode {false};
468 bool displayDigitalSurface {false};
469 bool thresholdImage {false};
470 bool colorizeCC {false};
471 int thresholdMin {0};
472 int thresholdMax {255};
473 std::vector<unsigned int> vectSDPIndex {0,1,2};
474 std::vector<unsigned int> colorSDP;
475 std::vector<unsigned int> colorMesh;
476
477 float sx {1.0};
478 float sy {1.0};
479 float sz {1.0};
480 double ballRadius = {0.0};
481 unsigned char transp {255};
482
483
484 app.description("Displays volume file as a voxel set by using PolyscopeViewer\n 3dImageViewer $DGtal/examples/samples/lobster.vol --thresholdImage -m 180");
485
486 app.add_option("-i,--input,1", inputFileName, "vol file (.vol, .longvol .p3d, .pgm3d and if DGTAL_WITH_ITK is selected: dicom, dcm, mha, mhd). For longvol, dicom, dcm, mha or mhd formats, the input values are linearly scaled between 0 and 255." )
487 ->required()
488 ->check(CLI::ExistingFile);
489
490 app.add_flag("--grid", grid , "draw slice images using grid mode.");
491 app.add_flag("--intergrid", grid , "draw slice images using inter grid mode.");
492 app.add_flag("--emptyMode", emptyMode,"remove the default boundingbox display.");
493 app.add_flag("--thresholdImage", thresholdImage,"threshold the image to define binary shape");
494 app.add_option("--thresholdMin", thresholdMin, "threshold min to define binary shape");
495 app.add_option("--thresholdMax", thresholdMax, "threshold maw to define binary shape");
496 app.add_option("--displaySDP,s",inputFileNameSDP, "display a set of discrete points (.sdp)" );
497 app.add_option("--SDPindex", vectSDPIndex, "specify the sdp index.")
498 ->expected(3);
499 app.add_option("--SDPball",ballRadius, "use balls to display a set of discrete points (if not set to 0 and used with displaySDP option).");
500
501 app.add_option("--displayMesh", inputFileNameMesh, "display a Mesh given in OFF or OFS format.");
502 app.add_flag("--displayDigitalSurface",displayDigitalSurface, "display the digital surface instead of display all the set of voxels (used with thresholdImage or displaySDP options)" );
503
504 app.add_flag("--colorizeCC", colorizeCC, "colorize each Connected Components of the surface displayed by displayDigitalSurface option.");
505 app.add_option("--colorSDP,-c", colorSDP, "set the color discrete points: r g b a ")
506 ->expected(4);
507 app.add_option("--colorMesh", colorMesh, "set the color of Mesh (given from displayMesh option) : r g b a ")
508 ->expected(4);
509
510 app.add_option("--scaleX,-x", sx, "set the scale value in the X direction" );
511 app.add_option("--scaleY,-y", sy, "set the scale value in the Y direction" );
512 app.add_option("--scaleZ,-z", sy, "set the scale value in the Z direction" );
513 app.add_option("--rescaleInputMin",rescaleInputMin, "min value used to rescale the input intensity (to avoid basic cast into 8 bits image)." );
514 app.add_option("--rescaleInputMax",rescaleInputMax, "max value used to rescale the input intensity (to avoid basic cast into 8 bits image)." );
515 app.add_option("--transparency,-t",transp, "change the default transparency" );
516
517
518 app.get_formatter()->column_width(40);
519 CLI11_PARSE(app, argc, argv);
520 // END parse command line using CLI ----------------------------------------------
521 stringstream s;
522 s << "3dImageViewer - DGtalTools: ";
523 string name = inputFileName.substr(inputFileName.find_last_of("/")+1,inputFileName.size()) ;
524 s << " " << name << " (W key to display settings)";
525 polyscope::options::programName = s.str();
526 polyscope::options::buildGui=false;
527 polyscope::options::groundPlaneMode = polyscope::GroundPlaneMode::None;
528 polyscope::view::setNavigateStyle(polyscope::NavigateStyle::Free);
529 PolyscopeViewer<> viewer;
530 string extension = inputFileName.substr(inputFileName.find_last_of(".") + 1);
531 startTime = ImGui::GetTime();
532 invFunctorX.initRemoveOneDim(0);
533 invFunctorY.initRemoveOneDim(1);
534 invFunctorZ.initRemoveOneDim(2);
535
536 image = GenericReader< Image3D >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
537 rescaleInputMax,
538 0,
539 255));
540 Domain domain = image.domain();
541 domain2DX = DGtal::Z2i::Domain(invFunctorX(image.domain().lowerBound()),
542 invFunctorX(image.domain().upperBound()));
543 domain2DY = DGtal::Z2i::Domain(invFunctorY(image.domain().lowerBound()),
544 invFunctorY(image.domain().upperBound()));
545 domain2DZ = DGtal::Z2i::Domain(invFunctorZ(image.domain().lowerBound()),
546 invFunctorZ(image.domain().upperBound()));
547
548 trace.info() << "Image loaded: "<<image<< std::endl;
549
550 // Used to display 3D surface
551 Z3i::DigitalSet set3d(domain);
552
553 if(thresholdImage){
554 viewer.newCubeList("Threshold image");
555 viewer.allowReuseList = true;
556 for(Domain::ConstIterator it = domain.begin(), itend=domain.end(); it!=itend; ++it){
557 unsigned char val= image( (*it) );
558 if(val<=thresholdMax && val >=thresholdMin)
559 {
560 if(!displayDigitalSurface)
561 {
562 viewer << WithQuantity(*it, "value", val);
563 }
564 else
565 {
566 set3d.insert(*it);
567 }
568 }
569 }
570 viewer.endCurrentGroup();
571 }
572
573
574
575 auto myImageOrigin = (image.domain().lowerBound()+image.domain().upperBound())/2.0;
576
577 sliceXNum=myImageOrigin[0];
578 sliceYNum=myImageOrigin[1];
579 sliceZNum=myImageOrigin[2];
580
581 // Adding X slice in the viewer.
582 DGtal::Z2i::Domain domain2DX(invFunctorX(image.domain().lowerBound()),
583 invFunctorX(image.domain().upperBound()));
584 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorX(0, image.domain(), sliceXNum, 2, 0 );
585 const DGtal::functors::Identity identityFunctor{};
586 MyRotatorSliceImageAdapter sliceImageX( image, domain2DX, aSliceFunctorX, identityFunctor );
587 slicePlaneX = initSlices(sliceImageX, "slicex", TypeSlice::SliceX, aSliceFunctorX);
588
589 // Adding Y slice in the viewer.
590 DGtal::Z2i::Domain domain2DY(invFunctorY(image.domain().lowerBound()),
591 invFunctorY(image.domain().upperBound()));
592 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorY(1, image.domain(), sliceYNum, 0, 0 );
593 MyRotatorSliceImageAdapter sliceImageY( image, domain2DY, aSliceFunctorY, identityFunctor );
594 slicePlaneY = initSlices(sliceImageY, "slicey", TypeSlice::SliceY, aSliceFunctorY);
595
596 // Adding Z slice in the viewer.
597 DGtal::Z2i::Domain domain2DZ(invFunctorZ(image.domain().lowerBound()),
598 invFunctorZ(image.domain().upperBound()));
599 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorZ(2, image.domain(), sliceZNum, 1, 0 );
600 MyRotatorSliceImageAdapter sliceImageZ( image, domain2DZ, aSliceFunctorZ, identityFunctor );
601 slicePlaneZ = initSlices(sliceImageZ, "slicez", TypeSlice::SliceZ, aSliceFunctorZ);
602
603 if(inputFileNameSDP != "" )
604 {
605 if(colorSDP.size()==4)
606 {
607 Color c(colorSDP[0], colorSDP[1], colorSDP[2], colorSDP[3]);
608 viewer << c;
609 }
610
611 vector<Z3i::Point> vectVoxels;
612 if(vectSDPIndex.size()==3)
613 {
614 vectVoxels = PointListReader<Z3i::Point>::getPointsFromFile(inputFileNameSDP, vectSDPIndex);
615 }else
616 {
617 vectVoxels = PointListReader<Z3i::Point>::getPointsFromFile(inputFileNameSDP);
618 }
619
620 if (ballRadius != 0.0) viewer.drawAsBalls();
621 for(unsigned int i=0;i< vectVoxels.size(); i++)
622 {
623 if(!displayDigitalSurface)
624 {
625 viewer << vectVoxels.at(i);
626 }
627 else
628 {
629 set3d.insert(vectVoxels.at(i));
630 }
631 }
632 viewer.drawAsPaving();
633 }
634
635 if(inputFileNameMesh != "")
636 {
637 if(colorMesh.size() != 0)
638 {
639 Color c(colorMesh[0], colorMesh[1], colorMesh[2], colorMesh[3]);
640 viewer.drawColor(c);
641 }
642 DGtal::Mesh<Z3i::RealPoint> aMesh(colorMesh.size() == 0);
643 MeshReader<Z3i::RealPoint>::importOFFFile(inputFileNameMesh, aMesh);
644 viewer << aMesh;
645 }
646
647 if(displayDigitalSurface)
648 {
649 KSpace K;
650 Point low = domain.lowerBound(); low[0]=low[0]-1; low[1]=low[1]-1; low[2]=low[2]-1;
651 Point upp = domain.upperBound(); upp[0]=upp[0]+1; upp[1]=upp[1]+1; upp[2]=upp[2]+1;
652 K.init(low, upp , true);
653 SurfelAdjacency<3> SAdj( true );
654 vector<vector<SCell> > vectConnectedSCell;
655 trace.info() << "Extracting surface set ... " ;
656 Surfaces<KSpace>::extractAllConnectedSCell(vectConnectedSCell,K, SAdj, set3d, true);
657 trace.info()<< " [done] " <<std::endl;
658
659 viewer.drawAsSimplified();
660 for(unsigned int i= 0; i <vectConnectedSCell.size(); i++)
661 {
662 for(unsigned int j= 0; j <vectConnectedSCell.at(i).size(); j++)
663 {
664 const auto& toDraw = vectConnectedSCell.at(i).at(j);
665 if(colorizeCC)
666 {
667 viewer << WithQuantity(toDraw, "index", i);
668 }
669 else if(colorSDP.size() != 0)
670 {
671 Color c(colorSDP[0], colorSDP[1], colorSDP[2], colorSDP[3]);
672 viewer << WithQuantity(toDraw, "color", c);
673 }
674 else
675 {
676 viewer << toDraw;
677 }
678 }
679 }
680 }
681
682 DGtal::Z3i::Point size = image.domain().upperBound() - image.domain().lowerBound();
683 DGtal::Z3i::Point center = image.domain().lowerBound()+size/2;
684 unsigned int maxDist = std::max(std::max(size[2], size[1]), size[0]);
685 polyscope::state::userCallback = callbackFaceID;
686
687 viewer.show();
688 return 0;
689}
Definition ATu0v1.h:57