7 #include "imstkCollisionUtils.h" 8 #include "imstkPbdConnectiveTissueConstraintGenerator.h" 9 #include "imstkLineMesh.h" 10 #include "imstkPbdBaryPointToPointConstraint.h" 11 #include "imstkPbdConstraintFunctor.h" 12 #include "imstkPbdModel.h" 13 #include "imstkPbdModelConfig.h" 14 #include "imstkPbdObject.h" 15 #include "imstkSurfaceMesh.h" 16 #include "imstkTetrahedralMesh.h" 17 #include "imstkTriangleToTetMap.h" 19 #include "imstkProximitySurfaceSelector.h" 20 #include "imstkConnectiveStrandGenerator.h" 27 auto tetMesh = std::dynamic_pointer_cast<
TetrahedralMesh>(pbdObj->getPhysicsGeometry());
39 int verticesConnected = 0;
40 for (
int vertId = 0; vertId < lineMesh->getNumVertices(); vertId++)
43 double minSqrDist = IMSTK_FLOAT_MAX;
45 int nearestTriangleId = -1;
46 for (
int triId = 0; triId < surfMesh->getNumCells(); triId++)
48 const Vec3d& x1 = surfMesh->getVertexPosition(surfMesh->getCells()->at(triId)[0]);
49 const Vec3d& x2 = surfMesh->getVertexPosition(surfMesh->getCells()->at(triId)[1]);
50 const Vec3d& x3 = surfMesh->getVertexPosition(surfMesh->getCells()->at(triId)[2]);
52 int ptOnTriangleCaseType;
53 const Vec3d closestPtOnTri = CollisionUtils::closestPointOnTriangle(vertexPosition,
54 x1, x2, x3, ptOnTriangleCaseType);
56 const double sqrDist = (closestPtOnTri - vertexPosition).squaredNorm();
57 if (sqrDist < minSqrDist)
60 nearestTriangleId = triId;
73 const Vec4d weights = tetMesh->computeBarycentricWeights(tetId, vertexPosition);
74 const int objId = pbdObj->getPbdBody()->bodyHandle;
77 auto vertToTetConstraint = std::make_shared<PbdBaryPointToPointConstraint>();
78 std::vector<PbdParticleId> ptsA = {
79 { objId, (*tetMesh->getCells())[tetId][0] },
80 { objId, (*tetMesh->getCells())[tetId][1] },
81 { objId, (*tetMesh->getCells())[tetId][2] },
82 { objId, (*tetMesh->getCells())[tetId][3] } };
84 std::vector<double> weightsA = { weights[0], weights[1], weights[2], weights[3] };
88 std::vector<double> weightsB = { 1.0 };
89 vertToTetConstraint->initConstraint(ptsA, weightsA, ptsB, weightsB, 1.0, 1.0);
96 std::shared_ptr<PbdObject> pbdObj,
99 auto surfMesh = std::dynamic_pointer_cast<
SurfaceMesh>(pbdObj->getPhysicsGeometry());
103 int verticesConnected = 0;
104 for (
int vertId = 0; vertId < lineMesh->getNumVertices(); vertId++)
107 double minSqrDist = IMSTK_FLOAT_MAX;
109 int nearestTriangleId = -1;
110 for (
int triId = 0; triId < surfMesh->getNumCells(); triId++)
112 const Vec3d& x1 = surfMesh->getVertexPosition(surfMesh->getCells()->at(triId)[0]);
113 const Vec3d& x2 = surfMesh->getVertexPosition(surfMesh->getCells()->at(triId)[1]);
114 const Vec3d& x3 = surfMesh->getVertexPosition(surfMesh->getCells()->at(triId)[2]);
116 int ptOnTriangleCaseType;
117 const Vec3d closestPtOnTri = CollisionUtils::closestPointOnTriangle(vertexPosition,
118 x1, x2, x3, ptOnTriangleCaseType);
120 const double sqrDist = (closestPtOnTri - vertexPosition).squaredNorm();
121 if (sqrDist < minSqrDist)
123 minSqrDist = sqrDist;
124 nearestTriangleId = triId;
136 const Vec3d weights = surfMesh->computeBarycentricWeights(nearestTriangleId, vertexPosition);
137 const int objId = pbdObj->getPbdBody()->bodyHandle;
140 auto vertToTriConstraint = std::make_shared<PbdBaryPointToPointConstraint>();
141 std::vector<PbdParticleId> ptsA = {
142 { objId, (*surfMesh->getCells())[nearestTriangleId][0] },
143 { objId, (*surfMesh->getCells())[nearestTriangleId][1] },
144 { objId, (*surfMesh->getCells())[nearestTriangleId][2] } };
146 std::vector<double> weightsA = { weights[0], weights[1], weights[2] };
150 std::vector<double> weightsB = { 1.0 };
151 vertToTriConstraint->initConstraint(ptsA, weightsA, ptsB, weightsB, 1.0, 1.0);
167 auto objAPhysMeshSurf = std::dynamic_pointer_cast<
SurfaceMesh>(
m_objA->getPhysicsGeometry());
168 if (objAPhysMeshSurf !=
nullptr)
174 if (objAPhysMeshTet !=
nullptr)
179 auto objBPhysMeshSurf = std::dynamic_pointer_cast<
SurfaceMesh>(
m_objB->getPhysicsGeometry());
180 if (objBPhysMeshSurf !=
nullptr)
186 if (objBPhysMeshTet !=
nullptr)
192 std::shared_ptr<PbdObject>
193 addConnectiveTissueConstraints(
194 std::shared_ptr<LineMesh> connectiveLineMesh,
195 std::shared_ptr<PbdObject> objA,
196 std::shared_ptr<PbdObject> objB,
197 std::shared_ptr<PbdModel> model,
199 double distStiffness)
202 CHECK(connectiveLineMesh !=
nullptr) <<
"NULL line mesh passes to generateConnectiveTissueConstraints";
203 CHECK(objA !=
nullptr) <<
"PbdObject objA is NULL in generateConnectiveTissueConstraints";
204 CHECK(objB !=
nullptr) <<
"PbdObject objB is NULL in generateConnectiveTissueConstraints";
206 auto connectiveStrands = std::make_shared<PbdObject>(
"connectiveTissue");
209 connectiveStrands->setVisualGeometry(connectiveLineMesh);
210 connectiveStrands->setPhysicsGeometry(connectiveLineMesh);
211 connectiveStrands->setCollidingGeometry(connectiveLineMesh);
212 connectiveStrands->setDynamicalModel(model);
214 connectiveStrands->getPbdBody()->uniformMassValue = mass / connectiveLineMesh->getNumVertices();
217 auto attachmentConstraintFunctor = std::make_shared<PbdConnectiveTissueConstraintGenerator>();
218 attachmentConstraintFunctor->setDistStiffness(distStiffness);
219 attachmentConstraintFunctor->setConnectiveStrandObj(connectiveStrands);
220 attachmentConstraintFunctor->generateDistanceConstraints();
221 attachmentConstraintFunctor->setConnectedObjA(objA);
222 attachmentConstraintFunctor->setConnectedObjB(objB);
223 attachmentConstraintFunctor->setBodyIndex(connectiveStrands->getPbdBody()->bodyHandle);
224 model->getConfig()->addPbdConstraintFunctor(attachmentConstraintFunctor);
226 return connectiveStrands;
229 std::shared_ptr<PbdObject>
230 makeConnectiveTissue(
231 std::shared_ptr<PbdObject> objA,
232 std::shared_ptr<PbdObject> objB,
233 std::shared_ptr<PbdModel> model,
235 double strandsPerFace,
236 int segmentsPerStrand,
237 std::shared_ptr<ProximitySurfaceSelector> proxSelector,
239 double distStiffness,
240 double allowedAngleDeviation)
242 proxSelector = std::make_shared<ProximitySurfaceSelector>();
245 auto objASurf = std::dynamic_pointer_cast<
SurfaceMesh>(objA->getCollidingGeometry());
246 CHECK(objASurf !=
nullptr) <<
"Object A " << objA->getName() <<
" Did not contain a surface mesh as colliding geometry in generateConnectiveTissue";
248 auto objBSurf = std::dynamic_pointer_cast<
SurfaceMesh>(objB->getCollidingGeometry());
249 CHECK(objBSurf !=
nullptr) <<
"Object B " << objB->getName() <<
" Did not contain a surface mesh as colliding geometry in generateConnectiveTissue";
251 CHECK(model !=
nullptr) <<
"PbdModel in generateConnectiveTissue is NULL";
253 Vec3d objACenter = std::dynamic_pointer_cast<
SurfaceMesh>(objA->getCollidingGeometry())->getCenter();
254 Vec3d objBCenter = std::dynamic_pointer_cast<SurfaceMesh>(objB->getCollidingGeometry())->getCenter();
256 if (fabs(maxDist) < 1.0e-6)
258 maxDist = (objACenter - objBCenter).norm();
261 proxSelector->setInputMeshes(
262 std::dynamic_pointer_cast<SurfaceMesh>(objA->getCollidingGeometry()),
263 std::dynamic_pointer_cast<SurfaceMesh>(objB->getCollidingGeometry()));
265 proxSelector->setProximity(maxDist);
266 proxSelector->update();
269 auto surfConnector = std::make_shared<ConnectiveStrandGenerator>();
270 surfConnector->setInputMeshes(
271 std::dynamic_pointer_cast<SurfaceMesh>(proxSelector->getOutput(0)),
272 std::dynamic_pointer_cast<SurfaceMesh>(proxSelector->getOutput(1)));
273 surfConnector->setSegmentsPerStrand(segmentsPerStrand);
274 surfConnector->setStrandsPerFace(strandsPerFace);
275 surfConnector->setAllowedAngleDeviation(allowedAngleDeviation);
276 surfConnector->update();
279 auto connectiveLineMesh = std::dynamic_pointer_cast<
LineMesh>(surfConnector->getOutput(0));
282 auto connectiveStrands = addConnectiveTissueConstraints(
283 connectiveLineMesh, objA, objB, model, mass);
285 return connectiveStrands;
288 std::shared_ptr<imstk::PbdObject>
289 makeConnectiveTissue(std::shared_ptr<PbdObject> objA, std::shared_ptr<PbdObject> objB, std::shared_ptr<PbdModel> model,
double maxDist ,
double strandsPerFace ,
290 int segmentsPerStrand ,
double mass ,
double distStiffness ,
double allowedAngleDeviation )
292 return makeConnectiveTissue(objA, objB, model, maxDist, strandsPerFace, segmentsPerStrand,
nullptr, mass, distStiffness, allowedAngleDeviation);
std::shared_ptr< PbdObject > m_objA
Organ being connected.
Container for pbd constraints.
void connectLineToTetMesh(std::shared_ptr< PbdObject > pbdObj, PbdConstraintContainer &constraints)
Used to generate connecting constraints when the body being attached uses a tet mesh as the physics m...
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.
std::shared_ptr< PbdObject > m_objB
Organ being connected.
std::shared_ptr< PbdObject > m_connectiveStrandObj
Connective tissue that is made.
std::shared_ptr< SurfaceMesh > extractSurfaceMesh() override
This method extracts the conforming triangular mesh from the tetrahedral mesh.
double m_distStiffness
Stiffness used for distance constraints.
SurfaceToTetrahedralMap serves as a PointwiseMap but also maps tets to triangle faces.
Represents a set of tetrahedrons & vertices via an array of Vec3d double vertices & Vec4i integer ind...
void setChildGeometry(std::shared_ptr< Geometry > child)
Get/Set child geometry.
const Vec3d & getVertexPosition(const size_t vertNum, DataType type=DataType::PostTransform) const
Returns the position of a vertex given its index.
Base class for all volume mesh types.
Represents a set of triangles & vertices via an array of Vec3d double vertices & Vec3i integer indice...
void connectLineToSurfMesh(std::shared_ptr< PbdObject > pbdObj, PbdConstraintContainer &constraints)
Used to generate connecting constraints when the body being attached uses a surface mesh as the physi...
void operator()(PbdConstraintContainer &constraints) override
Appends a set of constraint to the container given a geometry & body.
double m_tolerance
Tolerance for checking coincidence of surface to line mesh.
virtual void addConstraint(std::shared_ptr< PbdConstraint > constraint)
Adds a constraint to the system, thread safe.
void generateDistanceConstraints()
Creates distance constraints for the connective strands using the default m_distStiffness value...
void setTolerance(const double tolerance)
Set/Get the tolerance. The distance to consider two points equivalent/corresponding.