void HexahedronSetTopologyModifier::removeHexahedraProcess( const sofa::helper::vector<unsigned int> &indices, const bool removeIsolatedItems) { if(!m_container->hasHexahedra()) return; bool removeIsolatedVertices = removeIsolatedItems && removeIsolated.getValue(); bool removeIsolatedEdges = removeIsolatedItems && m_container->hasEdges(); bool removeIsolatedQuads = removeIsolatedItems && m_container->hasQuads(); if(removeIsolatedVertices) { if(!m_container->hasHexahedraAroundVertex()) m_container->createHexahedraAroundVertexArray(); } if(removeIsolatedEdges) { if(!m_container->hasHexahedraAroundEdge()) m_container->createHexahedraAroundEdgeArray(); } if(removeIsolatedQuads) { if(!m_container->hasHexahedraAroundQuad()) m_container->createHexahedraAroundQuadArray(); } sofa::helper::vector<unsigned int> quadToBeRemoved; sofa::helper::vector<unsigned int> edgeToBeRemoved; sofa::helper::vector<unsigned int> vertexToBeRemoved; unsigned int lastHexahedron = m_container->getNumberOfHexahedra() - 1; helper::WriteAccessor< Data< sofa::helper::vector<Hexahedron> > > m_hexahedron = m_container->d_hexahedron; for(unsigned int i=0; i<indices.size(); ++i, --lastHexahedron) { const Hexahedron &t = m_hexahedron[ indices[i] ]; const Hexahedron &h = m_hexahedron[ lastHexahedron ]; if(m_container->hasHexahedraAroundVertex()) { for(unsigned int v=0; v<8; ++v) { sofa::helper::vector< unsigned int > &shell = m_container->m_hexahedraAroundVertex[ t[v] ]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedVertices && shell.empty()) vertexToBeRemoved.push_back(t[v]); } } if(m_container->hasHexahedraAroundEdge()) { for(unsigned int e=0; e<12; ++e) { sofa::helper::vector< unsigned int > &shell = m_container->m_hexahedraAroundEdge[ m_container->m_edgesInHexahedron[indices[i]][e]]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedEdges && shell.empty()) edgeToBeRemoved.push_back(m_container->m_edgesInHexahedron[indices[i]][e]); } } if(m_container->hasHexahedraAroundQuad()) { for(unsigned int q=0; q<6; ++q) { sofa::helper::vector< unsigned int > &shell = m_container->m_hexahedraAroundQuad[ m_container->m_quadsInHexahedron[indices[i]][q]]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedQuads && shell.empty()) quadToBeRemoved.push_back(m_container->m_quadsInHexahedron[indices[i]][q]); } } // now updates the shell information of the edge formely at the end of the array if( indices[i] < lastHexahedron ) { if(m_container->hasHexahedraAroundVertex()) { for(unsigned int v=0; v<8; ++v) { sofa::helper::vector< unsigned int > &shell = m_container->m_hexahedraAroundVertex[ h[v] ]; replace(shell.begin(), shell.end(), lastHexahedron, indices[i]); } } if(m_container->hasHexahedraAroundEdge()) { for(unsigned int e=0; e<12; ++e) { sofa::helper::vector< unsigned int > &shell = m_container->m_hexahedraAroundEdge[ m_container->m_edgesInHexahedron[lastHexahedron][e]]; replace(shell.begin(), shell.end(), lastHexahedron, indices[i]); } } if(m_container->hasHexahedraAroundQuad()) { for(unsigned int q=0; q<6; ++q) { sofa::helper::vector< unsigned int > &shell = m_container->m_hexahedraAroundQuad[ m_container->m_quadsInHexahedron[lastHexahedron][q]]; replace(shell.begin(), shell.end(), lastHexahedron, indices[i]); } } } if(m_container->hasQuadsInHexahedron()) { // removes the quadsInHexahedrons from the quadsInHexahedronArray m_container->m_quadsInHexahedron[ indices[i] ] = m_container->m_quadsInHexahedron[ lastHexahedron ]; // overwriting with last valid value. m_container->m_quadsInHexahedron.resize( lastHexahedron ); // resizing to erase multiple occurence of the hexa. } if(m_container->hasEdgesInHexahedron()) { // removes the edgesInHexahedrons from the edgesInHexahedronArray m_container->m_edgesInHexahedron[ indices[i] ] = m_container->m_edgesInHexahedron[ lastHexahedron ]; // overwriting with last valid value. m_container->m_edgesInHexahedron.resize( lastHexahedron ); // resizing to erase multiple occurence of the hexa. } // removes the hexahedron from the hexahedronArray m_hexahedron[ indices[i] ] = m_hexahedron[ lastHexahedron ]; // overwriting with last valid value. m_hexahedron.resize( lastHexahedron ); // resizing to erase multiple occurence of the hexa. } if( (!quadToBeRemoved.empty()) || (!edgeToBeRemoved.empty())) { if(!quadToBeRemoved.empty()) { /// warn that quads will be deleted removeQuadsWarning(quadToBeRemoved); } if(!edgeToBeRemoved.empty()) { /// warn that edges will be deleted removeEdgesWarning(edgeToBeRemoved); } propagateTopologicalChanges(); if(!quadToBeRemoved.empty()) { /// actually remove quads without looking for isolated vertices removeQuadsProcess(quadToBeRemoved, false, false); } if(!edgeToBeRemoved.empty()) { /// actually remove edges without looking for isolated vertices removeEdgesProcess(edgeToBeRemoved, false); } } if(!vertexToBeRemoved.empty()) { removePointsWarning(vertexToBeRemoved); propagateTopologicalChanges(); removePointsProcess(vertexToBeRemoved); } }
void TriangleSetTopologyModifier::removeTrianglesProcess(const sofa::helper::vector<unsigned int> &indices, const bool removeIsolatedEdges, const bool removeIsolatedPoints) { if(!m_container->hasTriangles()) // this method should only be called when triangles exist { #ifndef NDEBUG sout << "Error. [TriangleSetTopologyModifier::removeTrianglesProcess] triangle array is empty." << endl; #endif return; } if(m_container->hasEdges() && removeIsolatedEdges) { if(!m_container->hasEdgesInTriangle()) m_container->createEdgesInTriangleArray(); if(!m_container->hasTrianglesAroundEdge()) m_container->createTrianglesAroundEdgeArray(); } if(removeIsolatedPoints) { if(!m_container->hasTrianglesAroundVertex()) m_container->createTrianglesAroundVertexArray(); } sofa::helper::vector<unsigned int> edgeToBeRemoved; sofa::helper::vector<unsigned int> vertexToBeRemoved; helper::WriteAccessor< Data< sofa::helper::vector<Triangle> > > m_triangle = m_container->d_triangle; unsigned int lastTriangle = m_container->getNumberOfTriangles() - 1; for(unsigned int i = 0; i<indices.size(); ++i, --lastTriangle) { Triangle &t = m_triangle[ indices[i] ]; Triangle &q = m_triangle[ lastTriangle ]; if(m_container->hasTrianglesAroundVertex()) { for(unsigned int j=0; j<3; ++j) { sofa::helper::vector< unsigned int > &shell = m_container->m_trianglesAroundVertex[ t[j] ]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedPoints && shell.empty()) vertexToBeRemoved.push_back(t[j]); } } if(m_container->hasTrianglesAroundEdge()) { for(unsigned int j=0; j<3; ++j) { sofa::helper::vector< unsigned int > &shell = m_container->m_trianglesAroundEdge[ m_container->m_edgesInTriangle[indices[i]][j]]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedEdges && shell.empty()) edgeToBeRemoved.push_back(m_container->m_edgesInTriangle[indices[i]][j]); } } if(indices[i] < lastTriangle) { if(m_container->hasTrianglesAroundVertex()) { for(unsigned int j=0; j<3; ++j) { sofa::helper::vector< unsigned int > &shell = m_container->m_trianglesAroundVertex[ q[j] ]; replace(shell.begin(), shell.end(), lastTriangle, indices[i]); } } if(m_container->hasTrianglesAroundEdge()) { for(unsigned int j=0; j<3; ++j) { sofa::helper::vector< unsigned int > &shell = m_container->m_trianglesAroundEdge[ m_container->m_edgesInTriangle[lastTriangle][j]]; replace(shell.begin(), shell.end(), lastTriangle, indices[i]); } } } // removes the edgesInTriangles from the edgesInTrianglesArray if(m_container->hasEdgesInTriangle()) { m_container->m_edgesInTriangle[ indices[i] ] = m_container->m_edgesInTriangle[ lastTriangle ]; // overwriting with last valid value. m_container->m_edgesInTriangle.resize( lastTriangle ); // resizing to erase multiple occurence of the triangle. } // removes the triangle from the triangleArray m_triangle[ indices[i] ] = m_triangle[ lastTriangle ]; // overwriting with last valid value. m_triangle.resize( lastTriangle ); // resizing to erase multiple occurence of the triangle. } removeTrianglesPostProcessing(edgeToBeRemoved, vertexToBeRemoved); // Arrange the current topology. if(!edgeToBeRemoved.empty()) { /// warn that edges will be deleted removeEdgesWarning(edgeToBeRemoved); propagateTopologicalChanges(); /// actually remove edges without looking for isolated vertices removeEdgesProcess(edgeToBeRemoved, false); } if(!vertexToBeRemoved.empty()) { removePointsWarning(vertexToBeRemoved); /// propagate to all components propagateTopologicalChanges(); removePointsProcess(vertexToBeRemoved); } /* #ifndef NDEBUG // TO BE REMOVED WHEN SURE. Debug(); #endif */ }
void QuadSetTopologyModifier::removeQuadsProcess(const sofa::helper::vector<unsigned int> &indices, const bool removeIsolatedEdges, const bool removeIsolatedPoints) { if(!m_container->hasQuads()) // this method should only be called when quads exist { #ifndef NDEBUG sout << "Error. [QuadSetTopologyModifier::removeQuadsProcess] quad array is empty." << sendl; #endif return; } if(m_container->hasEdges() && removeIsolatedEdges) { if(!m_container->hasEdgesInQuad()) m_container->createEdgesInQuadArray(); if(!m_container->hasQuadsAroundEdge()) m_container->createQuadsAroundEdgeArray(); } if(removeIsolatedPoints) { if(!m_container->hasQuadsAroundVertex()) m_container->createQuadsAroundVertexArray(); } sofa::helper::vector<unsigned int> edgeToBeRemoved; sofa::helper::vector<unsigned int> vertexToBeRemoved; helper::WriteAccessor< Data< sofa::helper::vector<Quad> > > m_quad = m_container->d_quad; unsigned int lastQuad = m_container->getNumberOfQuads() - 1; for(unsigned int i=0; i<indices.size(); ++i, --lastQuad) { const Quad &t = m_quad[ indices[i] ]; const Quad &q = m_quad[ lastQuad ]; // first check that the quad vertex shell array has been initialized if(m_container->hasQuadsAroundVertex()) { for(unsigned int v=0; v<4; ++v) { sofa::helper::vector< unsigned int > &shell = m_container->m_quadsAroundVertex[ t[v] ]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedPoints && shell.empty()) vertexToBeRemoved.push_back(t[v]); } } if(m_container->hasQuadsAroundEdge()) { for(unsigned int e=0; e<4; ++e) { sofa::helper::vector< unsigned int > &shell = m_container->m_quadsAroundEdge[ m_container->m_edgesInQuad[indices[i]][e]]; shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end()); if(removeIsolatedEdges && shell.empty()) edgeToBeRemoved.push_back(m_container->m_edgesInQuad[indices[i]][e]); } } if(indices[i] < lastQuad) { // now updates the shell information of the quad at the end of the array if(m_container->hasQuadsAroundVertex()) { for(unsigned int v=0; v<4; ++v) { sofa::helper::vector< unsigned int > &shell = m_container->m_quadsAroundVertex[ q[v] ]; replace(shell.begin(), shell.end(), lastQuad, indices[i]); } } if(m_container->hasQuadsAroundEdge()) { for(unsigned int e=0; e<4; ++e) { sofa::helper::vector< unsigned int > &shell = m_container->m_quadsAroundEdge[ m_container->m_edgesInQuad[lastQuad][e]]; replace(shell.begin(), shell.end(), lastQuad, indices[i]); } } } // removes the edgesInQuads from the edgesInQuadsArray if(m_container->hasEdgesInQuad()) { m_container->m_edgesInQuad[ indices[i] ] = m_container->m_edgesInQuad[ lastQuad ]; // overwriting with last valid value. m_container->m_edgesInQuad.resize( lastQuad ); // resizing to erase multiple occurence of the quad. } // removes the quad from the quadArray m_quad[ indices[i] ] = m_quad[ lastQuad ]; // overwriting with last valid value. m_quad.resize( lastQuad ); // resizing to erase multiple occurence of the quad. } if(!edgeToBeRemoved.empty()) { /// warn that edges will be deleted removeEdgesWarning(edgeToBeRemoved); propagateTopologicalChanges(); /// actually remove edges without looking for isolated vertices removeEdgesProcess(edgeToBeRemoved,false); } if(!vertexToBeRemoved.empty()) { removePointsWarning(vertexToBeRemoved); /// propagate to all components propagateTopologicalChanges(); removePointsProcess(vertexToBeRemoved); } }