diff --git a/Source/CollisionHandling/imstkPbdCollisionHandling.cpp b/Source/CollisionHandling/imstkPbdCollisionHandling.cpp index e101e9b1435b0f4ed24a29bef0fd99eb7f16ee07..92e1b4fd8799e7d55d293791214705f7f22d5e27 100644 --- a/Source/CollisionHandling/imstkPbdCollisionHandling.cpp +++ b/Source/CollisionHandling/imstkPbdCollisionHandling.cpp @@ -70,7 +70,7 @@ getVertex(const CollisionElement& elem, const MeshSide& side) auto oneToOneMap = dynamic_cast<OneToOneMap*>(side.m_mapPtr); if (side.m_mapPtr && oneToOneMap != nullptr) { - ptId = oneToOneMap->getMapIdx(ptId); + ptId = oneToOneMap->getParentVertexId(ptId); } results[0] = { &side.m_vertices[ptId], side.m_invMasses[ptId], &side.m_velocities[ptId] }; } @@ -102,8 +102,8 @@ getEdge(const CollisionElement& elem, const MeshSide& side) auto oneToOneMap = dynamic_cast<OneToOneMap*>(side.m_mapPtr); if (side.m_mapPtr && oneToOneMap != nullptr) { - v1 = oneToOneMap->getMapIdx(v1); - v2 = oneToOneMap->getMapIdx(v2); + v1 = oneToOneMap->getParentVertexId(v1); + v2 = oneToOneMap->getParentVertexId(v2); } results[0] = { &side.m_vertices[v1], side.m_invMasses[v1], &side.m_velocities[v1] }; results[1] = { &side.m_vertices[v2], side.m_invMasses[v2], &side.m_velocities[v2] }; @@ -138,9 +138,9 @@ getTriangle(const CollisionElement& elem, const MeshSide& side) auto oneToOneMap = dynamic_cast<OneToOneMap*>(side.m_mapPtr); if (side.m_mapPtr && oneToOneMap != nullptr) { - v1 = oneToOneMap->getMapIdx(v1); - v2 = oneToOneMap->getMapIdx(v2); - v3 = oneToOneMap->getMapIdx(v3); + v1 = oneToOneMap->getParentVertexId(v1); + v2 = oneToOneMap->getParentVertexId(v2); + v3 = oneToOneMap->getParentVertexId(v3); } results[0] = { &side.m_vertices[v1], side.m_invMasses[v1], &side.m_velocities[v1] }; results[1] = { &side.m_vertices[v2], side.m_invMasses[v2], &side.m_velocities[v2] }; diff --git a/Source/GeometryMappers/CMakeLists.txt b/Source/GeometryMappers/CMakeLists.txt index 9600114194912dc99a03f8621fcd4e0dd9d24b3f..44d0ea3eeeff662f3ca404938e65f885be8da3b2 100644 --- a/Source/GeometryMappers/CMakeLists.txt +++ b/Source/GeometryMappers/CMakeLists.txt @@ -4,7 +4,7 @@ include(imstkAddLibrary) imstk_add_library( GeometryMappers DEPENDS - Geometry + FilteringCore ) #----------------------------------------------------------------------------- diff --git a/Source/GeometryMappers/Testing/imstkOneToOneMapTest.cpp b/Source/GeometryMappers/Testing/imstkOneToOneMapTest.cpp index 18863fa983d8764f6c4b5323468ca3efa47d7385..efd06ce6fba2690400e607cea9ffa1a892da6030 100644 --- a/Source/GeometryMappers/Testing/imstkOneToOneMapTest.cpp +++ b/Source/GeometryMappers/Testing/imstkOneToOneMapTest.cpp @@ -19,14 +19,14 @@ =========================================================================*/ -#include "imstkSurfaceMesh.h" -#include "imstkPointSet.h" #include "imstkGeometry.h" #include "imstkOneToOneMap.h" +#include "imstkPointSet.h" +#include "imstkSphere.h" +#include "imstkSurfaceMesh.h" #include "imstkVecDataArray.h" #include <gtest/gtest.h> -#include "imstkSphere.h" using namespace imstk; @@ -71,16 +71,15 @@ TEST(imstkOneToOneMapTest, SimpleMap) OneToOneMap map; map.setParentGeometry(parent); map.setChildGeometry(child); - map.compute(); for (int i = 0; i < child->getNumVertices(); ++i) { - EXPECT_EQ(map.getMapIdx(i), i); + EXPECT_EQ(map.getParentVertexId(i), i); } parent->translate({ 1.0, 2.0, 3.0 }, Geometry::TransformType::ApplyToData); - map.apply(); + map.update(); for (int i = 0; i < child->getNumVertices(); ++i) { EXPECT_TRUE(parent->getVertexPosition(i).isApprox(child->getVertexPosition(i))); @@ -133,23 +132,22 @@ TEST(imstkOneToOneMapTest, OneToManyMap) map.setParentGeometry(parent); map.setChildGeometry(child); map.setTolerance(1e-8); - map.compute(); for (int i = 0; i < parent->getNumVertices(); ++i) { - EXPECT_EQ(map.getMapIdx(i), i); + EXPECT_EQ(map.getParentVertexId(i), i); } - EXPECT_EQ(map.getMapIdx(8), 2); + EXPECT_EQ(map.getParentVertexId(8), 2); - EXPECT_EQ(map.getMapIdx(9), IMSTK_NO_INDEX); + EXPECT_EQ(map.getParentVertexId(9), -1); parent->translate({ 1.0, 2.0, 3.0 }, Geometry::TransformType::ApplyToData); - map.apply(); + map.update(); for (int i = 0; i < child->getNumVertices() - 1; ++i) { - auto j = map.getMapIdx(i); + auto j = map.getParentVertexId(i); EXPECT_TRUE(child->getVertexPosition(i).isApprox(parent->getVertexPosition(j))) << "For " << i << ", " << j; } } diff --git a/Source/GeometryMappers/imstkGeometryMap.cpp b/Source/GeometryMappers/imstkGeometryMap.cpp index a1d362bbd3205753167f0ea973d8d504db37ca42..a8b46528ccb722c3bfdf0deef43ca7203c6f01fe 100644 --- a/Source/GeometryMappers/imstkGeometryMap.cpp +++ b/Source/GeometryMappers/imstkGeometryMap.cpp @@ -20,63 +20,20 @@ =========================================================================*/ #include "imstkGeometryMap.h" -#include "imstkLogger.h" +#include "imstkGeometry.h" namespace imstk { -void -GeometryMap::mute() +GeometryMap::GeometryMap() { - m_isActive = false; -} - -void -GeometryMap::activate() -{ - m_isActive = true; -} - -void -GeometryMap::print() const -{ - LOG(INFO) << this->getTypeName(); -} - -bool -GeometryMap::isActive() const -{ - return m_isActive; -} + // Set 2 ports for each, inputs will be set to outputs + setNumInputPorts(2); -void -GeometryMap::setParentGeometry(std::shared_ptr<Geometry> parent) -{ - m_parentGeom = parent; -} - -std::shared_ptr<Geometry> -GeometryMap::getParentGeometry() const -{ - return m_parentGeom; -} - -void -GeometryMap::setChildGeometry(std::shared_ptr<Geometry> child) -{ - m_childGeom = child; -} - -std::shared_ptr<Geometry> -GeometryMap::getChildGeometry() const -{ - return m_childGeom; -} - -void -GeometryMap::initialize() -{ - CHECK(this->isValid()) << "Map is invalid!"; + // Both inputs required + setRequiredInputType<Geometry>(0); + setRequiredInputType<Geometry>(1); - this->compute(); + // Set 1 output port, the child + setNumOutputPorts(1); } -} // namespace imstk \ No newline at end of file +} \ No newline at end of file diff --git a/Source/GeometryMappers/imstkGeometryMap.h b/Source/GeometryMappers/imstkGeometryMap.h index 64bb4b19e94e8d45680e1d117952bc3926dfec3e..7896c84c24ea5b19247f233fa9f78fbc14f8b275 100644 --- a/Source/GeometryMappers/imstkGeometryMap.h +++ b/Source/GeometryMappers/imstkGeometryMap.h @@ -21,19 +21,21 @@ #pragma once -#include "imstkGeometry.h" +#include "imstkGeometryAlgorithm.h" namespace imstk { +class Geometry; + /// /// \class GeometryMap /// /// \brief Base class for any geometric map /// -class GeometryMap +class GeometryMap : public GeometryAlgorithm { protected: - GeometryMap() : m_isActive(true) { } + GeometryMap(); public: virtual ~GeometryMap() = default; @@ -45,65 +47,22 @@ public: virtual const std::string getTypeName() const = 0; /// - /// \brief Compute the map - /// + /// \brief Compute the map, usually called once on startup + /// virtual void compute() = 0; - /// - /// \brief Apply the map - /// - virtual void apply() = 0; - - /// - /// \brief Print the map - /// - virtual void print() const; - - /// - /// \brief Deactivate the map - /// - void mute(); - - /// - /// \brief Check the validity of the map - /// - virtual bool isValid() const = 0; - - /// - /// \brief Activate the map - /// - void activate(); - - /// - /// \brief Returns true if the map is actively applied at runtime, else false. - /// - bool isActive() const; - - // Accessors - /// /// \brief Get/Set parent geometry ///@{ - virtual void setParentGeometry(std::shared_ptr<Geometry> parent); - virtual std::shared_ptr<Geometry> getParentGeometry() const; + void setParentGeometry(std::shared_ptr<Geometry> parent) { setInput(parent, 0); } + std::shared_ptr<Geometry> getParentGeometry() const { return getInput(0); } ///@} /// /// \brief Get/Set child geometry ///@{ - virtual void setChildGeometry(std::shared_ptr<Geometry> child); - virtual std::shared_ptr<Geometry> getChildGeometry() const; + void setChildGeometry(std::shared_ptr<Geometry> child) { setInput(child, 1); } + std::shared_ptr<Geometry> getChildGeometry() const { return getInput(1); } ///@} - - /// - /// \brief Initialize the map - /// - virtual void initialize(); - -protected: - bool m_isActive; ///> true if the map us active at runtime - - std::shared_ptr<Geometry> m_parentGeom; ///> the geometry which dictates the configuration - std::shared_ptr<Geometry> m_childGeom; ///> the geometry which follows the parent }; } // namespace imstk diff --git a/Source/GeometryMappers/imstkIdentityMap.cpp b/Source/GeometryMappers/imstkIdentityMap.cpp deleted file mode 100644 index 335cb82b703b4da4c4bbbadf17910f5fdfb196d8..0000000000000000000000000000000000000000 --- a/Source/GeometryMappers/imstkIdentityMap.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/*========================================================================= - - Library: iMSTK - - Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, - & Imaging in Medicine, Rensselaer Polytechnic Institute. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#include "imstkIdentityMap.h" -#include "imstkLogger.h" - -namespace imstk -{ -void -IdentityMap::apply() -{ - // Check Map active - if (!m_isActive) - { - LOG(WARNING) << "Identity map is not active"; - return; - } - - // Check geometries - CHECK(m_parentGeom != nullptr && m_childGeom != nullptr) << "Identity map is being applied without valid geometries"; - - // Set the child mesh configuration to be same as that of parent - m_childGeom->setTranslation(m_parentGeom->getTranslation()); - m_childGeom->setRotation(m_parentGeom->getRotation()); -} - -const RigidTransform3d -IdentityMap::getTransform() const -{ - return RigidTransform3d::Identity(); -} -} // namespace imstk \ No newline at end of file diff --git a/Source/GeometryMappers/imstkIdentityMap.h b/Source/GeometryMappers/imstkIdentityMap.h deleted file mode 100644 index d02783c4b837255de79f736a0f6aaacd5ca28dda..0000000000000000000000000000000000000000 --- a/Source/GeometryMappers/imstkIdentityMap.h +++ /dev/null @@ -1,69 +0,0 @@ -/*========================================================================= - - Library: iMSTK - - Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, - & Imaging in Medicine, Rensselaer Polytechnic Institute. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#pragma once - -#include "imstkGeometryMap.h" -#include "imstkMacros.h" - -namespace imstk -{ -/// -/// \class IdentityMap -/// -/// \brief A maps that lets the child follow the parent's position and orientation -/// -class IdentityMap : public GeometryMap -{ -public: - IdentityMap() { } - ~IdentityMap() override = default; - - IMSTK_TYPE_NAME(IdentityMap) - - /// - /// \brief Compute the map - /// - void compute() override {} - - /// - /// \brief Apply the map - /// - void apply() override; - - /// - /// \brief Check the validity of the map - /// - bool isValid() const override { return true; } - - // Accessors - - /// - /// \brief DISABLED: Set the transform of the Identity map - /// - void setTransform(const RigidTransform3d& affineTransform) = delete; - - /// - /// \brief Get the transform of Identity map which is an Identity (3x3) - /// - const RigidTransform3d getTransform() const; -}; -} // namespace imstk \ No newline at end of file diff --git a/Source/GeometryMappers/imstkIsometricMap.cpp b/Source/GeometryMappers/imstkIsometricMap.cpp index cb1f9752146ebca72c900f8e816d416f65520fce..7dcf58bdafc3f52606fd834f26430e88014c91c1 100644 --- a/Source/GeometryMappers/imstkIsometricMap.cpp +++ b/Source/GeometryMappers/imstkIsometricMap.cpp @@ -20,27 +20,14 @@ =========================================================================*/ #include "imstkIsometricMap.h" +#include "imstkGeometry.h" #include "imstkLogger.h" namespace imstk { void -IsometricMap::apply() +IsometricMap::requestUpdate() { - // Check Map active - if (!m_isActive) - { - LOG(WARNING) << "Isometric map is not active"; - return; - } - - // Check geometries - if (!m_parentGeom || !m_childGeom) - { - LOG(WARNING) << "Isometric map is being applied without valid geometries"; - return; - } - - m_childGeom->setTransform(m_parentGeom->getTransform()); + getChildGeometry()->setTransform(getParentGeometry()->getTransform()); } } // namespace imstk \ No newline at end of file diff --git a/Source/GeometryMappers/imstkIsometricMap.h b/Source/GeometryMappers/imstkIsometricMap.h index 6bc226cbd4f2937e13d831735d7b6b881f50e251..46109554d3733724aff76723d5cc196287dc7a49 100644 --- a/Source/GeometryMappers/imstkIsometricMap.h +++ b/Source/GeometryMappers/imstkIsometricMap.h @@ -34,14 +34,13 @@ namespace imstk class IsometricMap : public GeometryMap { public: - IsometricMap() { } - - IsometricMap(std::shared_ptr<Geometry> parent, std::shared_ptr<Geometry> child) + IsometricMap() = default; + IsometricMap(std::shared_ptr<Geometry> parent, + std::shared_ptr<Geometry> child) { this->setParentGeometry(parent); this->setChildGeometry(child); } - ~IsometricMap() override = default; IMSTK_TYPE_NAME(IsometricMap) @@ -49,19 +48,12 @@ public: /// /// \brief Compute the map /// - void compute() override {} + void compute() override { } +protected: /// /// \brief Apply the map /// - void apply() override; - - /// - /// \brief Check the validity of the map - /// - inline bool isValid() const override - { - return true; - } + void requestUpdate() override; }; } // namespace imstk \ No newline at end of file diff --git a/Source/GeometryMappers/imstkOneToOneMap.cpp b/Source/GeometryMappers/imstkOneToOneMap.cpp index da94d4a04aeda346ad765d805bd42cea26e0d3ae..8b7c35ab31c968c18007a875de418df9faf620c0 100644 --- a/Source/GeometryMappers/imstkOneToOneMap.cpp +++ b/Source/GeometryMappers/imstkOneToOneMap.cpp @@ -70,9 +70,9 @@ OneToOneMap::computeMap(std::unordered_map<int, int>& tetVertToSurfVertMap) auto meshParent = std::dynamic_pointer_cast<PointSet>(getParentGeometry()); auto meshChild = std::dynamic_pointer_cast<PointSet>(getChildGeometry()); - std::shared_ptr<VecDataArray<double, 3>> parentVerticesPtr = meshParent->getInitialVertexPositions(); + std::shared_ptr<VecDataArray<double, 3>> parentVerticesPtr = meshParent->getVertexPositions(); const VecDataArray<double, 3>& parentVertices = *parentVerticesPtr; - std::shared_ptr<VecDataArray<double, 3>> childVerticesPtr = meshChild->getInitialVertexPositions(); + std::shared_ptr<VecDataArray<double, 3>> childVerticesPtr = meshChild->getVertexPositions(); const VecDataArray<double, 3>& childVertices = *childVerticesPtr; // For every vertex on the child, find corresponding one on the parent @@ -146,16 +146,9 @@ OneToOneMap::requestUpdate() } int -OneToOneMap::getMapIdx(const int idx) const +OneToOneMap::getParentVertexId(const int childVertexId) const { - auto citer = m_oneToOneMap.find(idx); - if (citer != m_oneToOneMap.end()) - { - return citer->second; - } - else - { - return -1; - } + auto citer = m_oneToOneMap.find(childVertexId); + return (citer != m_oneToOneMap.end()) ? citer->second : -1; } } // namespace imstk \ No newline at end of file diff --git a/Source/GeometryMappers/imstkOneToOneMap.h b/Source/GeometryMappers/imstkOneToOneMap.h index 0fdc4a5b1b79ae22a7e19f446d6249d87f212344..abf12f8c8cef891dedfa5b59bd0705732277b9f2 100644 --- a/Source/GeometryMappers/imstkOneToOneMap.h +++ b/Source/GeometryMappers/imstkOneToOneMap.h @@ -17,12 +17,12 @@ #include "imstkGeometryMap.h" #include "imstkMacros.h" +#include "imstkMath.h" #include "imstkTypes.h" namespace imstk { template<typename T, int N> class VecDataArray; -class PointSet; /// /// \class OneToOneMap @@ -33,15 +33,10 @@ class PointSet; class OneToOneMap : public GeometryMap { public: - OneToOneMap() : GeometryMap() {} + OneToOneMap(); OneToOneMap( std::shared_ptr<Geometry> parent, - std::shared_ptr<Geometry> child) - { - this->setParentGeometry(parent); - this->setChildGeometry(child); - } - + std::shared_ptr<Geometry> child); ~OneToOneMap() override = default; IMSTK_TYPE_NAME(OneToOneMap) @@ -52,41 +47,21 @@ public: void compute() override; /// - /// \brief Check the validity of the map - /// - bool isValid() const override; + /// \brief Compute tet vertex id to surf vertex id map + /// + void computeMap(std::unordered_map<int, int>& tetVertToSurfVertMap); /// /// \brief Sets the one-to-one correspondence directly /// void setMap(const std::unordered_map<int, int>& sourceMap); - /// - /// \brief Apply (if active) the tetra-triangle mesh map - /// - void apply() override; - - /// - /// \brief Print the map - /// - void print() const override; - - /// - /// \brief Set the geometry that dictates the map - /// - void setParentGeometry(std::shared_ptr<Geometry> parent) override; - - /// - /// \brief Set the geometry that follows the parent - /// - void setChildGeometry(std::shared_ptr<Geometry> child) override; - /// /// \brief Get the mapped/corresponding parent index, given a child index. /// returns -1 if no correspondence found. /// \param index on the child geometry /// - int getMapIdx(const int idx) const; + int getParentVertexId(const int childVertexId) const; /// /// \brief Set/Get the tolerance. The distance to consider @@ -94,7 +69,7 @@ public: ///@{ void setTolerance(const double tolerance) { m_epsilon = tolerance; } double getTolerance() const { return m_epsilon; } -///@} + ///@} protected: /// @@ -102,6 +77,12 @@ protected: /// int findMatchingVertex(const VecDataArray<double, 3>& parentMesh, const Vec3d& p); + /// + /// \brief Apply (if active) the tetra-triangle mesh map + /// + void requestUpdate() override; + +public: // A map and vector are maintained. The vector for parallel processing, the map for fast lookup std::unordered_map<int, int> m_oneToOneMap; ///> One to one mapping data std::vector<std::pair<int, int>> m_oneToOneMapVector; ///> One to one mapping data diff --git a/Source/GeometryMappers/imstkTetraTriangleMap.cpp b/Source/GeometryMappers/imstkTetraTriangleMap.cpp index 01f5682e163b2b1f35b59e509fab34d37a2dbc57..79c67ebb136897d9aaf694273dbb8915068584fc 100644 --- a/Source/GeometryMappers/imstkTetraTriangleMap.cpp +++ b/Source/GeometryMappers/imstkTetraTriangleMap.cpp @@ -22,21 +22,38 @@ #include "imstkTetraTriangleMap.h" #include "imstkLogger.h" #include "imstkParallelUtils.h" -#include "imstkSurfaceMesh.h" #include "imstkTetrahedralMesh.h" #include "imstkVecDataArray.h" namespace imstk { -void -TetraTriangleMap::compute() +TetraTriangleMap::TetraTriangleMap() : m_boundingBoxAvailable(false) +{ + setRequiredInputType<TetrahedralMesh>(0); + setRequiredInputType<PointSet>(1); +} +TetraTriangleMap::TetraTriangleMap( + std::shared_ptr<Geometry> parent, + std::shared_ptr<Geometry> child) + : m_boundingBoxAvailable(false) { - CHECK(m_parentGeom && m_childGeom) << "TetraTriangle map is being applied without valid geometries"; + setRequiredInputType<TetrahedralMesh>(0); + setRequiredInputType<PointSet>(1); - auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(m_parentGeom); - auto triMesh = std::dynamic_pointer_cast<SurfaceMesh>(m_childGeom); + setParentGeometry(parent); + setChildGeometry(child); +} - CHECK(tetMesh && triMesh) << "Fail to cast from geometry to meshes"; +void +TetraTriangleMap::compute() +{ + if (!areInputsValid()) + { + LOG(WARNING) << "TetraTriangleMap failed to run, inputs not satisfied"; + return; + } + auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(getParentGeometry()); + auto triMesh = std::dynamic_pointer_cast<PointSet>(getChildGeometry()); m_verticesEnclosingTetraId.clear(); m_verticesWeights.clear(); @@ -51,7 +68,9 @@ TetraTriangleMap::compute() updateBoundingBox(); } - ParallelUtils::parallelFor(triMesh->getNumVertices(), [&](const size_t vertexIdx) { + ParallelUtils::parallelFor(triMesh->getNumVertices(), + [&](const int vertexIdx) + { if (!bValid) // If map is invalid, no need to check further { return; @@ -59,12 +78,12 @@ TetraTriangleMap::compute() const Vec3d& surfVertPos = triMesh->getVertexPosition(vertexIdx); // Find the enclosing or closest tetrahedron - size_t closestTetId = findEnclosingTetrahedron(surfVertPos); - if (closestTetId == std::numeric_limits<size_t>::max()) + int closestTetId = findEnclosingTetrahedron(surfVertPos); + if (closestTetId == IMSTK_INT_MAX) { closestTetId = findClosestTetrahedron(surfVertPos); } - if (closestTetId == std::numeric_limits<size_t>::max()) + if (closestTetId == IMSTK_INT_MAX) { LOG(WARNING) << "Could not find closest tetrahedron"; bValid = false; @@ -87,27 +106,18 @@ TetraTriangleMap::compute() } void -TetraTriangleMap::apply() +TetraTriangleMap::requestUpdate() { - // Check if map is active - if (!m_isActive) - { - LOG(WARNING) << "TetraTriangle map is not active"; - return; - } - - // Check geometries - CHECK(m_parentGeom && m_childGeom) << "TetraTriangle map is being applied without valid geometries"; - - auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(m_parentGeom); - auto triMesh = std::dynamic_pointer_cast<SurfaceMesh>(m_childGeom); - - CHECK(m_parentGeom != nullptr && m_childGeom != nullptr) << "Fail to cast from geometry to meshes"; + auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(getParentGeometry()); + auto pointSet = std::dynamic_pointer_cast<PointSet>(getChildGeometry()); VecDataArray<double, 3>& vertices = *m_childVerts; - ParallelUtils::parallelFor(triMesh->getNumVertices(), [&](const size_t vertexId) { - const Vec4i& tetVerts = tetMesh->getTetrahedronIndices(m_verticesEnclosingTetraId[vertexId]); - const auto& weights = m_verticesWeights[vertexId]; + ParallelUtils::parallelFor(pointSet->getNumVertices(), + [&](const int vertexId) + { + const Vec4i& tetVerts = + tetMesh->getTetrahedronIndices(m_verticesEnclosingTetraId[vertexId]); + const Vec4d& weights = m_verticesWeights[vertexId]; vertices[vertexId] = tetMesh->getVertexPosition(tetVerts[0]) * weights[0] + tetMesh->getVertexPosition(tetVerts[1]) * weights[1] + @@ -115,85 +125,28 @@ TetraTriangleMap::apply() tetMesh->getVertexPosition(tetVerts[3]) * weights[3]; }); - triMesh->postModified(); -} - -void -TetraTriangleMap::print() const -{ - // Print Type - GeometryMap::print(); + pointSet->postModified(); - // Print vertices and weight info - LOG(INFO) << "Vertex (<vertNum>): Tetrahedra: <TetNum> - Weights: (w1, w2, w3, w4)\n"; - for (size_t vertexId = 0; vertexId < m_verticesEnclosingTetraId.size(); ++vertexId) - { - LOG(INFO) << "Vertex (" << vertexId << "):" - << "\tTetrahedra: " << m_verticesEnclosingTetraId.at(vertexId) << " - Weights: " - << "(" << m_verticesWeights.at(vertexId)[0] << ", " - << m_verticesWeights.at(vertexId)[1] << ", " << m_verticesWeights.at(vertexId)[2] - << ", " << m_verticesWeights.at(vertexId)[3] << ")"; - } + setOutput(pointSet); } -bool -TetraTriangleMap::isValid() const -{ - auto meshParent = std::dynamic_pointer_cast<TetrahedralMesh>(m_parentGeom); - CHECK(m_parentGeom != nullptr) << "Fail to cast parent Geometry to TetrahedralMesh"; - - size_t totalElementsParent = static_cast<size_t>(meshParent->getNumTetrahedra()); - std::atomic<bool> bOK{ true }; - - ParallelUtils::parallelFor(m_verticesEnclosingTetraId.size(), [&](const size_t tetId) { - if (!bOK) // If map is invalid, no need to check further - { - return; - } - if (!(m_verticesEnclosingTetraId[tetId] < totalElementsParent)) - { - bOK = false; - } - }); - - return bOK; -} - -void -TetraTriangleMap::setParentGeometry(std::shared_ptr<Geometry> parent) -{ - CHECK(parent != nullptr) << "The parent geometry provided is nullptr"; - CHECK(std::dynamic_pointer_cast<TetrahedralMesh>(parent) != nullptr) << - "The parent geometry provided is not TetrahedralMesh"; - GeometryMap::setParentGeometry(parent); -} - -void -TetraTriangleMap::setChildGeometry(std::shared_ptr<Geometry> child) -{ - CHECK(child != nullptr) << "The child geometry provided is nullptr"; - CHECK(std::dynamic_pointer_cast<SurfaceMesh>(child) != nullptr) << - "The child geometry provided is not SurfaceMesh"; - GeometryMap::setChildGeometry(child); -} - -size_t +int TetraTriangleMap::findClosestTetrahedron(const Vec3d& pos) const { - auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(m_parentGeom); - double closestDistanceSqr = MAX_D; - size_t closestTetrahedron = std::numeric_limits<size_t>::max(); - Vec3d center(0, 0, 0); + auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(getParentGeometry()); + double closestDistanceSqr = IMSTK_DOUBLE_MAX; + int closestTetrahedron = IMSTK_INT_MAX; + Vec3d center(0.0, 0.0, 0.0); - for (int tetId = 0; tetId < tetMesh->getNumTetrahedra(); ++tetId) + for (int tetId = 0; tetId < tetMesh->getNumTetrahedra(); tetId++) { center = Vec3d::Zero(); const Vec4i& vert = tetMesh->getTetrahedronIndices(tetId); - for (size_t i = 0; i < 4; ++i) + for (int i = 0; i < 4; i++) { center += tetMesh->getInitialVertexPosition(vert[i]); } - center = center / 4.; + center = center / 4.0; const double distSqr = (pos - center).squaredNorm(); if (distSqr < closestDistanceSqr) @@ -206,15 +159,15 @@ TetraTriangleMap::findClosestTetrahedron(const Vec3d& pos) const return closestTetrahedron; } -size_t +int TetraTriangleMap::findEnclosingTetrahedron(const Vec3d& pos) const { - auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(m_parentGeom); - size_t enclosingTetrahedron = std::numeric_limits<size_t>::max(); + auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(getParentGeometry()); + int enclosingTetrahedron = IMSTK_INT_MAX; - for (int idx = 0; idx < tetMesh->getNumTetrahedra(); ++idx) + for (int idx = 0; idx < tetMesh->getNumTetrahedra(); idx++) { - bool inBox = (pos[0] >= m_bBoxMin[idx][0] && pos[0] <= m_bBoxMax[idx][0]) + const bool inBox = (pos[0] >= m_bBoxMin[idx][0] && pos[0] <= m_bBoxMax[idx][0]) && (pos[1] >= m_bBoxMin[idx][1] && pos[1] <= m_bBoxMax[idx][1]) && (pos[2] >= m_bBoxMin[idx][2] && pos[2] <= m_bBoxMax[idx][2]); @@ -226,7 +179,6 @@ TetraTriangleMap::findEnclosingTetrahedron(const Vec3d& pos) const } const Vec4d weights = tetMesh->computeBarycentricWeights(idx, pos); - if (weights[0] >= 0 && weights[1] >= 0 && weights[2] >= 0 && weights[3] >= 0) { enclosingTetrahedron = idx; @@ -240,12 +192,13 @@ TetraTriangleMap::findEnclosingTetrahedron(const Vec3d& pos) const void TetraTriangleMap::updateBoundingBox() { - /// \todo use parallelFor - auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(m_parentGeom); + auto tetMesh = std::dynamic_pointer_cast<TetrahedralMesh>(getParentGeometry()); m_bBoxMin.resize(tetMesh->getNumTetrahedra()); m_bBoxMax.resize(tetMesh->getNumTetrahedra()); - ParallelUtils::parallelFor(tetMesh->getNumTetrahedra(), [&](const size_t tid) { + ParallelUtils::parallelFor(tetMesh->getNumTetrahedra(), + [&](const int tid) + { tetMesh->computeTetrahedronBoundingBox(tid, m_bBoxMin[tid], m_bBoxMax[tid]); }); diff --git a/Source/GeometryMappers/imstkTetraTriangleMap.h b/Source/GeometryMappers/imstkTetraTriangleMap.h index 4e9d47d02feb97ea13447faa30bcaff9276b0a20..2ef707e0703d9646060c6fb3998b1446368f8f68 100644 --- a/Source/GeometryMappers/imstkTetraTriangleMap.h +++ b/Source/GeometryMappers/imstkTetraTriangleMap.h @@ -23,6 +23,7 @@ #include "imstkGeometryMap.h" #include "imstkMacros.h" +#include "imstkMath.h" namespace imstk { @@ -31,22 +32,17 @@ template<typename T, int N> class VecDataArray; /// /// \class TetraTriangleMap /// -/// \brief Computes and applies the triangle-tetrahedra map. The parent mesh is the -/// tetrahedral mesh and the child is the surface triangular mesh. +/// \brief Computes and applies the PointSet-Tetrahedra map. Vertices of the +/// child geometry are deformed according to the deformation of the tetrahedron +/// they are located in. If they are not within one, nearest tet is used. /// class TetraTriangleMap : public GeometryMap { public: - TetraTriangleMap() : m_boundingBoxAvailable(false) { } + TetraTriangleMap(); TetraTriangleMap( std::shared_ptr<Geometry> parent, - std::shared_ptr<Geometry> child) - : m_boundingBoxAvailable(false) - { - this->setParentGeometry(parent); - this->setChildGeometry(child); - } - + std::shared_ptr<Geometry> child); ~TetraTriangleMap() override = default; IMSTK_TYPE_NAME(TetraTriangleMap) @@ -56,36 +52,16 @@ public: /// void compute() override; +protected: /// /// \brief Apply (if active) the tetra-triangle mesh map /// - void apply() override; - - /// - /// \brief Print the map - /// - void print() const override; - - /// - /// \brief Check the validity of the map - /// - bool isValid() const override; + void requestUpdate() override; - /// - /// \brief Set the geometry that dictates the map - /// - void setParentGeometry(std::shared_ptr<Geometry> parent) override; - - /// - /// \brief Set the geometry that follows the parent - /// - void setChildGeometry(std::shared_ptr<Geometry> child) override; - -protected: /// /// \brief Find the tetrahedron that encloses a given point in 3D space /// - size_t findEnclosingTetrahedron(const Vec3d& pos) const; + int findEnclosingTetrahedron(const Vec3d& pos) const; /// /// \brief Update bounding box of each tetrahedra of the mesh @@ -96,11 +72,12 @@ protected: /// \brief Find the closest tetrahedron based on the distance to their centroids for a given /// point in 3D space /// - size_t findClosestTetrahedron(const Vec3d& pos) const; + int findClosestTetrahedron(const Vec3d& pos) const; +protected: std::vector<Vec4d> m_verticesWeights; ///> weights - std::vector<size_t> m_verticesEnclosingTetraId; ///> Enclosing tetrahedra to interpolate the weights upon + std::vector<int> m_verticesEnclosingTetraId; ///> Enclosing tetrahedra to interpolate the weights upon std::vector<Vec3d> m_bBoxMin; std::vector<Vec3d> m_bBoxMax; diff --git a/Source/SceneEntities/Objects/imstkCollidingObject.cpp b/Source/SceneEntities/Objects/imstkCollidingObject.cpp index 0c6ad615f4f9c4194600dbde8c49a030700a02a1..9cb3d9fd96b3dda43aeb91390db0bf86401821a7 100644 --- a/Source/SceneEntities/Objects/imstkCollidingObject.cpp +++ b/Source/SceneEntities/Objects/imstkCollidingObject.cpp @@ -20,6 +20,7 @@ =========================================================================*/ #include "imstkCollidingObject.h" +#include "imstkGeometry.h" #include "imstkGeometryMap.h" namespace imstk @@ -34,7 +35,7 @@ CollidingObject::initialize() if (m_collidingToVisualMap) { - m_collidingToVisualMap->initialize(); + m_collidingToVisualMap->compute(); } return true; @@ -69,7 +70,7 @@ CollidingObject::updateGeometries() { if (m_collidingToVisualMap) { - m_collidingToVisualMap->apply(); + m_collidingToVisualMap->update(); m_collidingToVisualMap->getChildGeometry()->postModified(); } SceneObject::updateGeometries(); diff --git a/Source/SceneEntities/Objects/imstkDynamicObject.cpp b/Source/SceneEntities/Objects/imstkDynamicObject.cpp index d4c1da38f46cc1501c6fd5337d4b6ae2e6ef22dc..adb1d5d42f23bf8957f8d25e49ec03116bfddc82 100644 --- a/Source/SceneEntities/Objects/imstkDynamicObject.cpp +++ b/Source/SceneEntities/Objects/imstkDynamicObject.cpp @@ -49,7 +49,7 @@ DynamicObject::updateGeometries() { if (m_physicsToVisualGeomMap) { - m_physicsToVisualGeomMap->apply(); + m_physicsToVisualGeomMap->update(); m_physicsToVisualGeomMap->getChildGeometry()->postModified(); } } @@ -66,7 +66,7 @@ DynamicObject::updatePhysicsGeometry() if (m_physicsToCollidingGeomMap) { - m_physicsToCollidingGeomMap->apply(); + m_physicsToCollidingGeomMap->update(); m_physicsToCollidingGeomMap->getChildGeometry()->postModified(); } @@ -83,12 +83,12 @@ DynamicObject::initialize() { if (m_physicsToCollidingGeomMap) { - m_physicsToCollidingGeomMap->initialize(); + m_physicsToCollidingGeomMap->compute(); } if (m_physicsToVisualGeomMap) { - m_physicsToVisualGeomMap->initialize(); + m_physicsToVisualGeomMap->compute(); } return m_dynamicalModel->initialize();