diff --git a/scenes/TopologyBenchmarks/Benchmark_01_TriangleCut_plane.scn.qglviewer.view b/scenes/TopologyBenchmarks/Benchmark_01_TriangleCut_plane.scn.qglviewer.view new file mode 100644 index 0000000..77a09d8 --- /dev/null +++ b/scenes/TopologyBenchmarks/Benchmark_01_TriangleCut_plane.scn.qglviewer.view @@ -0,0 +1,2 @@ +-4.56984 18.0925 3.09767 +-0.707107 -2.08167e-17 4.93754e-18 0.707107 diff --git a/scenes/TopologyBenchmarks/TriangleCut_benchmark-01_simpleCut.scn b/scenes/TopologyBenchmarks/TriangleCut_benchmark-01_simpleCut.scn new file mode 100644 index 0000000..2bb7859 --- /dev/null +++ b/scenes/TopologyBenchmarks/TriangleCut_benchmark-01_simpleCut.scn @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scenes/TopologyBenchmarks/TriangleCut_benchmark-01_simpleCut.scn.qglviewer.view b/scenes/TopologyBenchmarks/TriangleCut_benchmark-01_simpleCut.scn.qglviewer.view new file mode 100644 index 0000000..182337c --- /dev/null +++ b/scenes/TopologyBenchmarks/TriangleCut_benchmark-01_simpleCut.scn.qglviewer.view @@ -0,0 +1,2 @@ +-0.849029 46.9556 1.51729 +-0.707107 2.01511e-19 -2.01511e-19 0.707107 diff --git a/scenes/TopologyBenchmarks/TriangleCut_benchmark-02_snapping.scn b/scenes/TopologyBenchmarks/TriangleCut_benchmark-02_snapping.scn new file mode 100644 index 0000000..25caf58 --- /dev/null +++ b/scenes/TopologyBenchmarks/TriangleCut_benchmark-02_snapping.scn @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scenes/TopologyBenchmarks/TriangleCut_benchmark-02_snapping.scn.qglviewer.view b/scenes/TopologyBenchmarks/TriangleCut_benchmark-02_snapping.scn.qglviewer.view new file mode 100644 index 0000000..e048f83 --- /dev/null +++ b/scenes/TopologyBenchmarks/TriangleCut_benchmark-02_snapping.scn.qglviewer.view @@ -0,0 +1,2 @@ +2.82916e-17 49.6379 8.72903e-15 +-0.707107 2.01511e-19 -2.01511e-19 0.707107 diff --git a/scenes/TopologyBenchmarks/TriangleCut_benchmark-03_snapping.scn b/scenes/TopologyBenchmarks/TriangleCut_benchmark-03_snapping.scn new file mode 100644 index 0000000..eaf1d07 --- /dev/null +++ b/scenes/TopologyBenchmarks/TriangleCut_benchmark-03_snapping.scn @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scenes/TopologyBenchmarks/TriangleCut_benchmark-03_snapping.scn.qglviewer.view b/scenes/TopologyBenchmarks/TriangleCut_benchmark-03_snapping.scn.qglviewer.view new file mode 100644 index 0000000..088c644 --- /dev/null +++ b/scenes/TopologyBenchmarks/TriangleCut_benchmark-03_snapping.scn.qglviewer.view @@ -0,0 +1,2 @@ +-0.740008 44.5146 -4.62505 +-0.707107 6.93889e-18 1.14281e-17 0.707107 diff --git a/src/Tearing/Controllers/TriangleCuttingController.h b/src/Tearing/Controllers/TriangleCuttingController.h index 1927dcd..9deef8c 100644 --- a/src/Tearing/Controllers/TriangleCuttingController.h +++ b/src/Tearing/Controllers/TriangleCuttingController.h @@ -107,6 +107,9 @@ class TEARING_API TriangleCuttingController : public core::behavior::BaseControl type::vector< TriangleSubdivider*> m_subviders; type::vector< std::shared_ptr > m_pointsToAdd; + + type::vector m_addTriangles; + type::vector m_removedTriangles; }; diff --git a/src/Tearing/Controllers/TriangleCuttingController.inl b/src/Tearing/Controllers/TriangleCuttingController.inl index bf26d7c..afeb5b8 100644 --- a/src/Tearing/Controllers/TriangleCuttingController.inl +++ b/src/Tearing/Controllers/TriangleCuttingController.inl @@ -388,7 +388,7 @@ void TriangleCuttingController::processSubdividers() _ancestors.push_back(ptA->m_ancestors); _baryCoefs.push_back(ptA->m_coefs); - if (ptA->m_idClone != sofa::InvalidID) + if (ptA->m_idClone != sofa::InvalidID && ptA->m_idLocalSnap == sofa::InvalidID) { _ancestors.push_back(ptA->m_ancestors); _baryCoefs.push_back(ptA->m_coefs); @@ -396,6 +396,7 @@ void TriangleCuttingController::processSubdividers() } size_t nbrP = _ancestors.size(); + std::cout << "processSubdividers: nbrP: " << nbrP << std::endl; // 2. resize the point buffer in the topology // warn for the creation of all the points registered to be created @@ -417,6 +418,17 @@ void TriangleCuttingController::processSubdividers() } trianglesToRemove.push_back(triSub->getTriangleIdToSplit()); } + + for (auto tri : m_addTriangles) + { + trianglesToAdd.push_back(tri); + } + + for (auto triId : m_removedTriangles) + { + trianglesToRemove.push_back(triId); + } + std::cout << "Nbr trianglesToAdd: " << trianglesToAdd.size() << std::endl; m_topoModifier->addTriangles(trianglesToAdd, _ancestors, _baryCoefs); std::cout << "Nbr trianglesToRemove: " << trianglesToRemove.size() << std::endl; @@ -455,78 +467,107 @@ void TriangleCuttingController::processCut() sofa::type::vector< TriangleID > triangles_list; sofa::type::vector< EdgeID > edges_list; sofa::type::vector< Real > coords_list; - //m_geometryAlgorithms->computeIntersectedPointsList2(ptA, ptB, triIds[0], triIds[1], triangles_list, edges_list, coords_list); + + std::cout << "ptA: " << ptA << std::endl; + std::cout << "ptB: " << ptB << std::endl; + m_geometryAlgorithms->computeIntersectedPointsList2(ptA, ptB, triIds[0], triIds[1], triangles_list, edges_list, coords_list); - std::map < TriangleID, std::vector> > PTA_map; - // create map to store point to be added - //for (auto triId : triangles_list) - //{ - // auto tSplit = new TriangleToSplit(triId, triangles[triId]); - // TTS_map[triId] = tSplit; - //} + std::cout << "triangles_list: " << triangles_list << std::endl; + std::cout << "edges_list: " << edges_list << std::endl; + std::cout << "coords_list: " << coords_list << std::endl; - // create points To add + // create map to store point to be added + std::map < TriangleID, std::vector > > PTA_map; + std::map < Topology::PointID, Topology::PointID> cloneMap; + SReal snapThreshold = 0.8; + + // create points To add from start/end triangles -> TODO see snap possibility later for (unsigned int i = 0; i < 2; ++i) { - type::vector _coefs; - type::vector _ancestors; + type::vector _coefs = { 0.3333, 0.3333, 0.3333 }; + type::vector _ancestors = { theTris[i][0] , theTris[i][1], theTris[i][2] }; + Topology::PointID uniqID = getUniqueId(theTris[i][0], theTris[i][1], theTris[i][2]); - for (unsigned int j = 0; j < 3; ++j) - { - _ancestors.push_back(theTris[i][j]); - _coefs.push_back(0.3333); - } - std::cout << "triIds[i]: " << triIds[i] << std::endl; - std::cout << "theTris[i]: " << theTris[i] << std::endl; - Topology::PointID uniqID = getUniqueId(theTris[i][0], theTris[i][1]) + theTris[i][2]; std::shared_ptr PTA = std::make_shared(uniqID, nbrPoints, _ancestors, _coefs); PTA->m_ancestorType = sofa::geometry::ElementType::TRIANGLE; m_pointsToAdd.push_back(PTA); nbrPoints++; + // add to the map for later retrieving std::vector >& PTAs = PTA_map[triIds[i]]; - //if (tSplit == nullptr) { - // std::cout << "TTS_map not found" << std::endl; - // return; - //} PTAs.push_back(PTA); - //tSplit->m_points.push_back(PTA); + } + + // ProcessUpdate all coef due to the snapping + std::set psnap; + for (unsigned int i = 0; i < edges_list.size(); ++i) + { + const Topology::Edge& edge = edges[edges_list[i]]; + if (coords_list[i] > snapThreshold) + psnap.insert(edge[0]); + else if (1.0 - coords_list[i] > snapThreshold) + psnap.insert(edge[1]); } for (unsigned int i = 0; i < edges_list.size(); ++i) { - type::vector _coefs; - type::vector _ancestors; + const Topology::Edge& edge = edges[edges_list[i]]; + if (psnap.find(edge[0]) != psnap.end()) + coords_list[i] = 1.0; + else if (psnap.find(edge[1]) != psnap.end()) + coords_list[i] = 0.0; + } + // create PointToAdd from edges + for (unsigned int i = 0; i < edges_list.size(); ++i) + { const Topology::Edge& edge = edges[edges_list[i]]; - _ancestors.push_back(edge[0]); - _ancestors.push_back(edge[1]); - _coefs.push_back(coords_list[i]); // use them as weights if W == 1 -> point is on vertex. - _coefs.push_back(1.0 - coords_list[i]); + type::vector _coefs = { coords_list[i], 1.0 - coords_list[i] }; + type::vector _ancestors = { edge[0], edge[1] }; - Topology::PointID uniqID = getUniqueId(_ancestors[0], _ancestors[1]); - std::shared_ptr PTA = std::make_shared(uniqID, nbrPoints, _ancestors, _coefs); - PTA->m_ancestorType = sofa::geometry::ElementType::EDGE; - PTA->m_idClone = nbrPoints + 1; - m_pointsToAdd.push_back(PTA); - nbrPoints = nbrPoints + 2; + Topology::PointID uniqID = getUniqueId(edge[0], edge[1]); + std::shared_ptr PTA = std::make_shared(uniqID, nbrPoints, _ancestors, _coefs, snapThreshold); + bool snapped = PTA->updatePointIDForDuplication(); + if (snapped) + { + auto itM = cloneMap.find(PTA->m_idPoint); + if (itM == cloneMap.end()) + { + cloneMap[PTA->m_idPoint] = PTA->m_idClone; + m_pointsToAdd.push_back(PTA); + nbrPoints++; + } + else { + PTA = m_pointsToAdd.back(); + } + } + else + { + m_pointsToAdd.push_back(PTA); + nbrPoints = nbrPoints +2; + } const auto& triAEdge = triAEdges[edges_list[i]]; for (auto triId : triAEdge) - { - //TriangleToSplit* tSplit = TTS_map[triId]; - //tSplit->m_points.push_back(PTA); + { std::vector >& PTAs = PTA_map[triId]; PTAs.push_back(PTA); } } - + // Create subdividers and add PTA for (unsigned int i = 0; i < triangles_list.size(); ++i) { TriangleID triId = triangles_list[i]; - std::vector >& PTAs = PTA_map[triId]; - //TriangleToSplit* tSplit = TTS_map[triId]; + auto itM = PTA_map.find(triId); + if (itM == PTA_map.end()) + { + // TriangleSubdivider has been removed due to snapping + continue; + } + + std::vector >& PTAs = itM->second; + const Topology::Triangle& theTri = triangles[triId]; TriangleSubdivider* subdivider = new TriangleSubdivider(triId, theTri); sofa::type::fixed_array points = { x[theTri[0]], x[theTri[1]], x[theTri[2]] }; @@ -539,74 +580,76 @@ void TriangleCuttingController::processCut() } - // split path here - + //std::cout << "m_pointsToAdd: " << m_pointsToAdd.size() << std::endl; + //for (auto ptA : m_pointsToAdd) + //{ + // std::cout << ptA->m_uniqueID << " | ancestors: " << ptA->m_ancestors << " | " << ptA->m_coefs << std::endl; + //} + + + // Move that directly inside the subdividers + const sofa::type::Vec3 AB = x[theTris[0][1]] - x[theTris[0][0]]; + const sofa::type::Vec3 AC = x[theTris[0][2]] - x[theTris[0][0]]; + const sofa::type::Vec3 triNorm = AB.cross(AC); + const sofa::type::Vec3 cutPath = ptB - ptA; + + // create the list of new triangles around the inside path - std::map < Topology::PointID, type::vector > TTA_map; - std::map < Topology::PointID, Topology::PointID> cloneMap; for (auto triSub : m_subviders) { - const type::vector& TTAS = triSub->getTrianglesToAdd(); - const type::vector>& PTAS = triSub->getPointsToAdd(); - for (unsigned int i = 0; i < TTAS.size(); ++i) + triSub->cutTriangles(ptA, ptB, triNorm); + } + + // need to split snapped point in existing triangles + m_addTriangles.clear(); + m_removedTriangles.clear(); + for (auto itM : cloneMap) + { + std::cout << "need to update triangles arount v: " << itM.first << " -> " << itM.second << std::endl; + const auto& triAV = m_topoContainer->getTrianglesAroundVertex(itM.first); + for (TriangleID triId : triAV) { - Topology::Triangle newTri = TTAS[i]->m_triangle; - for (unsigned int j = 0; j < PTAS.size(); ++j) + bool found = false; + for (auto triSub : m_subviders) { - if (PTAS[j]->m_ancestorType == sofa::geometry::ElementType::TRIANGLE) - continue; - - Topology::PointID idNewPoint = PTAS[j]->m_idPoint; - cloneMap[idNewPoint] = PTAS[j]->m_idClone; - for (unsigned int k = 0; k < 3; ++k) + if (triSub->getTriangleIdToSplit() == triId) // already in subdivider { - if (newTri[k] == idNewPoint) - { - type::vector tris = TTA_map[idNewPoint]; - tris.push_back(TTAS[i]); - TTA_map[idNewPoint] = tris; - break; - } + found = true; + break; } } - } - } - const sofa::type::Vec3 AB = x[theTris[0][1]] - x[theTris[0][0]]; - const sofa::type::Vec3 AC = x[theTris[0][2]] - x[theTris[0][0]]; - const sofa::type::Vec3 triNorm = AB.cross(AC); - const sofa::type::Vec3 cutPath = ptB - ptA; + if (found) + continue; - for (auto it = TTA_map.begin(); it != TTA_map.end(); ++it) - { - const type::vector& TTAS = it->second; - Topology::PointID idClone = cloneMap[it->first]; - for (unsigned int i = 0; i < TTAS.size(); ++i) - { - TriangleToAdd* TTA = TTAS[i]; + Triangle tri = triangles[triId]; + sofa::type::Vec3 _gravityCenter = (x[tri[0]] + x[tri[1]] + x[tri[2]]) / 3; - const sofa::type::fixed_array& triCoords = TTA->m_triCoords; - sofa::type::Vec3 m_gravityCenter = (triCoords[0] + triCoords[1] + triCoords[2]) / 3; - sofa::type::Vec3 triCutNorm = cutPath.cross(m_gravityCenter - ptA); + sofa::type::Vec3 triCutNorm = cutPath.cross(_gravityCenter - ptA); SReal dotValue = triCutNorm * triNorm; if (dotValue < 0) { - TTA->isUp = false; - for (unsigned int j = 0; j < 3; ++j) + for (unsigned int k = 0; k < 3; ++k) { - if (TTA->m_triangle[j] == it->first) - TTA->m_triangle[j] = idClone; - } + if (tri[k] == itM.first) + { + tri[k] = itM.second; + break; + } + } + + std::cout << "add Tri: " << tri << " to replace triId: " << triId << std::endl; + m_addTriangles.push_back(tri); + m_removedTriangles.push_back(triId); } - else - TTA->isUp = true; } + } - std::cout << "triangles_list: " << triangles_list << std::endl; - std::cout << "edges_list: " << edges_list << std::endl; - std::cout << "coords_list: " << coords_list << std::endl; + // split path here + if (!d_performCut.getValue()) + return; processSubdividers(); } @@ -639,47 +682,51 @@ void TriangleCuttingController::draw(const core::visual::VisualParams if (!d_drawDebugCut.getValue()) return; + const auto stateLifeCycle = vparams->drawTool()->makeStateLifeCycle(); + sofa::type::RGBAColor colorL = sofa::type::RGBAColor::red(); vparams->drawTool()->drawLine(d_cutPointA.getValue(), d_cutPointB.getValue(), colorL); - std::vector spheresUp, spheresDown;// , float radius, const type::RGBAColor& color - std::vector pointsUp, pointsDown; - int cpt = 0; - for (auto triSub : m_subviders) + sofa::helper::ReadAccessor x = m_state->read(sofa::core::ConstVecCoordId::position())->getValue(); + + std::vector points; + for (auto ptA : m_pointsToAdd) { - if (cpt == 20000) - break; - - const type::vector& TTAS = triSub->getTrianglesToAdd(); - const type::vector>& PTAS = triSub->getPointsToAdd(); - for (unsigned int i = 0; i < TTAS.size(); ++i) + sofa::type::Vec3 vecG = sofa::type::Vec3(0.0, 0.0, 0.0); + sofa::Size nbr = ptA->m_ancestors.size(); + for (int i = 0; i < nbr; ++i) { - TriangleToAdd* TTA = TTAS[i]; - sofa::type::fixed_array triCoords = TTA->m_triCoords; - sofa::type::Vec3 vecG = (triCoords[0] + triCoords[1] + triCoords[2]) / 3;; - if (TTA->isUp) - { - pointsUp.push_back(triCoords[0]); - pointsUp.push_back(triCoords[1]); - pointsUp.push_back(triCoords[2]); - spheresUp.push_back(vecG); - } - else - { - pointsDown.push_back(triCoords[0]); - pointsDown.push_back(triCoords[1]); - pointsDown.push_back(triCoords[2]); - spheresDown.push_back(vecG); - } + vecG += x[ptA->m_ancestors[i]] * ptA->m_coefs[i]; } - - cpt++; + points.push_back(vecG); } + vparams->drawTool()->drawSpheres(points, 0.1, sofa::type::RGBAColor::red()); + + //std::vector pointsUp, pointsDown; + //for (auto triSub : m_subviders) + //{ + // const type::vector& TTAS = triSub->getTrianglesToAdd(); + // for (unsigned int i = 0; i < TTAS.size(); ++i) + // { + // TriangleToAdd* TTA = TTAS[i]; + // sofa::type::fixed_array triCoords = TTA->m_triCoords; + // if (TTA->isUp) + // { + // pointsUp.push_back(triCoords[0]); + // pointsUp.push_back(triCoords[1]); + // pointsUp.push_back(triCoords[2]); + // } + // else + // { + // pointsDown.push_back(triCoords[0]); + // pointsDown.push_back(triCoords[1]); + // pointsDown.push_back(triCoords[2]); + // } + // } + //} - vparams->drawTool()->drawTriangles(pointsUp, sofa::type::RGBAColor::red()); - vparams->drawTool()->drawTriangles(pointsDown, sofa::type::RGBAColor::green()); - vparams->drawTool()->drawSpheres(spheresUp, 0.01, sofa::type::RGBAColor::red()); - vparams->drawTool()->drawSpheres(spheresDown, 0.01, sofa::type::RGBAColor::green()); + //vparams->drawTool()->drawTriangles(pointsUp, sofa::type::RGBAColor::red()); + //vparams->drawTool()->drawTriangles(pointsDown, sofa::type::RGBAColor::green()); }