iMSTK
Interactive Medical Simulation Toolkit
imstkMeshCut.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkMeshCut.h"
8 #include "imstkAnalyticalGeometry.h"
9 #include "imstkSurfaceMesh.h"
10 
11 namespace imstk
12 {
13 MeshCut::MeshCut()
14 {
16  setRequiredInputType<AbstractCellMesh>(0);
17 
18  m_CutGeometry = nullptr;
19  m_RemoveConstraintVertices = std::make_shared<std::unordered_set<size_t>>();
20  m_AddConstraintVertices = std::make_shared<std::unordered_set<size_t>>();
21 }
22 
23 void
25 {
26  // input and output SurfaceMesh
27  auto inputGeom = std::dynamic_pointer_cast<AbstractCellMesh>(getInput(0));
28  if (inputGeom == nullptr)
29  {
30  LOG(WARNING) << "Missing required AbstractCellMesh input";
31  return;
32  }
33  // Copy input to output
34  setOutput(inputGeom->clone());
35  auto outputGeom = std::dynamic_pointer_cast<AbstractCellMesh>(getOutput(0));
36 
37  // Vertices on the cutting path and whether they will be split
38  std::map<int, bool> cutVerts;
39 
40  // Compute the CutData which defines how to perform the cut
41  m_CutData = generateCutData(m_CutGeometry, outputGeom);
42  if (m_CutData->size() == 0)
43  {
44  return;
45  }
46 
47  // Refine the mesh, adding vertices where the cutting occurs
48  refinement(outputGeom, cutVerts);
49 
50  // Split cutting vertices, separating the geometry
51  splitVerts(outputGeom, cutVerts, m_CutGeometry);
52 }
53 
54 int
55 MeshCut::ptBoundarySign(const Vec3d& pt, std::shared_ptr<Geometry> geometry)
56 {
57  if (auto implicitGeom = std::dynamic_pointer_cast<ImplicitGeometry>(geometry))
58  {
59  const double normalProjection = implicitGeom->getFunctionValue(pt);
60  if (normalProjection > m_Epsilon)
61  {
62  return 1;
63  }
64  else if (normalProjection < -m_Epsilon)
65  {
66  return -1;
67  }
68  }
69  else if (std::dynamic_pointer_cast<SurfaceMesh>(geometry) != nullptr)
70  {
71  // save for curve surface cutting
72  }
73  return 0;
74 }
75 
76 bool
77 MeshCut::pointProjectionInSurface(const Vec3d& pt,
78  std::shared_ptr<SurfaceMesh> surface)
79 {
80  std::shared_ptr<VecDataArray<int, 3>> triangles = surface->getCells();
81  std::shared_ptr<VecDataArray<double, 3>> vertices = surface->getVertexPositions();
82  bool inSurface = false;
83 
84  for (const Vec3i& tri : *triangles)
85  {
86  const Vec3d p0 = (*vertices)[tri[0]];
87  const Vec3d p1 = (*vertices)[tri[1]];
88  const Vec3d p2 = (*vertices)[tri[2]];
89  const Vec3d normal = (p1 - p0).cross(p2 - p0).normalized();
90 
91  const double leftP0P1 = normal.dot((p1 - p0).cross(pt - p0));
92  const double leftP1P2 = normal.dot((p2 - p1).cross(pt - p1));
93  const double leftP2P0 = normal.dot((p0 - p2).cross(pt - p2));
94 
95  if (leftP0P1 >= 0.0 && leftP1P2 >= 0.0 && leftP2P0 >= 0.0)
96  {
97  inSurface = true;
98  break;
99  }
100  }
101  return inSurface;
102 }
103 } // namespace imstk
virtual void refinement(std::shared_ptr< AbstractCellMesh > outputGeom, std::map< int, bool > &cutVerts)=0
Refine the mesh adding vertices and changing connectivity along the cut.
std::shared_ptr< Geometry > getInput(size_t port=0) const
Returns input geometry given port, returns nullptr if doesn&#39;t exist.
Compound Geometry.
int ptBoundarySign(const Vec3d &pt, std::shared_ptr< Geometry > geometry)
Determine the sign of the point -1 if inside, 1 if outside, 0 if on boundary defined by epsilon...
std::shared_ptr< Geometry > getOutput(size_t port=0) const
Returns output geometry given port, returns nullptr if doesn&#39;t exist.
virtual void splitVerts(std::shared_ptr< AbstractCellMesh > outputGeom, std::map< int, bool > &cutVerts, std::shared_ptr< Geometry > cuttingGeom)=0
Split the cutting vertices, separating them into two.
void requestUpdate() override
Users can implement this for the logic to be run.
void setOutput(std::shared_ptr< Geometry > inputGeometry, const size_t port=0)
Set the output at the port.
virtual std::shared_ptr< std::vector< CutData > > generateCutData(std::shared_ptr< Geometry > cuttingGeom, std::shared_ptr< AbstractCellMesh > geomToCut)=0
Generate CutData which defines how the cut should be performed.
void setNumInputPorts(const size_t numPorts)
Get/Set the amount of input ports.
Provides non templated base for cell based meshes.