DGtalTools  1.5.beta
3dSDPViewer.cpp
1 
29 #include <iostream>
30 
31 #include "DGtal/base/Common.h"
32 #include "DGtal/helpers/StdDefs.h"
33 #include "DGtal/io/viewers/Viewer3D.h"
34 #include "DGtal/io/DrawWithDisplay3DModifier.h"
35 #include "DGtal/io/readers/TableReader.h"
36 #include "DGtal/io/readers/PointListReader.h"
37 #include "DGtal/io/readers/MeshReader.h"
38 #include "DGtal/topology/helpers/Surfaces.h"
39 #include "DGtal/topology/SurfelAdjacency.h"
40 #include "DGtal/shapes/Mesh.h"
41 #include "DGtal/io/Color.h"
42 #include "DGtal/io/colormaps/HueShadeColorMap.h"
43 #include "DGtal/io/readers/GenericReader.h"
44 #include "DGtal/io/DrawWithDisplay3DModifier.h"
45 
46 #include "CLI11.hpp"
47 
48 using namespace std;
49 using namespace DGtal;
50 using namespace Z3i;
51 
53 
138 // call back function to display voxel coordinates
139 int displayCoordsCallBack(void *viewer, int name, void *data)
140 {
141  vector<Z3i::RealPoint> *vectVoxels = (vector<Z3i::RealPoint> *)data;
142  std::stringstream ss;
143  ss << "Selected voxel: (" << (*vectVoxels)[name][0] << ", ";
144  ss << (*vectVoxels)[name][1] << ", ";
145  ss << (*vectVoxels)[name][2] << ") ";
146  ((Viewer *)viewer)->displayMessage(QString(ss.str().c_str()), 100000);
147 
148  return 0;
149 }
150 
151 int main(int argc, char **argv)
152 {
153  // parse command line using CLI ----------------------------------------------
154  CLI::App app;
155  std::string inputFileName;
156  std::vector<unsigned int> vectIndexSDP{0, 1, 2};
157  Color lineColor(100, 100, 250);
158  Color pointColor(250, 250, 250);
159  std::vector<int> vectColorPt;
160  std::vector<int> vectColorLine;
161  std::string meshName;
162  std::string typePrimitive{"voxel"};
163  std::string vectorsFileName;
164  std::vector<double> vectSphereRadius;
165  std::vector<unsigned int> vectColMesh;
166  std::vector<unsigned int> vectIndexColorImport{3, 4, 5};
167  bool importColorLabels{false};
168  bool noPointDisplay{false};
169  bool drawLines{false};
170  bool sphereRadiusFromInput{true};
171  bool importColors{false};
172  bool interactiveDisplayVoxCoords{false};
173  float sx{1.0};
174  float sy{1.0};
175  float sz{1.0};
176  unsigned int sphereResolution{30};
177  double sphereRadius{0.2};
178  double lineSize{0.2};
179  double filterValue{100.0};
180  double constantNorm{0.0};
181  double percentageFilterVect{100.0};
182  unsigned int customAlphaMesh;
183 
184  unsigned int colorLabelIndex = 3;
185 
186  app.description("Display sequence of 3d discrete points by using QGLviewer.");
187  app.add_option("-i,--input,1", inputFileName, "input file: sdp (sequence of discrete points).")
188  ->required()
189  ->check(CLI::ExistingFile);
190  app.add_option("--SDPindex", vectIndexSDP, "specify the sdp index (by default 0,1,2).")
191  ->expected(3);
192  app.add_option("--pointColor,-c", vectColorPt, "set the color of points: r g b a.")
193  ->expected(4);
194  app.add_option("--lineColor,-l", vectColorLine, "set the color of line: r g b a.")
195  ->expected(4);
196  app.add_option("--addMesh,-m", meshName, "append a mesh (off/obj) to the point set visualization.");
197  app.add_option("--customAlphaMesh", customAlphaMesh, "set the alpha components of the colors of the mesh faces (can be applied for each mesh).");
198  auto optMesh = app.add_option("--customColorMesh", vectColMesh, "set the R, G, B, A components of the colors of the mesh faces (mesh added with option --addMesh).")
199  ->expected(4);
200  auto importColOpt = app.add_flag("--importColors", importColors, "import point colors from the input file (R G B colors should be by default at index 3, 4, 5).");
201  app.add_option("--setColorsIndex", vectIndexColorImport, "customize the index of the imported colors in the source file (used by --importColor). By default the initial indexes are 3, 4, 5.")
202  ->expected(3)
203  ->needs(importColOpt);
204 
205  app.add_flag("--importColorLabels", importColorLabels, "import color labels from the input file (label index should be by default at index 3).");
206  app.add_option("--setColorLabelIndex", colorLabelIndex, "customize the index of the imported color labels in the source file (used by -importColorLabels).", true);
207  app.add_option("--filter,-f", filterValue, "filter input file in order to display only the [arg] percent of the input 3D points (uniformly selected).", true);
208  app.add_flag("--noPointDisplay", noPointDisplay, "usefull for instance to only display the lines between points.");
209  app.add_flag("--drawLines", drawLines, "draw the line between discrete points.");
210  app.add_option("--scaleX,-x", sx, "set the scale value in the X direction", true);
211  app.add_option("--scaleY,-y", sy, "set the scale value in the Y direction", true);
212  app.add_option("--scaleZ,-z", sy, "set the scale value in the Z direction", true);
213  app.add_option("--sphereResolution", sphereResolution, "defines the sphere resolution (used when the primitive is set to the sphere).", true);
214  app.add_option("-s,--sphereRadius", sphereRadius, "defines the sphere radius (used when the primitive is set to the sphere).", true);
215  app.add_flag("--sphereRadiusFromInput", sphereRadiusFromInput, "takes, as sphere radius, the 4th field of the sdp input file.");
216  app.add_option("--lineSize", lineSize, "defines the line size (used when the --drawLines or --drawVectors option is selected).", true);
217  app.add_option("--primitive,-p", typePrimitive, "set the primitive to display the set of points.", true)
218  ->check(CLI::IsMember({"voxel", "glPoints", "sphere"}));
219  app.add_option("--drawVectors,-v", vectorsFileName, "SDP vector file: draw a set of vectors from the given file (each vector are determined by two consecutive point given, each point represented by its coordinates on a single line.");
220 
221  app.add_option("--unitVector,-u", constantNorm, "specifies that the SDP vector file format (of --drawVectors option) should be interpreted as unit vectors (each vector position is be defined from the input point (with input order) with a constant norm defined by [arg]).", true);
222 
223  app.add_option("--filterVectors", percentageFilterVect, "filters vector input file in order to display only the [arg] percent of the input vectors (uniformly selected, to be used with option --drawVectors else no effect). ", true);
224  app.add_flag("--interactiveDisplayVoxCoords", interactiveDisplayVoxCoords, " by using this option the coordinates can be displayed after selection (shift+left click on voxel).");
225 
226  app.get_formatter()->column_width(40);
227  CLI11_PARSE(app, argc, argv);
228  // END parse command line using CLI ----------------------------------------------
229 
230  if (vectColorLine.size() == 4)
231  {
232  lineColor.setRGBi(vectColorLine[0], vectColorLine[1], vectColorLine[2], vectColorLine[3]);
233  }
234  if (vectColorPt.size() == 4)
235  {
236  pointColor.setRGBi(vectColorPt[0], vectColorPt[1], vectColorPt[2], vectColorPt[3]);
237  }
238 
239  QApplication application(argc, argv);
240 
241  bool useUnitVector = constantNorm != 0.0;
242 
244  Z3i::KSpace K;
245  Viewer viewer(K);
246  viewer.setWindowTitle("3dSPD Viewer");
247  viewer.show();
248  viewer.setGLScale(sx, sy, sz);
249  viewer.myGLLineMinWidth = lineSize;
250  viewer << CustomColors3D(pointColor, pointColor);
251 
252  // Get vector of colors if imported.
253  std::vector<Color> vectColors;
254  if (importColors)
255  {
256  std::vector<unsigned int> r = TableReader<unsigned int>::getColumnElementsFromFile(inputFileName, vectIndexColorImport[0]);
257  std::vector<unsigned int> g = TableReader<unsigned int>::getColumnElementsFromFile(inputFileName, vectIndexColorImport[1]);
258  std::vector<unsigned int> b = TableReader<unsigned int>::getColumnElementsFromFile(inputFileName, vectIndexColorImport[2]);
259  for (unsigned int i = 0; i < r.size(); i++)
260  {
261  vectColors.push_back(Color(r[i], g[i], b[i]));
262  }
263  }
264 
265  // Get vector of colors if imported.
266  std::vector<int> vectColorLabels;
267  unsigned int maxLabel = 1;
268  if (importColorLabels)
269  {
270  vectColorLabels = TableReader<int>::getColumnElementsFromFile(inputFileName, colorLabelIndex);
271  maxLabel = *(std::max_element(vectColorLabels.begin(), vectColorLabels.end()));
272  }
273  HueShadeColorMap<unsigned int> aColorMap(0, maxLabel);
274 
275  if (sphereRadiusFromInput)
276  {
277  vectSphereRadius = TableReader<double>::getColumnElementsFromFile(inputFileName, 3);
278  }
279 
280  vector<Z3i::RealPoint> vectVoxels;
281  vectVoxels = PointListReader<Z3i::RealPoint>::getPointsFromFile(inputFileName, vectIndexSDP);
282 
283  int name = 0;
284  if (!noPointDisplay)
285  {
286  if (typePrimitive == "glPoints")
287  {
288  viewer.setUseGLPointForBalls(true);
289  }
290 
291  int step = max(1, (int)(100 / filterValue));
292  for (unsigned int i = 0; i < vectVoxels.size(); i = i + step)
293  {
294  if (importColors)
295  {
296  Color col = vectColors[i];
297  viewer.setFillColor(col);
298  }
299  else if (importColorLabels)
300  {
301  unsigned int index = vectColorLabels[i];
302  Color col = aColorMap(index);
303  viewer.setFillColor(col);
304  }
305 
306  if (typePrimitive == "voxel")
307  {
308  if (interactiveDisplayVoxCoords)
309  {
310  viewer << SetName3D(name++);
311  }
312  viewer << Z3i::Point((int)vectVoxels.at(i)[0],
313  (int)vectVoxels.at(i)[1],
314  (int)vectVoxels.at(i)[2]);
315  }
316  else
317  {
318  viewer.addBall(vectVoxels.at(i), sphereRadius, sphereResolution);
319  }
320  }
321 
322  viewer << CustomColors3D(lineColor, lineColor);
323  if (drawLines)
324  {
325  for (unsigned int i = 1; i < vectVoxels.size(); i++)
326  {
327  viewer.addLine(vectVoxels.at(i - 1), vectVoxels.at(i), lineSize);
328  }
329  }
330 
331  if (vectorsFileName != "")
332  {
333  std::vector<Z3i::RealPoint> vectorsPt = PointListReader<Z3i::RealPoint>::getPointsFromFile(vectorsFileName);
334  if (vectorsPt.size() % 2 == 1)
335  {
336  trace.info() << "Warning the two set of points doesn't contains the same number of points, some vectors will be skipped." << std::endl;
337  }
338 
339  double percentage = percentageFilterVect;
340  int step = max(1, (int)(100 / percentage));
341 
342  if (useUnitVector)
343  {
344  for (unsigned int i = 0; i < std::min(vectVoxels.size(), vectorsPt.size()); i = i + 2 * step)
345  {
346  viewer.addLine(vectVoxels.at(i), vectVoxels.at(i) + vectorsPt.at(i) * constantNorm, lineSize);
347  }
348  }
349  else
350  {
351  for (unsigned int i = 0; i < vectorsPt.size() - 1; i = i + 2 * step)
352  {
353  viewer.addLine(vectorsPt.at(i), vectorsPt.at(i + 1), lineSize);
354  }
355  }
356  }
357  if (meshName != "")
358  {
359  bool customColorMesh = vectColMesh.size() == 4;
360  if (customColorMesh)
361  {
362  viewer.setFillColor(DGtal::Color(vectColMesh[0], vectColMesh[1], vectColMesh[2], vectColMesh[3]));
363  }
364  Mesh<Z3i::RealPoint> mesh(!customColorMesh);
365  mesh << meshName;
366  if (customAlphaMesh)
367  {
368  for (unsigned int j = 0; j < mesh.nbFaces(); j++)
369  {
370  auto c = mesh.getFaceColor(j);
371  mesh.setFaceColor(j, Color(c.red(), c.green(), c.blue(), customAlphaMesh));
372  }
373  viewer << mesh;
374  }
375  if (interactiveDisplayVoxCoords)
376  {
377  viewer << SetSelectCallback3D(displayCoordsCallBack, &vectVoxels, 0, vectVoxels.size() - 1);
378  }
379 
380  viewer << Viewer3D<>::updateDisplay;
381  return application.exec();
382  }
383  }
384 }
int main(int argc, char **argv)
std::ostream & info()
Trace trace(traceWriterTerm)