rsvs3D  0.0.0
Codes for the c++ implementation of the 3D RSVS
polyscopersvs.cpp
Go to the documentation of this file.
1 
13 #include "polyscopersvs.hpp"
14 #include "RSVSclass.hpp"
15 #include "RSVSintegration.hpp"
16 #include "imgui_stdlib.h"
17 #include "meshprocessing.hpp"
18 #include "parameters.hpp"
19 #include "polyscope/polyscope.h"
20 #include "polyscope/surface_mesh.h"
21 #include "rsvsjson.hpp"
22 #include "voxel.hpp"
23 #include <array>
24 #include <sstream>
25 #include <vector>
26 
29 namespace polyscopersvs
30 {
31 #ifdef HEADLESS
32 const std::string polyscopeBackend = "openGL_mock";
33 #else
34 const std::string polyscopeBackend = "";
35 #endif
36 } // namespace polyscopersvs
40 {
41 #ifndef HEADLESS
42  this->isHeadless = true;
43 #else
44  this->isHeadless = false;
45 #endif
47  {
49  // TODO: support the mocked backend of polyscope
50  polyscope::init(polyscopersvs::polyscopeBackend);
51  }
52 }
53 
55 {
56  this->isHeadless = isHeadless;
58  {
60  // TODO: support the mocked backend of polyscope
61  if (isHeadless)
62  {
63  polyscope::init("openGL_mock");
64  }
65  else
66  {
68  }
69  }
70 }
71 
78 void polyscopersvs::PolyScopeRSVS::show(size_t forFrames)
79 {
80  if (!(this->isHeadless))
81  {
82  polyscope::show(forFrames);
83  }
84  else
85  {
86  std::cout << "Headless mode, no polyscope window shown." << std::endl;
87  }
88 }
89 
98 void polyscopersvs::PolyScopeRSVS::addMesh(std::string name, const mesh &meshIn)
99 {
100  if (this->isHeadless)
101  return;
102 
103  if (!meshIn.isready())
104  {
105  RSVS3D_ERROR("Mesh is not ready, cannot add to polyscope. Call `PrepareForUse` first.");
106  }
107  std::vector<std::vector<double>> points;
108  std::vector<std::vector<int>> faces;
109  points.reserve(meshIn.verts.size());
110  faces.reserve(meshIn.surfs.size());
111 
112  for (size_t i = 0; i < size_t(meshIn.verts.size()); ++i)
113  {
114  if (meshIn.verts(i)->coord.size() != 3)
115  {
117  (std::string("Vertex at position ") + std::to_string(i) + " has invalid coordinate.").c_str());
118  }
119 
120  points.push_back(meshIn.verts(i)->coord);
121  }
122  for (size_t i = 0; i < size_t(meshIn.surfs.size()); ++i)
123  {
124  auto faceIndices = meshIn.verts.find_list(meshIn.surfs(i)->OrderedVerts(&meshIn));
125  if (faceIndices.size() < 3)
126  {
128  (std::string("Surface at position") + std::to_string(i) + " has less than 3 vertices.").c_str());
129  }
130  faces.push_back(faceIndices);
131  }
132 
133  polyscope::registerSurfaceMesh(name, points, faces);
134 }
135 
141 void polyscopersvs::PolyScopeRSVS::addSnake(std::string name, const snake &snakeIn)
142 {
143  if (this->isHeadless)
144  return;
145 
146  this->addMesh(name, snakeIn.snakeconn);
147  std::vector<double> velocities;
148  velocities.reserve(snakeIn.snaxs.size());
149  for (size_t i = 0; i < size_t(snakeIn.snaxs.size()); ++i)
150  {
151 
152  velocities.push_back(snakeIn.snaxs(i)->v);
153  }
154  polyscope::getSurfaceMesh(name)->addVertexScalarQuantity("velocity", velocities);
155 }
156 
165 {
166  public:
167  _3dVectorWrapper(const std::vector<double> &vec, double multiplier = 1.0) : vec(vec), multiplier(multiplier)
168  {
169  }
170  double operator()(size_t i, size_t j) const
171  {
172  return vec[i * 3 + j] * this->multiplier;
173  }
174  size_t size() const
175  {
176  return vec.size() / 3;
177  }
178 
179  private:
180  const std::vector<double> &vec;
181  double multiplier = 1.0;
182 };
183 
190 void polyscopersvs::PolyScopeRSVS::addSurfaceProperties(std::string name, const mesh &surfaceMesh)
191 {
192  if (this->isHeadless)
193  return;
194 
195  std::vector<double> properties;
196 
197  auto psMesh = polyscope::getSurfaceMesh(name);
198 
199  psMesh->addEdgeScalarQuantity("edge-curvature", CalculateEdgeCurvature(surfaceMesh));
200  psMesh->addEdgeScalarQuantity("edge-length", CalculateEdgeLengths(surfaceMesh));
201  psMesh->addVertexScalarQuantity("vertex-curvature", CalculateVertexCurvature(surfaceMesh, 1));
202  psMesh->addVertexScalarQuantity("vertex-minimum-length", CalculateVertexMinEdgeLength(surfaceMesh));
203  psMesh->addVertexScalarQuantity("vertex-maximum-length", CalculateVertexMaxEdgeLength(surfaceMesh));
204  psMesh->addVertexScalarQuantity("vertex-mean-length", CalculateVertexMeanEdgeLength(surfaceMesh));
205  psMesh->addVertexVectorQuantity("vertex-normal", _3dVectorWrapper(MeshUnitNormals(surfaceMesh)));
206  psMesh->addVertexVectorQuantity("vertex-laplacians-(flipped)", _3dVectorWrapper(MeshLaplacians(surfaceMesh), -1.0));
207 }
208 
218 float polyscopersvs::PolyScopeRSVS::addCells(std::string name, const mesh &meshIn, const std::vector<int> &&cellIndices,
219  bool isIndex)
220 {
221  if (!meshIn.isready())
222  {
223  RSVS3D_ERROR("Mesh is not ready, cannot add to polyscope. Call `PrepareForUse` first.");
224  }
225  std::vector<std::vector<double>> points;
226  std::vector<std::vector<int>> faces;
227  points.reserve(meshIn.verts.size());
228  faces.reserve(meshIn.surfs.size());
229  float outputVolume = 0.0;
230 
231  // Todo: only access vertices that are in the cell.
232  for (size_t i = 0; i < size_t(meshIn.verts.size()); ++i)
233  {
234  if (meshIn.verts(i)->coord.size() != 3)
235  {
237  (std::string("Vertex at position ") + std::to_string(i) + " has invalid coordinate.").c_str());
238  }
239 
240  points.push_back(meshIn.verts(i)->coord);
241  }
242  std::vector<int> volumePositions;
243  if (isIndex)
244  {
245  volumePositions = meshIn.volus.find_list(cellIndices);
246  }
247  else
248  {
249  volumePositions = cellIndices;
250  }
251  for (auto volumePosition : volumePositions)
252  {
253  if (volumePosition < 0 || volumePosition >= meshIn.volus.size())
254  {
255  polyscope::warning("Failed to find cell", "ID : " + std::to_string(volumePosition));
256  continue;
257  }
258  std::cout << "Display cell " << meshIn.volus(volumePosition)->index << " at position [" << volumePosition << "]"
259  << std::endl;
260  outputVolume = meshIn.volus(volumePosition)->target;
261  if (this->isHeadless)
262  continue;
263  for (auto surfaceIndex : meshIn.volus(volumePosition)->surfind)
264  {
265  auto faceIndices = meshIn.verts.find_list(meshIn.surfs.isearch(surfaceIndex)->OrderedVerts(&meshIn));
266  if (faceIndices.size() < 3)
267  {
269  (std::string("Surface ") + std::to_string(surfaceIndex) + " has less than 3 vertices.").c_str());
270  }
271  faces.push_back(faceIndices);
272  }
273  }
274 
275  polyscope::registerSurfaceMesh(name, points, faces);
276  return outputVolume;
277 }
278 
286 namespace parameter_ui
287 {
288 void parameterConfigGui(param::voronoi &paramConf)
289 {
290  // Static variable keeps track of which entry is active in the voronoi config.
291  static int activeEntry;
292 
293  ImGui::InputDouble("Snake coarseness", &paramConf.snakecoarseness, 0.0, 0.0, "%.2f");
294  ImGui::InputInt("Voronoi layers", &paramConf.vorosnakelayers);
295  ImGui::InputDouble("Bounding box distance", &paramConf.distancebox, 0.0, 0.0, "%.2f");
296  paramConf.pointfile.reserve(2048);
297  ImGui::InputText("Voronoi points file", &paramConf.pointfile);
298 
299  if (ImGui::Button("Add Voronoi point"))
300  {
301  for (size_t i = 0; i < 4; i++)
302  {
303  paramConf.inputpoints.push_back(0.5);
304  // Hacky condition to ensure we finish when we hit a multiple of 4.
305  if (paramConf.inputpoints.size() % 4 == 0)
306  {
307  break;
308  }
309  }
310  }
311  int nEntries = paramConf.inputpoints.size() / 4;
312  // This is used to initalise the static variable if it is out of bounds
313  if (!(activeEntry < nEntries && activeEntry >= 0))
314  {
315  activeEntry = 0;
316  }
317 
318  if (nEntries > 0)
319  {
320  ImGui::InputInt(("Active Point, max ID: " + std::to_string(nEntries)).c_str(), &activeEntry);
321  if (!(activeEntry < nEntries && activeEntry >= 0))
322  {
323  polyscope::warning("ID to access input point was incorrect.", "Maximum value is " +
324  std::to_string(nEntries) + " value was " +
325  std::to_string(activeEntry));
326  activeEntry = 0;
327  }
328  ImGui::Text("Voronoi point definition - Active ID: %i\n X , Y , Z , Volume fraction", activeEntry);
329  for (int i = 0; i < 4; ++i)
330  {
331  auto fullName = ("## voropoint setter " + std::to_string(i)).c_str();
332  ImGui::InputDouble(fullName, &(paramConf.inputpoints[activeEntry * 4 + i]), 0.0, 0.0, "%.2f");
333  ImGui::SameLine();
334  }
335  ImGui::NewLine();
336  }
337 }
338 void parameterConfigGui(param::voxel &paramConf)
339 {
340  ImGui::InputInt3("Background grid", paramConf.gridsizebackground.data());
341  ImGui::InputInt3("Snaking grid", paramConf.gridsizesnake.data());
342 }
343 
344 void parameterConfigGui(std::string name, std::array<param::realbounds, 3> &paramConf)
345 {
346  if (ImGui::TreeNode(name.c_str()))
347  {
348  for (int j = 0; j < 2; ++j)
349  {
350  for (int i = 0; i < 3; ++i)
351  {
352  auto fullName = ("##" + name + std::to_string(i) + "," + std::to_string(j)).c_str();
353  ImGui::InputDouble(fullName, &(paramConf[i][j]), 0.2, 2.0, "%.2f");
354  ImGui::SameLine();
355  }
356  ImGui::NewLine();
357  }
358  ImGui::TreePop();
359  }
360 }
361 void parameterConfigGui(param::grid &paramConf)
362 {
363  if (ImGui::BeginCombo("##Grid Style", paramConf.activegrid.c_str()))
364  {
365  for (auto key : {"voxel", "voronoi"})
366  {
367  if (ImGui::Selectable(key, paramConf.activegrid == key))
368  {
369  paramConf.activegrid = key;
370  }
371  }
372  ImGui::EndCombo();
373  }
374  parameterConfigGui("Compute domain", paramConf.domain);
375  parameterConfigGui("Physical domain", paramConf.physdomain);
376  ImGui::SetNextTreeNodeOpen(false, ImGuiCond_FirstUseEver);
377  if (ImGui::TreeNode("Voxel"))
378  {
379  parameterConfigGui(paramConf.voxel);
380  ImGui::TreePop();
381  }
382  ImGui::SetNextTreeNodeOpen(false, ImGuiCond_FirstUseEver);
383  if (ImGui::TreeNode("Voronoi"))
384  {
385  parameterConfigGui(paramConf.voronoi);
386  ImGui::TreePop();
387  }
388 }
389 void parameterConfigGui(param::rsvs &paramConf)
390 {
391  bool change = ImGui::Checkbox("Uniform", &paramConf.cstfill.active);
392  if (change && paramConf.cstfill.active)
393  {
394  paramConf.filefill.active = false;
395  paramConf.makefill.active = false;
396  }
397  ImGui::SameLine();
398  ImGui::InputDouble("##Uniform value", &paramConf.cstfill.fill, 0.0, 0.0, "%.2f");
399 
400  change = ImGui::Checkbox("File", &paramConf.filefill.active);
401  if (change && paramConf.cstfill.active)
402  {
403  paramConf.makefill.active = false;
404  paramConf.cstfill.active = false;
405  }
406  ImGui::SameLine();
407  paramConf.filefill.fill.reserve(2048);
408  ImGui::InputText("##File value", &paramConf.filefill.fill);
409 
410  change = ImGui::Checkbox("Auto", &paramConf.makefill.active);
411  if (change && paramConf.makefill.active)
412  {
413  paramConf.filefill.active = false;
414  paramConf.cstfill.active = false;
415  }
416  ImGui::SameLine();
417  paramConf.makefill.fill.reserve(2048);
418  ImGui::InputText("##Auto value", &paramConf.makefill.fill);
419 
420  ImGui::InputInt("Linear solver (0-4)", &paramConf.solveralgorithm);
421 }
422 void parameterConfigGui(param::snaking &paramConf)
423 {
424  ImGui::InputDouble("Arrival tolerance", &paramConf.arrivaltolerance, 0.0, 0.0, "%.2e");
425  ImGui::InputDouble("Simulataneous arrival tolerance", &paramConf.multiarrivaltolerance, 0.0, 0.0, "%.2e");
426  ImGui::InputDouble("Max step distance", &paramConf.snaxdiststep, 0.0, 0.0, "%.2e");
427  ImGui::InputDouble("Max step time", &paramConf.snaxtimestep, 0.0, 0.0, "%.2e");
428  ImGui::InputDouble("Spawn position", &paramConf.spawnposition, 0.0, 0.0, "%.2e");
429  ImGui::InputInt("Initialisation boundary (0/1)", &paramConf.initboundary);
430 }
431 void parameterConfigGui(param::files &paramConf)
432 {
433  ImGui::InputInt("Logging level [0-7]", &paramConf.ioout.logginglvl);
434  ImGui::InputText("Case name", &paramConf.ioin.casename);
435  rsvsjson::json out;
436  out = paramConf;
437  std::ostringstream stream;
438  stream << out.dump(2);
439  ImGui::TextUnformatted(stream.str().c_str());
440 }
441 
442 void parameterConfigGui(param::dev::devparam &paramConf)
443 {
444  ImGui::InputDouble("limitlagrangian", &paramConf.limitlagrangian, 0.0, 0.0, "%.2e");
445  ImGui::InputInt("mindesvarsparse", &paramConf.mindesvarsparse);
446  ImGui::InputTextWithHint("smoothstepmethod", "Not sure what appropriate values are", &paramConf.smoothstepmethod);
447  ImGui::Checkbox("snaxDistanceLimit_conserveShape", &paramConf.snaxDistanceLimit_conserveShape);
448  ImGui::Checkbox("surfcentrehessian", &paramConf.surfcentrehessian);
449  ImGui::Checkbox("surfcentrejacobian", &paramConf.surfcentrejacobian);
450 
451  if (ImGui::TreeNode("Smoothing tolerances"))
452  {
453  ImGui::InputDouble("rsvsmath_automatic_eps_centre2", &paramConf.rsvsepsilons.rsvsmath_automatic_eps_centre2,
454  0.0, 0.0, "%.2e");
455  ImGui::InputDouble("rsvsmath_automatic_eps_centre", &paramConf.rsvsepsilons.rsvsmath_automatic_eps_centre, 0.0,
456  0.0, "%.2e");
457  ImGui::InputDouble("rsvsmath_automatic_eps_edge", &paramConf.rsvsepsilons.rsvsmath_automatic_eps_edge, 0.0, 0.0,
458  "%.2e");
459  ImGui::InputDouble("rsvsmath_automatic_eps_surf", &paramConf.rsvsepsilons.rsvsmath_automatic_eps_surf, 0.0, 0.0,
460  "%.2e");
461  ImGui::InputDouble("rsvsmath_automatic_eps_volu", &paramConf.rsvsepsilons.rsvsmath_automatic_eps_volu, 0.0, 0.0,
462  "%.2e");
463 
464  ImGui::TreePop();
465  }
466 }
467 void parameterExportImportGui(param::parameters &paramConf)
468 {
469  int fileNameCapacity = 1024;
470  static std::string importFile;
471  static std::string exportFile;
472  static bool flatJsonExport = false;
473  // Make sure the capacity of importFile is large enough
474  if (importFile.capacity() < size_t(fileNameCapacity))
475  {
476  importFile.reserve(fileNameCapacity);
477  importFile = "";
478  exportFile.reserve(fileNameCapacity);
479  exportFile = "interactive-export.json";
480  }
481 
482  // Buttons to import and export parameters
483  ImGui::PushItemWidth(200);
484  ImGui::InputTextWithHint("##Import-parameter", "import.json...", &importFile);
485  ImGui::PopItemWidth();
486  ImGui::SameLine();
487  if (ImGui::Button("Import"))
488  {
489  try
490  {
491  param::io::read(importFile, paramConf);
492  }
493  catch (const std::exception &e)
494  {
495  polyscope::error(std::string("Could not import parameters from file '") + importFile + "': " + e.what());
496  }
497  }
498  ImGui::PushItemWidth(200);
499  ImGui::InputTextWithHint("##Export-parameter", "export.json...", &exportFile);
500  ImGui::PopItemWidth();
501  ImGui::SameLine();
502  if (ImGui::Button("Export"))
503  {
504  try
505  {
506  if (!flatJsonExport)
507  {
508  param::io::write(exportFile, paramConf);
509  }
510  else
511  {
512  param::io::writeflat(exportFile, paramConf);
513  }
514  }
515  catch (const std::exception &e)
516  {
517  polyscope::error(std::string("Could not export parameters to file '") + exportFile + "': " + e.what());
518  }
519  }
520  ImGui::SameLine();
521  ImGui::Checkbox("Flat JSON format", &flatJsonExport);
522 }
523 void parameterConfigGui(param::parameters &paramConf)
524 {
525  // Buttons for configuring the parameter structure
526  if (ImGui::CollapsingHeader("Parameters"))
527  {
528  parameterExportImportGui(paramConf);
529 
530  ImGui::SetNextTreeNodeOpen(false, ImGuiCond_FirstUseEver);
531  if (ImGui::TreeNode("Grid"))
532  {
533  parameterConfigGui(paramConf.grid);
534  ImGui::TreePop();
535  }
536  if (ImGui::TreeNode("RSVS"))
537  {
538  parameterConfigGui(paramConf.rsvs);
539  ImGui::TreePop();
540  }
541  if (ImGui::TreeNode("Snaking"))
542  {
543  parameterConfigGui(paramConf.snak);
544  ImGui::TreePop();
545  }
546  if (ImGui::TreeNode("File setting (view)"))
547  {
548  parameterConfigGui(paramConf.files);
549  ImGui::TreePop();
550  }
551  if (ImGui::TreeNode("Development"))
552  {
553  parameterConfigGui(paramConf.dev);
554  ImGui::TreePop();
555  }
556  }
557 }
558 } // namespace parameter_ui
559 
560 namespace vos_ui
561 {
562 void UpdateVolume(integrate::RSVSclass &RSVSobj, int inspectId, bool volumeByIndex, double newVolumeValue)
563 {
564  // executes when button is pressed
565  RSVSobj.voluMesh.PrepareForUse();
566  int volumePosition = inspectId;
567  if (volumeByIndex)
568  {
569  volumePosition = RSVSobj.voluMesh.volus.find(inspectId);
570  }
571  if (volumePosition > -1 && volumePosition < RSVSobj.voluMesh.volus.size())
572  {
573  RSVSobj.voluMesh.volus[volumePosition].target =
574  newVolumeValue > 0.0 ? (newVolumeValue <= 1.0 ? newVolumeValue : 1.0) : 0.0;
575  RSVSobj.voluMesh.PrepareForUse();
576  }
577  else
578  {
579  polyscope::warning("Invalid Cell Position", "The cell was not found, it is either out of bounds"
580  " or not a valid index.");
581  }
582 }
583 void UpdateVolumes(integrate::RSVSclass &RSVSobj, double newVolumeValue)
584 {
585  RSVSobj.voluMesh.PrepareForUse();
586  newVolumeValue = newVolumeValue > 0.0 ? (newVolumeValue <= 1.0 ? newVolumeValue : 1.0) : 0.0;
587  for (size_t i = 0; i < size_t(RSVSobj.voluMesh.volus.size()); ++i)
588  {
589  RSVSobj.voluMesh.volus[i].target = newVolumeValue;
590  }
591 }
592 void vosExportImportGui(integrate::RSVSclass &RSVSobj)
593 {
594  static int lineLength = 8;
595  static int vosPrecision = 4;
596  size_t fileNameCapacity = 1024;
597  static std::string importFile;
598  static std::string exportFile;
599  // Make sure the capacity of importFile is large enough
600  if (importFile.capacity() < fileNameCapacity)
601  {
602  importFile.reserve(fileNameCapacity);
603  importFile = "";
604  exportFile.reserve(fileNameCapacity);
605  exportFile = "interactive-export.fill";
606  }
607  if (ImGui::TreeNode("Export/Import of Volume fractions"))
608  {
609  // Buttons to import and export parameters
610  ImGui::PushItemWidth(200);
611  ImGui::InputTextWithHint("##Import-vosfill", "import.fill...", &importFile);
612  ImGui::PopItemWidth();
613  ImGui::SameLine();
614  if (ImGui::Button("Import"))
615  {
616  try
617  {
618  RSVSobj.voluMesh.LoadTargetFill(importFile);
619  }
620  catch (const std::exception &e)
621  {
622  polyscope::error(std::string("Could not import VOS from file '") + importFile + "': " + e.what());
623  }
624  }
625  ImGui::PushItemWidth(200);
626  ImGui::InputTextWithHint("##Export-vosfill", "export.fill...", &exportFile);
627  ImGui::PopItemWidth();
628  ImGui::SameLine();
629  if (ImGui::Button("Export"))
630  {
631  try
632  {
633  // Write out the target fill of each Volume cell to the export file
634  std::fstream file(exportFile, std::ios::out);
635  file << std::setprecision(vosPrecision);
636  for (int i = 0; i < RSVSobj.voluMesh.volus.size(); ++i)
637  {
638  file << RSVSobj.voluMesh.volus[i].target << " ";
639  // every lineLength characters, write a newline
640  if (i % lineLength == lineLength - 1)
641  {
642  file << std::endl;
643  }
644  }
645  }
646  catch (const std::exception &e)
647  {
648  polyscope::error(std::string("Could not export parameters to file '") + exportFile + "': " + e.what());
649  }
650  }
651 
652  // Input for line length of the output file
653  ImGui::InputInt("Items per line", &lineLength);
654  ImGui::SameLine();
655  ImGui::InputInt("Precision", &vosPrecision);
656  ImGui::TreePop();
657  }
658 }
659 void vosControlGui(integrate::RSVSclass &RSVSobj)
660 {
661  static int inspectId = 1;
662  static bool volumeByIndex = true;
663  static float newVolumeValue = 0.0;
664  if (ImGui::CollapsingHeader("VOS Configuration"))
665  {
666  // A button to import and export the VOS configuration
667  vosExportImportGui(RSVSobj);
668  ImGui::Text("\nManual control and viewing Volume fractions");
669  bool cellIdChange = ImGui::InputInt("Cell ID", &inspectId);
670  ImGui::SameLine();
671  ImGui::Checkbox("Use ID (or position)", &volumeByIndex);
672  bool volumeHasChanged = ImGui::InputFloat("New volume", &newVolumeValue);
673  ImGui::SameLine();
674  bool volumesHaveChanged = ImGui::Button("Set All");
675  if (volumeHasChanged)
676  {
677  UpdateVolume(RSVSobj, inspectId, volumeByIndex, newVolumeValue);
678  }
679  if (volumesHaveChanged)
680  {
681  UpdateVolumes(RSVSobj, newVolumeValue);
682  }
683  if (cellIdChange || volumeHasChanged || volumesHaveChanged)
684  {
685  RSVSobj.voluMesh.PrepareForUse();
686  newVolumeValue = RSVSobj.viewer.addCells("Active Cell", RSVSobj.voluMesh, {inspectId}, volumeByIndex);
687  polyscope::getSurfaceMesh("Active Cell")
688  ->setSurfaceColor({1.0 - newVolumeValue, 1.0 - newVolumeValue, 1.0 - newVolumeValue});
689  }
690  }
691 }
692 
693 } // namespace vos_ui
694 
705 {
706  integrate::iteratereturns iterateInfo(0, 0, 0.0);
707 
713  auto callback = [&] {
714  bool runPreparation = false;
715  static bool safeToRun = true;
716  ImGui::PushItemWidth(100);
717 
718  bool viewSurfaces = ImGui::Button("View surfaces");
719  if (!safeToRun)
720  {
721  ImGui::SameLine();
722  if (ImGui::Button("Clear GUI Errors"))
723  {
724  safeToRun = true;
725  }
726  }
727 
728  if (ImGui::CollapsingHeader("RSVS Execution"))
729  {
730  ImGui::InputInt("Number of steps", &RSVSobj.paramconf.snak.maxsteps);
731  if (ImGui::Button("Run"))
732  {
733  if (!safeToRun)
734  {
735  polyscope::error("An error occurred during preparation, try resetting before iteration.");
736  }
737  else if (RSVSobj.rsvsSnake.snaxs.size() == 0)
738  {
739  polyscope::error("There are no snakes on the plane; try resetting before iteration.");
740  }
741  else
742  {
743  // executes when button is pressed
744  try
745  {
746  iterateInfo = integrate::execute::RSVSiterate(RSVSobj);
747  }
748  catch (const std::invalid_argument &e)
749  {
750  std::cerr << e.what() << '\n';
751  polyscope::error(e.what());
752  safeToRun = false;
753  }
754  }
755  }
756  ImGui::SameLine();
757 
758  if (ImGui::Button("Postprocess"))
759  {
760  // executes when button is pressed
761  integrate::execute::PostProcessing(RSVSobj, iterateInfo.timeT, iterateInfo.nVoluZone,
762  iterateInfo.stepNum);
763  integrate::execute::Exporting(RSVSobj);
764  }
765  ImGui::SameLine();
766  runPreparation = ImGui::Button("Reset");
767  if (runPreparation)
768  {
769  try
770  {
771  integrate::Prepare(RSVSobj);
772  safeToRun = true;
773  }
774  catch (const std::invalid_argument &e)
775  {
776  std::cerr << e.what() << '\n';
777  polyscope::error(e.what());
778  safeToRun = false;
779  }
780  }
781 
782  RSVSobj.paramconf.snak.engine.reserve(2048);
783  ImGui::InputText("Velocity Engine", &RSVSobj.paramconf.snak.engine);
784  }
785  if (viewSurfaces || runPreparation)
786  {
787  // executes when button is pressed
788  RSVSobj.rsvsSnake.PrepareForUse();
789  RSVSobj.voluMesh.PrepareForUse();
790  integrate::execute::logging::SnakePolyscope(RSVSobj.viewer, RSVSobj.rsvsSnake);
791  this->addMesh("Snaking mesh", *RSVSobj.rsvsSnake.snakemesh());
792  this->addMesh("Volume mesh", RSVSobj.voluMesh);
793 
794  polyscope::getSurfaceMesh("Snaking mesh")->setEnabled(false);
795  polyscope::getSurfaceMesh("Volume mesh")->setTransparency(0.5);
796  auto snakeSurfaceMesh = polyscope::getSurfaceMesh(integrate::constants::polyscopeSnakeName);
797  snakeSurfaceMesh->setEdgeColor({0, 0, 0});
798  snakeSurfaceMesh->setEdgeWidth(1);
799  snakeSurfaceMesh->setBackFacePolicy(polyscope::BackFacePolicy::Identical);
800  }
801  vos_ui::vosControlGui(RSVSobj);
802  parameter_ui::parameterConfigGui(RSVSobj.paramconf);
803 
804  ImGui::PopItemWidth();
805  };
806  polyscope::state::userCallback = callback;
807 }
808 
815 {
818  return 0;
819 }
820 
827 {
829  viewer.show(30);
830  return 0;
831 }
832 
839 {
840  int errorOut = 0;
842  mesh mesh1;
843 
844  std::array<int, 3> dims = {2, 3, 4};
845  errorOut += BuildBlockGrid(dims, mesh1);
846  mesh1.PrepareForUse();
847  viewer.addMesh("mesh1", mesh1);
848  viewer.show(60);
849  return 0;
850 }
Simple class containing all the information needed for the 3D-RSVS execution.
Integration into the full 3 dimensional Restricted Snake Volume of Solid method.
Wrap a vector to allow for (i,j) indexing as if it was a 2D array of coordinates.
Class for mesh handling.
Definition: mesh.hpp:592
Class for development parameters.
Definition: parameters.hpp:272
Class containing all parameter settings for file operations.
Definition: parameters.hpp:230
Class for parameters of the grid generation.
Definition: parameters.hpp:167
std::string activegrid
The type of grid to use either "voxel" or "voronoi" .
Definition: parameters.hpp:176
std::array< realbounds, 3 > physdomain
Physical domain size for export.
Definition: parameters.hpp:174
std::array< realbounds, 3 > domain
Domain size in internal coordinates.
Definition: parameters.hpp:172
Root class for all the parameters.
Definition: parameters.hpp:288
Parameters related to the Velocity calculation and VOS steps.
Definition: parameters.hpp:75
filltype< double > cstfill
Fill the VOS values with a constant value.
Definition: parameters.hpp:84
int solveralgorithm
Algorithm used by Eigen to solve the SQP system.
Definition: parameters.hpp:82
filltype< std::string > filefill
Fill the VOS values from file filefill.fill.
Definition: parameters.hpp:86
filltype< std::string > makefill
Fill the VOS values from a run time function accessible from makefill.fill.
Definition: parameters.hpp:89
Parameters controlling tuning parameters for the stepping of the restricted surface.
Definition: parameters.hpp:100
double snaxtimestep
maximum snake time step length
Definition: parameters.hpp:111
int initboundary
Initialisation boundary (either 0 (outer border), 1 (inner border))
Definition: parameters.hpp:116
int maxsteps
maximum number of steps
Definition: parameters.hpp:118
double multiarrivaltolerance
Distance along edge at which converging snaxels are considered arrived.
Definition: parameters.hpp:109
double snaxdiststep
maximum snaxel distance movement
Definition: parameters.hpp:113
double arrivaltolerance
Distance along edge at which a vertex is considered arrived regardless of "d" and "v".
Definition: parameters.hpp:106
double spawnposition
Position of spawn.
Definition: parameters.hpp:120
Class for handling of voronoi VOS meshing parameters.
Definition: parameters.hpp:144
double distancebox
Distance at which to build the bounding box of the mesh.
Definition: parameters.hpp:149
double snakecoarseness
The coarseneness level of the snaking mesh that will be generated.
Definition: parameters.hpp:154
int vorosnakelayers
The number of layers making up the snaking mesh inside each VOS cell [6 6 6] is roughly equal to 2.
Definition: parameters.hpp:157
std::vector< double > inputpoints
Vector of input points, 4 datums per point.
Definition: parameters.hpp:147
std::string pointfile
A string pointing to a file containing the set of inputpoints.
Definition: parameters.hpp:151
Parameters controlling cartesian grid properties.
Definition: parameters.hpp:129
std::array< int, 3 > gridsizesnake
Size of the Snaking grid on which the snake is defined.
Definition: parameters.hpp:135
std::array< int, 3 > gridsizebackground
Size of the Background grid on which the VOS is defined.
Definition: parameters.hpp:132
A structure containing the information about the polyscope display and the RSVS elements to display.
void addMesh(std::string name, const mesh &meshIn)
Add a mesh with a given name to the polyscope window.
float addCells(std::string name, const mesh &meshIn, const std::vector< int > &&cellIndices, bool isIndex=true)
Plot specified volume elements into polyscope.
bool isHeadless
Captures whether the RSVS window is being displayed or not.
PolyScopeRSVS()
Initialize polyscope, creating graphics contexts and constructing a window.
void addSurfaceProperties(std::string name, const mesh &surfaceMesh)
Adds properties of the surface of a snake to it's mesh as scalar quantities.
void show(size_t forFrames=SIZE_MAX)
Show the polyscope window.
void setInteractiveCallback(integrate::RSVSclass &RSVSobj)
Set polyscope's user callback to a lambda which allows control of the RSVSobj.
void addSnake(std::string name, const snake &snakeIn)
PLot a snake with it's velocity in the given polyscope window.
Definition: snake.hpp:83
Tools for the mathematical processing of meshes.
std::vector< double > CalculateEdgeCurvature(const mesh &meshin)
Calculates the angles between the surfaces connected at an edge.
std::vector< double > CalculateVertexCurvature(const mesh &meshin, int smoothingSteps)
Calculates the vertex curvature.
std::vector< double > CalculateEdgeLengths(const mesh &meshin)
Calculates the edge lengths.
std::vector< double > CalculateVertexMinEdgeLength(const mesh &meshin)
Calculates the vertex minimum edge length.
std::vector< double > CalculateVertexMeanEdgeLength(const mesh &meshin)
Calculates the vertex mean edge length.
std::vector< double > CalculateVertexMaxEdgeLength(const mesh &meshin)
Calculates the vertex maximum edge length.
Contains overloads of functions for displaying and configuring the parameter structure.
int show()
Should display the polyscope window.
int init()
Should initialise polyscope.
bool TEST_HEADLESS
Boolean controlling wether tests are run in headless mode or not.
int meshShow()
Should display a single small cubic mesh.
Namespace containing interfaces to polyscope for RSVS objects.
bool POLYSCOPE_INITIALISED
Flag controlling wether polyscope has been initialised or not.
Parameters for the integrated 3DRSVS.
Provide an interface between the RSVS process and polyscope.
Interface between the RSVS project and the JSON for Modern C++ library.
Generation of cartesian grids.
#define RSVS3D_ERROR(M)
Throw generic rsvs errors.
Definition: warning.hpp:113
#define RSVS3D_ERROR_RANGE(M)
Throw a range_error.
Definition: warning.hpp:173