7 #include "imstkImplicitGeometryToPointSetCCD.h" 8 #include "imstkCollisionData.h" 9 #include "imstkImageData.h" 10 #include "imstkParallelUtils.h" 11 #include "imstkSurfaceMesh.h" 16 findFirstRoot(std::shared_ptr<ImplicitGeometry> implicitGeomA,
const Vec3d& start,
const Vec3d& end, Vec3d& root)
18 const Vec3d displacement = end - start;
20 Vec3d currPos = start;
21 Vec3d prevPos = start;
22 double currDist = implicitGeomA->getFunctionValue(start);
27 const double stepRatio = 0.01;
28 const double length = displacement.norm();
29 const double stepLength = length * stepRatio;
30 const Vec3d dir = displacement * (1.0 / length);
31 for (
double x = stepLength; x < length; x += stepLength)
34 currPos = start + dir * x;
37 currDist = implicitGeomA->getFunctionValue(currPos);
42 root = (prevPos + currPos) * 0.5;
49 ImplicitGeometryToPointSetCCD::ImplicitGeometryToPointSetCCD()
51 setRequiredInputType<ImplicitGeometry>(0);
52 setRequiredInputType<PointSet>(1);
56 ImplicitGeometryToPointSetCCD::setupFunctions(std::shared_ptr<ImplicitGeometry> implicitGeom, std::shared_ptr<PointSet> pointSet)
58 m_centralGrad.setFunction(implicitGeom);
59 if (
auto sdf = std::dynamic_pointer_cast<SignedDistanceField>(implicitGeom))
61 m_centralGrad.setDx(sdf->getImage()->getSpacing());
65 m_displacementsPtr = std::dynamic_pointer_cast<VecDataArray<double, 3>>(pointSet->getVertexAttribute(
"displacements"));
66 if (m_displacementsPtr ==
nullptr)
68 m_displacementsPtr = std::make_shared<VecDataArray<double, 3>>(pointSet->getNumVertices());
69 pointSet->setVertexAttribute(
"displacements", m_displacementsPtr);
70 m_displacementsPtr->fill(Vec3d::Zero());
76 std::shared_ptr<Geometry> geomA,
77 std::shared_ptr<Geometry> geomB,
78 std::vector<CollisionElement>& elementsA,
79 std::vector<CollisionElement>& elementsB)
81 std::shared_ptr<ImplicitGeometry> implicitGeom = std::dynamic_pointer_cast<
ImplicitGeometry>(geomA);
82 std::shared_ptr<PointSet> pointSet = std::dynamic_pointer_cast<
PointSet>(geomB);
83 setupFunctions(implicitGeom, pointSet);
91 std::shared_ptr<VecDataArray<double, 3>> vertexData = pointSet->getVertexPositions();
94 for (
int i = 0; i < vertices.size(); i++)
96 const Vec3d& pt = vertices[i];
97 const Vec3d& displacement = displacements[i];
98 const double limit = displacement.norm() * m_depthRatioLimit;
99 const Vec3d prevPt = pt - displacement;
101 Vec3d prevPos = prevPt;
102 double prevDist = implicitGeom->getFunctionValue(prevPos);
103 bool prevIsInside = std::signbit(prevDist);
106 double currDist = implicitGeom->getFunctionValue(currPos);
107 bool currIsInside = std::signbit(currDist);
110 if (prevIsInside && currIsInside)
112 if (m_prevOuterElementCounter[i] > 0)
115 m_prevOuterElementCounter[i]++;
117 const Vec3d start = m_prevOuterElement[i];
118 const Vec3d end = pt;
119 Vec3d contactPt = Vec3d::Zero();
120 if (findFirstRoot(implicitGeom, start, end, contactPt))
122 const Vec3d n = -m_centralGrad(contactPt).normalized();
123 const double depth = std::max(0.0, (contactPt - end).dot(n));
130 elemA.penetrationDepth = depth;
135 elemB.penetrationDepth = depth;
137 elementsA.push_back(elemA);
138 elementsB.push_back(elemB);
144 else if (!prevIsInside && currIsInside)
146 const Vec3d start = prevPt;
147 const Vec3d end = pt;
148 Vec3d contactPt = Vec3d::Zero();
149 if (findFirstRoot(implicitGeom, start, end, contactPt))
151 const Vec3d n = -m_centralGrad(contactPt).normalized();
152 const double depth = std::max(0.0, (contactPt - end).dot(n));
159 elemA.penetrationDepth = depth;
164 elemB.penetrationDepth = depth;
166 elementsA.push_back(elemA);
167 elementsB.push_back(elemB);
169 m_prevOuterElementCounter[i] = 1;
171 m_prevOuterElement[i] = start;
175 m_prevOuterElementCounter[i] = 0;
180 m_prevOuterElementCounter[i] = 0;
187 std::shared_ptr<Geometry> geomA,
188 std::shared_ptr<Geometry> geomB,
189 std::vector<CollisionElement>& elementsA)
192 std::shared_ptr<ImplicitGeometry> implicitGeom = std::dynamic_pointer_cast<
ImplicitGeometry>(geomA);
193 std::shared_ptr<PointSet> pointSet = std::dynamic_pointer_cast<
PointSet>(geomB);
194 setupFunctions(implicitGeom, pointSet);
198 std::shared_ptr<VecDataArray<double, 3>> vertexData = pointSet->getVertexPositions();
201 for (
int i = 0; i < vertices.size(); i++)
203 const Vec3d& pt = vertices[i];
204 const Vec3d& displacement = displacements[i];
205 const double limit = displacement.norm() * m_depthRatioLimit;
206 const Vec3d prevPt = pt - displacement;
208 Vec3d prevPos = prevPt;
209 double prevDist = implicitGeom->getFunctionValue(prevPos);
210 bool prevIsInside = std::signbit(prevDist);
213 double currDist = implicitGeom->getFunctionValue(currPos);
214 bool currIsInside = std::signbit(currDist);
217 if (prevIsInside && currIsInside)
219 if (m_prevOuterElementCounter[i] > 0)
222 m_prevOuterElementCounter[i]++;
224 const Vec3d start = m_prevOuterElement[i];
225 const Vec3d end = pt;
226 Vec3d contactPt = Vec3d::Zero();
227 if (findFirstRoot(implicitGeom, start, end, contactPt))
229 const Vec3d n = -m_centralGrad(contactPt).normalized();
230 const double depth = std::max(0.0, (contactPt - end).dot(n));
237 elemA.penetrationDepth = depth;
239 elementsA.push_back(elemA);
245 else if (!prevIsInside && currIsInside)
247 const Vec3d start = prevPt;
248 const Vec3d end = pt;
249 Vec3d contactPt = Vec3d::Zero();
250 if (findFirstRoot(implicitGeom, start, end, contactPt))
252 const Vec3d n = -m_centralGrad(contactPt).normalized();
253 const double depth = std::max(0.0, (contactPt - end).dot(n));
260 elemA.penetrationDepth = depth;
262 elementsA.push_back(elemA);
264 m_prevOuterElementCounter[i] = 1;
266 m_prevOuterElement[i] = start;
270 m_prevOuterElementCounter[i] = 0;
275 m_prevOuterElementCounter[i] = 0;
282 std::shared_ptr<Geometry> geomA,
283 std::shared_ptr<Geometry> geomB,
284 std::vector<CollisionElement>& elementsB)
287 std::shared_ptr<ImplicitGeometry> implicitGeom = std::dynamic_pointer_cast<
ImplicitGeometry>(geomA);
288 std::shared_ptr<PointSet> pointSet = std::dynamic_pointer_cast<
PointSet>(geomB);
289 setupFunctions(implicitGeom, pointSet);
293 std::shared_ptr<VecDataArray<double, 3>> vertexData = pointSet->getVertexPositions();
296 for (
int i = 0; i < vertices.size(); i++)
298 const Vec3d& pt = vertices[i];
299 const Vec3d& displacement = displacements[i];
300 const double limit = displacement.norm() * m_depthRatioLimit;
301 const Vec3d prevPt = pt - displacement;
303 Vec3d prevPos = prevPt;
304 double prevDist = implicitGeom->getFunctionValue(prevPos);
305 bool prevIsInside = std::signbit(prevDist);
308 double currDist = implicitGeom->getFunctionValue(currPos);
309 bool currIsInside = std::signbit(currDist);
312 if (prevIsInside && currIsInside)
314 if (m_prevOuterElementCounter[i] > 0)
317 m_prevOuterElementCounter[i]++;
319 const Vec3d start = m_prevOuterElement[i];
320 const Vec3d end = pt;
321 Vec3d contactPt = Vec3d::Zero();
322 if (findFirstRoot(implicitGeom, start, end, contactPt))
324 const Vec3d n = -m_centralGrad(contactPt).normalized();
325 const double depth = std::max(0.0, (contactPt - end).dot(n));
332 elemB.penetrationDepth = depth;
334 elementsB.push_back(elemB);
340 else if (!prevIsInside && currIsInside)
342 const Vec3d start = prevPt;
343 const Vec3d end = pt;
344 Vec3d contactPt = Vec3d::Zero();
345 if (findFirstRoot(implicitGeom, start, end, contactPt))
347 const Vec3d n = -m_centralGrad(contactPt).normalized();
348 const double depth = std::max(0.0, (contactPt - end).dot(n));
355 elemB.penetrationDepth = depth;
357 elementsB.push_back(elemB);
359 m_prevOuterElementCounter[i] = 1;
361 m_prevOuterElement[i] = start;
365 m_prevOuterElementCounter[i] = 0;
370 m_prevOuterElementCounter[i] = 0;
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
void computeCollisionDataA(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsA) override
Compute collision data for side A.
void computeCollisionDataAB(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsA, std::vector< CollisionElement > &elementsB) override
Compute collision data for AB simultaneously.
Direclty gives a point-direction contact as its collision data, point given by index.
void computeCollisionDataB(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsB) override
Compute collision data for side B.
Class that can represent the geometry of multiple implicit geometries as boolean functions One may su...
Direclty gives a point-direction contact as its collision data.