7 #include "imstkPbdObjectStitching.h" 8 #include "imstkCellPicker.h" 9 #include "imstkLineMesh.h" 10 #include "imstkPbdBaryPointToPointConstraint.h" 11 #include "imstkPbdModel.h" 12 #include "imstkPbdObject.h" 13 #include "imstkPbdSolver.h" 14 #include "imstkPointPicker.h" 15 #include "imstkSurfaceMesh.h" 16 #include "imstkTaskGraph.h" 17 #include "imstkTetrahedralMesh.h" 18 #include "imstkTriangleToTetMap.h" 31 indicesPtr(indicesPtrt), map(mapt), bodyId(bodyIdt)
42 static std::vector<PbdParticleId>
45 std::vector<PbdParticleId> results(N);
48 const Eigen::Matrix<int, N, 1>& cell = (*
dynamic_cast<VecDataArray<int, N>*
>(side.indicesPtr))[pickData.
ids[0]];
49 for (
int i = 0; i < N; i++)
51 int vertexId = cell[i];
52 if (side.map !=
nullptr)
56 results[i] = { side.bodyId, vertexId };
61 for (
int i = 0; i < N; i++)
63 int vertexId = pickData.
ids[i];
64 if (side.map !=
nullptr)
68 results[i] = { side.bodyId, vertexId };
74 static std::vector<double>
75 getWeights(
const PbdState& bodies,
const std::vector<PbdParticleId>& particles,
const Vec3d& pt)
77 std::vector<double> weights(particles.size());
78 if (particles.size() == 4)
80 const Vec4d baryCoord = baryCentric(pt,
81 bodies.getPosition(particles[0]),
82 bodies.getPosition(particles[1]),
83 bodies.getPosition(particles[2]),
84 bodies.getPosition(particles[3]));
85 weights[0] = baryCoord[0];
86 weights[1] = baryCoord[1];
87 weights[2] = baryCoord[2];
88 weights[3] = baryCoord[3];
90 else if (particles.size() == 3)
92 const Vec3d baryCoord = baryCentric(pt,
93 bodies.getPosition(particles[0]),
94 bodies.getPosition(particles[1]),
95 bodies.getPosition(particles[2]));
96 weights[0] = baryCoord[0];
97 weights[1] = baryCoord[1];
98 weights[2] = baryCoord[2];
100 else if (particles.size() == 2)
102 const Vec2d baryCoord = baryCentric(pt,
103 bodies.getPosition(particles[0]),
104 bodies.getPosition(particles[1]));
105 weights[0] = baryCoord[0];
106 weights[1] = baryCoord[1];
108 else if (particles.size() == 1)
115 PbdObjectStitching::PbdObjectStitching(std::shared_ptr<PbdObject> obj) :
116 m_objectToStitch(obj), m_pickMethod(std::make_shared<CellPicker>())
119 "PbdStitchingUpdate",
true);
120 m_taskGraph->addNode(m_stitchingNode);
122 m_taskGraph->addNode(m_objectToStitch->getPbdModel()->getIntegratePositionNode());
123 m_taskGraph->addNode(m_objectToStitch->getPbdModel()->getSolveNode());
125 m_taskGraph->addNode(m_objectToStitch->getTaskGraph()->getSource());
126 m_taskGraph->addNode(m_objectToStitch->getTaskGraph()->getSink());
132 auto pointPicker = std::make_shared<PointPicker>();
133 pointPicker->setPickingRay(rayStart, rayDir, maxDist);
134 m_pickMethod = pointPicker;
136 m_performStitch =
true;
137 LOG(INFO) <<
"Begin stitch";
143 m_constraints.clear();
144 m_collisionConstraints.clear();
150 std::shared_ptr<PbdModel> model = m_objectToStitch->getPbdModel();
153 std::shared_ptr<PointSet> pbdPhysicsGeom =
154 std::dynamic_pointer_cast<
PointSet>(m_objectToStitch->getPhysicsGeometry());
159 std::shared_ptr<PointSet> pointSetToPick = std::dynamic_pointer_cast<
PointSet>(m_geomToStitch);
160 if (m_geomToStitch ==
nullptr)
162 pointSetToPick = pbdPhysicsGeom;
165 std::shared_ptr<VecDataArray<double, 3>> verticesPtr = pbdPhysicsGeom->
getVertexPositions();
167 std::shared_ptr<AbstractDataArray> indicesPtr =
nullptr;
168 if (
auto cellMesh = std::dynamic_pointer_cast<AbstractCellMesh>(pointSetToPick))
170 indicesPtr = cellMesh->getAbstractCells();
175 if (m_geometryToStitchMap !=
nullptr)
177 map = m_geometryToStitchMap.get();
186 m_objectToStitch->getPbdBody()->bodyHandle);
191 const CellTypeId pickedCellType = data.cellType;
193 std::vector<PbdParticleId> cellIdVerts;
194 if (pickedCellType == IMSTK_TETRAHEDRON)
196 cellIdVerts = getElement<4>(data, meshStruct);
198 else if (pickedCellType == IMSTK_TRIANGLE)
200 cellIdVerts = getElement<3>(data, meshStruct);
202 else if (pickedCellType == IMSTK_EDGE)
204 cellIdVerts = getElement<2>(data, meshStruct);
209 auto pointPicker = std::dynamic_pointer_cast<
PointPicker>(m_pickMethod);
213 auto surfMesh = std::dynamic_pointer_cast<
SurfaceMesh>(pointSetToPick);
214 auto tetMesh = std::dynamic_pointer_cast<
TetrahedralMesh>(pointSetToPick);
215 if (tetMesh !=
nullptr)
219 const std::vector<PickData>& pickData = m_pickMethod->pick(surfMesh);
222 if (pickData.size() < 1)
227 std::vector<std::pair<PickData, PickData>> constraintPair;
228 if (std::dynamic_pointer_cast<TetrahedralMesh>(pointSetToPick) !=
nullptr)
232 surfMesh->computeTrianglesNormals();
233 std::shared_ptr<VecDataArray<double, 3>> faceNormalsPtr = surfMesh->getCellNormals();
237 for (
size_t i = 0, j = 1; i < pickData.size() - 1; i++, j++)
239 const Vec3d& pt_i = pickData[i].pickPoint;
240 const Vec3d& pt_j = pickData[j].pickPoint;
241 const Vec3d& normal_i = faceNormals[pickData[i].ids[0]];
242 const Vec3d& normal_j = faceNormals[pickData[j].ids[0]];
243 const Vec3d diff = pt_j - pt_i;
246 bool faceInwards = (diff.dot(normal_i) > 0.0) && (diff.dot(normal_j) < 0.0);
251 constraintPair.
push_back({ pickData[i], pickData[j] });
256 if (constraintPair.size() == 0)
268 for (
size_t i = 0; i < constraintPair.size(); i++)
270 PickData& pickData1 = constraintPair[i].first;
271 PickData& pickData2 = constraintPair[i].second;
276 pickData1.
cellType = IMSTK_TETRAHEDRON;
280 pickData2.
cellType = IMSTK_TETRAHEDRON;
284 else if (std::dynamic_pointer_cast<SurfaceMesh>(pointSetToPick) !=
nullptr)
287 for (
size_t i = 0, j = 1; i < pickData.size() - 1; i++, j++)
289 constraintPair.push_back({ pickData[i], pickData[j] });
294 for (
size_t i = 0; i < constraintPair.size(); i++)
296 const PickData& pickData1 = constraintPair[i].first;
297 const PickData& pickData2 = constraintPair[i].second;
299 if (m_maxStitchDist == -1.0 || (pickData2.
pickPoint - pickData1.
pickPoint).norm() < m_maxStitchDist)
301 std::vector<PbdParticleId> cellVerts1 = getCellVerts(pickData1);
302 std::vector<double> weights1 = getWeights(model->getBodies(), cellVerts1, pickData1.
pickPoint);
303 std::vector<PbdParticleId> cellVerts2 = getCellVerts(pickData2);
304 std::vector<double> weights2 = getWeights(model->getBodies(), cellVerts2, pickData2.
pickPoint);
308 cellVerts1, weights1,
309 cellVerts2, weights2,
310 m_stiffness, m_stiffness);
314 m_collisionConstraints.reserve(m_constraints.size());
315 for (
int i = 0; i < m_constraints.size(); i++)
317 m_collisionConstraints.push_back(m_constraints[i].
get());
323 const std::vector<PbdParticleId>& ptsA,
324 const std::vector<double>& weightsA,
325 const std::vector<PbdParticleId>& ptsB,
326 const std::vector<double>& weightsB,
327 const double stiffnessA,
const double stiffnessB)
329 auto constraint = std::make_shared<PbdBaryPointToPointConstraint>();
330 constraint->initConstraint(
333 stiffnessA, stiffnessB);
334 m_constraints.push_back(constraint);
340 m_objectToStitch->updateGeometries();
345 addStitchConstraints();
346 m_performStitch =
false;
349 if (m_collisionConstraints.size() > 0)
351 m_objectToStitch->getPbdModel()->getSolver()->addConstraints(&m_collisionConstraints);
358 std::shared_ptr<PbdModel> pbdModel = m_objectToStitch->getPbdModel();
360 m_taskGraph->addEdge(source, m_objectToStitch->getTaskGraph()->getSource());
361 m_taskGraph->addEdge(m_objectToStitch->getTaskGraph()->getSink(), sink);
364 m_taskGraph->addEdge(pbdModel->getIntegratePositionNode(), m_stitchingNode);
365 m_taskGraph->addEdge(m_stitchingNode, pbdModel->getSolveNode());
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
void addStitchConstraints()
Compute/generate the constraints for stitching.
virtual void addConstraint(const std::vector< PbdParticleId > &ptsA, const std::vector< double > &weightsA, const std::vector< PbdParticleId > &ptsB, const std::vector< double > &weightsB, const double stiffnessA, const double stiffnessB)
Add constraint between a point on each element given via barycentric coordinates pt position = weight...
void compute() override
Compute the map.
void setParentGeometry(std::shared_ptr< Geometry > parent)
Get/Set parent geometry.
int getParentTetId(const int triId) const
Get the tet id that contains the triangle.
void beginStitch(const Vec3d &rayStart, const Vec3d &rayDir, const double maxDist=-1.0)
Begin a ray point stitch. Stitches two points for separate elements.
virtual void updateStitching()
Update picking state, this should move grasp points.
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
std::shared_ptr< SurfaceMesh > extractSurfaceMesh() override
This method extracts the conforming triangular mesh from the tetrahedral mesh.
This class serves as the base class of DataArray, for typeless use.
int idCount
Indicates number of vertices (if 1 a cell or individual vertex)
SurfaceToTetrahedralMap serves as a PointwiseMap but also maps tets to triangle faces.
int getParentVertexId(const int childVertexId) const
Get the mapped/corresponding parent index, given a child index. returns -1 if no correspondence found...
Vec3d pickPoint
Some pickings may produce specific points on an element.
Represents a set of tetrahedrons & vertices via an array of Vec3d double vertices & Vec4i integer ind...
void setUseFirstHit(const bool useFirstHit)
Get/Set whether only the first hit is used otherwise all intersections are returned.
void setChildGeometry(std::shared_ptr< Geometry > child)
Get/Set child geometry.
PickData provides ids to indicate what was picked These may be optionally used to indicate the select...
std::shared_ptr< VecDataArray< double, 3 > > getVertexPositions(DataType type=DataType::PostTransform) const
Returns the vector of current positions of the mesh vertices.
Represents a set of triangles & vertices via an array of Vec3d double vertices & Vec3i integer indice...
PointwiseMap can compute & apply a mapping between parent and child PointSet geometries.
void removeStitchConstraints()
Clears all the stitches.
Provides interface for accessing particles from a 2d array of PbdBody,Particles.
Picks points on elements of geomToPick via those that that are intersecting the provided ray...
CellTypeId cellType
Indicates picked cell type.
Packs the info needed to add a constraint to a side by reference (this way dynamic casting & derefere...
void initGraphEdges()
Initializes the edges of the SceneObject's computational graph.
int ids[4]
Ids of the cell or vertices.