7 #include "imstkLineMeshCut.h" 8 #include "imstkImplicitGeometry.h" 9 #include "imstkLineMesh.h" 10 #include "imstkPlane.h" 11 #include "imstkSurfaceMesh.h" 15 LineMeshCut::LineMeshCut()
21 std::shared_ptr<LineMesh>
22 LineMeshCut::getOutputMesh()
24 return std::dynamic_pointer_cast<LineMesh>(
getOutput(0));
28 LineMeshCut::setInputMesh(std::shared_ptr<LineMesh> mesh)
35 std::map<int, bool>& cutVerts)
37 auto outputLineMesh = std::dynamic_pointer_cast<
LineMesh>(outputGeom);
39 std::shared_ptr<VecDataArray<int, 2>> cells = outputLineMesh->getCells();
40 std::shared_ptr<VecDataArray<double, 3>> vertices = outputLineMesh->getVertexPositions();
41 std::shared_ptr<VecDataArray<double, 3>> initVerts = outputLineMesh->getInitialVertexPositions();
42 cells->reserve(cells->size() * 2);
43 vertices->reserve(vertices->size() * 2);
44 initVerts->reserve(initVerts->size() * 2);
47 std::map<std::pair<int, int>,
int> edgeVertMap;
48 for (
const auto& curCutData : *m_CutData)
51 const int cellId = curCutData.cellId;
52 const int ptId0 = curCutData.ptIds[0];
53 const int ptId1 = curCutData.ptIds[1];
54 const Vec3d& coord0 = curCutData.cutCoords[0];
56 const Vec3d& initCoord0 = curCutData.initCoords[0];
60 vertices->push_back(coord0);
61 initVerts->push_back(initCoord0);
63 const int newPtId0 = vertices->size() - 1;
67 const Vec2i prevCell = (*cells)[cellId];
68 (*cells)[cellId] = Vec2i(prevCell[0], newPtId0);
69 cells->push_back(Vec2i(newPtId0, prevCell[1]));
72 cutVerts[newPtId0] =
true;
75 m_RemoveConstraintVertices->insert(ptId0);
76 m_RemoveConstraintVertices->insert(ptId1);
77 m_AddConstraintVertices->insert(ptId0);
78 m_AddConstraintVertices->insert(ptId1);
79 m_AddConstraintVertices->insert(newPtId0);
85 std::map<int, bool>& cutVerts,
86 std::shared_ptr<Geometry> cuttingGeom)
88 auto outputLineMesh = std::dynamic_pointer_cast<
LineMesh>(outputGeom);
90 std::shared_ptr<VecDataArray<int, 2>> cells = outputLineMesh->getCells();
91 std::shared_ptr<VecDataArray<double, 3>> vertices = outputLineMesh->getVertexPositions();
92 std::shared_ptr<VecDataArray<double, 3>> initVerts = outputLineMesh->getInitialVertexPositions();
94 std::shared_ptr<ImplicitGeometry> cutGeometry =
nullptr;
95 if (
auto implicitCutGeom = std::dynamic_pointer_cast<ImplicitGeometry>(cuttingGeom))
97 cutGeometry = implicitCutGeom;
99 else if (
auto surfMeshCutGeom = std::dynamic_pointer_cast<SurfaceMesh>(cuttingGeom))
102 std::shared_ptr<VecDataArray<int, 3>> cutTriangles = surfMeshCutGeom->getCells();
103 std::shared_ptr<VecDataArray<double, 3>> cutVertices = surfMeshCutGeom->getVertexPositions();
106 const Vec3d p0 = (*cutVertices)[(*cutTriangles)[0][0]];
107 const Vec3d p1 = (*cutVertices)[(*cutTriangles)[0][1]];
108 const Vec3d p2 = (*cutVertices)[(*cutTriangles)[0][2]];
109 const Vec3d cutNormal = ((p1 - p0).cross(p2 - p0)).normalized();
110 cutGeometry = std::make_shared<Plane>(p0, cutNormal);
112 CHECK(cutGeometry !=
nullptr) <<
113 "Unsupported cut geometry. Only SurfaceMesh and ImplicitGeometry supported";
116 outputLineMesh->computeVertexToCellMap();
117 const std::vector<std::unordered_set<int>>& vertexToCellMap = outputLineMesh->getVertexToCellMap();
120 for (
const auto& cutVert : cutVerts)
122 bool useFirstVertex =
false;
125 for (
const auto& cellId : vertexToCellMap[cutVert.first])
130 useFirstVertex =
true;
136 const int newPtId = vertices->size();
137 vertices->push_back((*vertices)[cutVert.first]);
138 initVerts->push_back((*initVerts)[cutVert.first]);
139 (*m_CutVertMap)[cutVert.first] = newPtId;
140 m_AddConstraintVertices->insert(newPtId);
143 Vec2i& cell = (*cells)[cellId];
144 if (cell[0] == cutVert.first)
148 else if (cell[1] == cutVert.first)
156 std::shared_ptr<std::vector<CutData>>
158 std::shared_ptr<Geometry> cuttingGeom,
159 std::shared_ptr<AbstractCellMesh> geomToCut)
161 if (
auto cuttingSurfMesh = std::dynamic_pointer_cast<SurfaceMesh>(cuttingGeom))
163 return generateSurfaceMeshCutData(cuttingSurfMesh,
164 std::dynamic_pointer_cast<LineMesh>(geomToCut));
166 else if (
auto cuttingAnalyticGeom = std::dynamic_pointer_cast<AnalyticalGeometry>(cuttingGeom))
168 return generateImplicitCutData(cuttingAnalyticGeom,
169 std::dynamic_pointer_cast<LineMesh>(geomToCut));
171 LOG(FATAL) <<
"No case for cut geometry";
175 std::shared_ptr<std::vector<CutData>>
176 LineMeshCut::generateImplicitCutData(std::shared_ptr<ImplicitGeometry> cuttingGeom,
177 std::shared_ptr<LineMesh> geomToCut)
179 auto cutData = std::make_shared<std::vector<CutData>>();
181 auto lineMeshToCut = std::dynamic_pointer_cast<
LineMesh>(geomToCut);
182 std::shared_ptr<VecDataArray<int, 2>> cells = lineMeshToCut->getCells();
183 std::shared_ptr<VecDataArray<double, 3>> vertices = lineMeshToCut->getVertexPositions();
184 std::shared_ptr<VecDataArray<double, 3>> initVerts = lineMeshToCut->getInitialVertexPositions();
187 for (
int i = 0; i < cells->size(); i++)
189 const Vec2i& cell = (*cells)[i];
202 const int caseType = ptSide.squaredNorm();
205 const int ptId0 = cell[0];
206 const int ptId1 = cell[1];
208 const Vec3d pos0 = (*vertices)[ptId0];
209 const Vec3d pos1 = (*vertices)[ptId1];
210 const Vec3d initPos0 = (*initVerts)[ptId0];
211 const Vec3d initPos1 = (*initVerts)[ptId1];
212 const double func0 = cuttingGeom->getFunctionValue(pos0);
213 const double func1 = cuttingGeom->getFunctionValue(pos1);
214 const double frac = -func0 / (func1 - func0);
215 const Vec3d iPt = frac * (pos1 - pos0) + pos0;
216 const Vec3d init_iPt = frac * (initPos1 - initPos0) + initPos0;
220 cellCutData.cutType =
static_cast<int>(SegmentCutType::EDGE);
221 cellCutData.cellId = i;
222 cellCutData.ptIds[0] = ptId0;
223 cellCutData.ptIds[1] = ptId1;
224 cellCutData.cutCoords[0] = iPt;
225 cellCutData.cutCoords[1] = (*vertices)[ptId1];
226 cellCutData.initCoords[0] = init_iPt;
227 cellCutData.initCoords[1] = (*initVerts)[ptId1];
228 cutData->push_back(cellCutData);
236 std::shared_ptr<std::vector<CutData>>
237 LineMeshCut::generateSurfaceMeshCutData(std::shared_ptr<SurfaceMesh> cuttingGeom,
238 std::shared_ptr<LineMesh> geomToCut)
240 auto cutData = std::make_shared<std::vector<CutData>>();
242 std::shared_ptr<VecDataArray<int, 3>> cutTriangles = cuttingGeom->getCells();
243 std::shared_ptr<VecDataArray<double, 3>> cutVertices = cuttingGeom->getVertexPositions();
244 std::shared_ptr<VecDataArray<int, 2>> lines = geomToCut->getCells();
245 std::shared_ptr<VecDataArray<double, 3>> vertices = geomToCut->getVertexPositions();
248 const Vec3d p0 = (*cutVertices)[(*cutTriangles)[0][0]];
249 const Vec3d p1 = (*cutVertices)[(*cutTriangles)[0][1]];
250 const Vec3d p2 = (*cutVertices)[(*cutTriangles)[0][2]];
251 const Vec3d cutNormal = (p1 - p0).cross(p2 - p0);
252 auto cutPlane = std::make_shared<Plane>(p0, cutNormal);
255 std::shared_ptr<std::vector<CutData>> planeCutData =
256 generateImplicitCutData(cutPlane, geomToCut);
259 for (
const CutData& cellCutData : *planeCutData)
261 const bool coord0In = pointProjectionInSurface(cellCutData.cutCoords[0], cuttingGeom);
262 const bool coord1In = pointProjectionInSurface(cellCutData.cutCoords[1], cuttingGeom);
263 if (coord0In && coord1In)
265 cutData->push_back(cellCutData);
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...
void setNumOutputPorts(const size_t numPorts)
Get/Set the amount of output ports.
std::shared_ptr< Geometry > getOutput(size_t port=0) const
Returns output geometry given port, returns nullptr if doesn't exist.
void setInput(std::shared_ptr< Geometry > inputGeometry, size_t port=0)
Set the input at the port.
void splitVerts(std::shared_ptr< AbstractCellMesh > outputGeom, std::map< int, bool > &cutVerts, std::shared_ptr< Geometry > cuttingGeom) override
Split the cutting vertices, separating them into two.
Base class for all volume mesh types.
void setOutput(std::shared_ptr< Geometry > inputGeometry, const size_t port=0)
Set the output at the port.
void refinement(std::shared_ptr< AbstractCellMesh > outputGeom, std::map< int, bool > &cutVerts) override
Refine the mesh adding vertices and changing connectivity along the cut.
std::shared_ptr< std::vector< CutData > > generateCutData(std::shared_ptr< Geometry > cuttingGeom, std::shared_ptr< AbstractCellMesh > geomToCut) override
Generate CutData which defines how the cut should be performed.