7 #include "imstkConnectiveStrandGenerator.h" 8 #include "imstkLogger.h" 9 #include "imstkSurfaceMesh.h" 10 #include "imstkLineMesh.h" 11 #include "imstkVecDataArray.h" 18 ConnectiveStrandGenerator::ConnectiveStrandGenerator()
21 setRequiredInputType<SurfaceMesh>(0);
22 setRequiredInputType<SurfaceMesh>(1);
29 ConnectiveStrandGenerator::setInputMeshes(
30 std::shared_ptr<SurfaceMesh> inputMeshA,
31 std::shared_ptr<SurfaceMesh> inputMeshB)
37 std::shared_ptr<LineMesh>
38 ConnectiveStrandGenerator::getOutputMesh()
const 40 return std::static_pointer_cast<LineMesh>(
getOutput(0));
52 meshB->computeTrianglesNormals();
54 std::vector<int> meshAFiltered =
filterCells(meshA.get(), meshB.get());
62 std::vector<int> result;
63 for (
int cell_idA = 0; cell_idA < meshA->
getNumCells(); cell_idA++)
67 double nearestDistSquared = IMSTK_DOUBLE_MAX;
73 for (
int cell_idB = 0; cell_idB < meshB->
getNumCells(); cell_idB++)
79 double distSquared = (cellBCenter - cellACenter).squaredNorm();
81 if (distSquared < nearestDistSquared)
83 nearestDistSquared = distSquared;
89 double dotCheck = meshA->getCellNormals()->at(cell_idA).dot(meshB->getCellNormals()->at(nearestId));
92 result.push_back(cell_idA);
98 std::shared_ptr<LineMesh>
101 const std::vector<int>& faces,
105 static std::random_device rd;
106 static std::mt19937 gen((static_cast<unsigned int>(time(
nullptr))));
107 std::uniform_int_distribution<> faceDistr(0, meshB->
getNumCells() - 1);
109 const int maxIteration = 10;
110 const double angleThreshold = cos(m_allowedAngleDeviation);
111 const Vec3d cardinalDirection = (meshA->
getCenter() - meshB->
getCenter()).normalized();
114 auto lineMeshVerticesPtr = std::make_shared<VecDataArray<double, 3>>();
115 auto lineMeshIndicesPtr = std::make_shared<VecDataArray<int, 2>>();
117 for (
int cell_idA = 0; cell_idA < faces.size(); cell_idA++)
122 int strandCount =
static_cast<int>(m_strandsPerFace);
123 double remainder = m_strandsPerFace - strandCount;
125 if (static_cast<float>(rand()) / static_cast<float>(RAND_MAX) < remainder)
131 for (
int surfNodeId = 0; surfNodeId < strandCount; surfNodeId++)
134 Vec3d positionOnB = Vec3d::Zero();
136 double bestThreshold = std::numeric_limits<double>::min();
137 Vec3d bestPositionB = Vec3d::Zero();
138 int iterationCount = 0;
143 int sideBindx = faceDistr(gen);
147 Vec3d directionBA = (positionOnA - positionOnB).normalized();
148 double dotCheck = meshB->getCellNormals()->at(sideBindx).dot(directionBA);
149 double inCardinalDirection = cardinalDirection.dot(directionBA);
155 if (inCardinalDirection > angleThreshold)
160 if (inCardinalDirection > bestThreshold)
162 bestThreshold = angleThreshold;
163 bestPositionB = positionOnB;
166 if (iterationCount > maxIteration)
168 positionOnB = bestPositionB;
174 if (positionOnB.isApprox(Vec3d::Zero()))
179 Vec3d stepVec = (positionOnB - positionOnA) / static_cast<double>(m_segmentsPerStrand);
181 int strandStartIndex = lineMeshVerticesPtr->size();
182 for (
int i = 0; i < m_segmentsPerStrand + 1; i++)
184 lineMeshVerticesPtr->push_back(positionOnA + static_cast<double>(i) * stepVec);
186 for (
int i = 0; i < m_segmentsPerStrand; ++i)
188 lineMeshIndicesPtr->push_back(Vec2i(strandStartIndex + i, strandStartIndex + i + 1));
193 auto result = std::make_shared<LineMesh>();
194 result->initialize(lineMeshVerticesPtr, lineMeshIndicesPtr);
201 float r0 =
static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
202 float r1 =
static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
208 return (1.0 - sqrt(r0)) * ptA + (sqrt(r0) * (1 - r1)) * ptB + (r1 * sqrt(r0)) * ptC;
std::shared_ptr< Geometry > getInput(size_t port=0) const
Returns input geometry given port, returns nullptr if doesn't exist.
void requestUpdate() override
Users can implement this for the logic to be run.
std::vector< int > filterCells(SurfaceMesh *meshA, SurfaceMesh *meshB) const
Filter faces on meshA to remove those facing away from meshB Checks nearest faces, if nearest face normal points in same general direction then ignore.
void setNumOutputPorts(const size_t numPorts)
Get/Set the amount of output ports.
int getNumCells() const override
Returns the number of cells.
virtual Vec3d getCenter()
Returns the bounding box center.
std::shared_ptr< Geometry > getOutput(size_t port=0) const
Returns output geometry given port, returns nullptr if doesn't exist.
const Vec3d & getVertexPosition(const size_t vertNum, DataType type=DataType::PostTransform) const
Returns the position of a vertex given its index.
void setInput(std::shared_ptr< Geometry > inputGeometry, size_t port=0)
Set the input at the port.
Represents a set of triangles & vertices via an array of Vec3d double vertices & Vec3i integer indice...
void setOutput(std::shared_ptr< Geometry > inputGeometry, const size_t port=0)
Set the output at the port.
void setNumInputPorts(const size_t numPorts)
Get/Set the amount of input ports.
const Vec3d generateRandomPointOnFace(SurfaceMesh *mesh, int face) const
void computeTrianglesNormals()
Compute the normals of all the triangles.
std::shared_ptr< LineMesh > createStrands(SurfaceMesh *meshA, const std::vector< int > &faces, SurfaceMesh *meshB) const
Creates a line mesh by connecting points of the given faces of meshA with with random points on rando...