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