00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sofa/component/topology/QuadSetTopologyModifier.h>
00026 #include <sofa/component/topology/QuadSetTopologyChange.h>
00027 #include <sofa/component/topology/QuadSetTopologyContainer.h>
00028 #include <algorithm>
00029 #include <functional>
00030 #include <iostream>
00031 #include <sofa/core/ObjectFactory.h>
00032
00033 namespace sofa
00034 {
00035 namespace component
00036 {
00037 namespace topology
00038 {
00039 SOFA_DECL_CLASS(QuadSetTopologyModifier)
00040 int QuadSetTopologyModifierClass = core::RegisterObject("Quad set topology modifier")
00041 .add< QuadSetTopologyModifier >();
00042
00043
00044 using namespace std;
00045 using namespace sofa::defaulttype;
00046
00047
00048 void QuadSetTopologyModifier::init()
00049 {
00050 EdgeSetTopologyModifier::init();
00051 this->getContext()->get(m_container);
00052 }
00053
00054
00055 void QuadSetTopologyModifier::addQuadProcess(Quad t)
00056 {
00057 #ifndef NDEBUG
00058
00059 if((t[0]==t[1]) || (t[0]==t[2]) || (t[0]==t[3])
00060 || (t[1]==t[2]) || (t[1]==t[3]) || (t[2]==t[3]))
00061 {
00062 cout << "Error: [QuadSetTopologyModifier::addQuad] : invalid quad: "
00063 << t[0] << ", " << t[1] << ", " << t[2] << ", " << t[3] << endl;
00064
00065 return;
00066 }
00067
00068
00069
00070 if(m_container->hasQuadVertexShell())
00071 {
00072 if(m_container->getQuadIndex(t[0],t[1],t[2],t[3]) != -1)
00073 {
00074 cout << "Error: [QuadSetTopologyModifier::addQuad] : Quad "
00075 << t[0] << ", " << t[1] << ", " << t[2] << ", " << t[3] << " already exists." << endl;
00076 return;
00077 }
00078 }
00079 #endif
00080
00081 const unsigned int quadIndex = m_container->getNumberOfQuads();
00082
00083 if(m_container->hasQuadVertexShell())
00084 {
00085 for(unsigned int j=0;j<4;++j)
00086 {
00087 sofa::helper::vector< unsigned int > &shell = m_container->getQuadVertexShellForModification( t[j] );
00088 shell.push_back( quadIndex );
00089 }
00090 }
00091
00092 if(m_container->hasEdges())
00093 {
00094 for(unsigned int j=0; j<4; ++j)
00095 {
00096 int edgeIndex = m_container->getEdgeIndex(t[(j+1)%4], t[(j+2)%4]);
00097
00098 if(edgeIndex == -1)
00099 {
00100
00101 sofa::helper::vector< Edge > v(1);
00102 Edge e1 (t[(j+1)%4], t[(j+2)%4]);
00103 v[0] = e1;
00104
00105 addEdgesProcess((const sofa::helper::vector< Edge > &) v);
00106
00107 edgeIndex = m_container->getEdgeIndex(t[(j+1)%4],t[(j+2)%4]);
00108 sofa::helper::vector< unsigned int > edgeIndexList;
00109 edgeIndexList.push_back((unsigned int) edgeIndex);
00110 addEdgesWarning( v.size(), v, edgeIndexList);
00111 }
00112
00113 if(m_container->hasQuadEdges())
00114 {
00115 m_container->m_quadEdge.resize(quadIndex+1);
00116 m_container->m_quadEdge[quadIndex][j]= edgeIndex;
00117 }
00118
00119 if(m_container->hasQuadEdgeShell())
00120 {
00121 sofa::helper::vector< unsigned int > &shell = m_container->m_quadEdgeShell[m_container->m_quadEdge[quadIndex][j]];
00122 shell.push_back( quadIndex );
00123 }
00124 }
00125 }
00126
00127 m_container->m_quad.push_back(t);
00128 }
00129
00130
00131 void QuadSetTopologyModifier::addQuadsProcess(const sofa::helper::vector< Quad > &quads)
00132 {
00133 m_container->m_quad.reserve(m_container->m_quad.size() + quads.size());
00134
00135 for(unsigned int i=0; i<quads.size(); ++i)
00136 {
00137 addQuadProcess(quads[i]);
00138 }
00139 }
00140
00141
00142 void QuadSetTopologyModifier::addQuadsWarning(const unsigned int nQuads,
00143 const sofa::helper::vector< Quad >& quadsList,
00144 const sofa::helper::vector< unsigned int >& quadsIndexList)
00145 {
00146
00147 QuadsAdded *e = new QuadsAdded(nQuads, quadsList, quadsIndexList);
00148 addTopologyChange(e);
00149 }
00150
00151
00152 void QuadSetTopologyModifier::addQuadsWarning(const unsigned int nQuads,
00153 const sofa::helper::vector< Quad >& quadsList,
00154 const sofa::helper::vector< unsigned int >& quadsIndexList,
00155 const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors,
00156 const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs)
00157 {
00158
00159 QuadsAdded *e=new QuadsAdded(nQuads, quadsList,quadsIndexList,ancestors,baryCoefs);
00160 addTopologyChange(e);
00161 }
00162
00163
00164 void QuadSetTopologyModifier::removeQuadsWarning( sofa::helper::vector<unsigned int> &quads)
00165 {
00167 std::sort( quads.begin(), quads.end(), std::greater<unsigned int>() );
00168
00169
00170 QuadsRemoved *e=new QuadsRemoved(quads);
00171 addTopologyChange(e);
00172 }
00173
00174
00175 void QuadSetTopologyModifier::removeQuadsProcess(const sofa::helper::vector<unsigned int> &indices,
00176 const bool removeIsolatedEdges,
00177 const bool removeIsolatedPoints)
00178 {
00179 if(!m_container->hasQuads())
00180 {
00181 #ifndef NDEBUG
00182 cout << "Error. [QuadSetTopologyModifier::removeQuadsProcess] quad array is empty." << endl;
00183 #endif
00184 return;
00185 }
00186
00187 if(m_container->hasEdges() && removeIsolatedEdges)
00188 {
00189 if(!m_container->hasQuadEdges())
00190 m_container->createQuadEdgeArray();
00191
00192 if(!m_container->hasQuadEdgeShell())
00193 m_container->createQuadEdgeShellArray();
00194 }
00195
00196 if(removeIsolatedPoints)
00197 {
00198 if(!m_container->hasQuadVertexShell())
00199 m_container->createQuadVertexShellArray();
00200 }
00201
00202 sofa::helper::vector<unsigned int> edgeToBeRemoved;
00203 sofa::helper::vector<unsigned int> vertexToBeRemoved;
00204
00205 unsigned int lastQuad = m_container->getNumberOfQuads() - 1;
00206 for(unsigned int i=0; i<indices.size(); ++i, --lastQuad)
00207 {
00208 Quad &t = m_container->m_quad[ indices[i] ];
00209 Quad &q = m_container->m_quad[ lastQuad ];
00210
00211
00212 if(m_container->hasQuadVertexShell())
00213 {
00214 for(unsigned int v=0; v<4; ++v)
00215 {
00216 sofa::helper::vector< unsigned int > &shell = m_container->m_quadVertexShell[ t[v] ];
00217 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00218 if(removeIsolatedPoints && shell.empty())
00219 vertexToBeRemoved.push_back(t[v]);
00220 }
00221 }
00222
00223 if(m_container->hasQuadEdgeShell())
00224 {
00225 for(unsigned int e=0; e<4; ++e)
00226 {
00227 sofa::helper::vector< unsigned int > &shell = m_container->m_quadEdgeShell[ m_container->m_quadEdge[indices[i]][e]];
00228 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00229 if(removeIsolatedEdges && shell.empty())
00230 edgeToBeRemoved.push_back(m_container->m_quadEdge[indices[i]][e]);
00231 }
00232 }
00233
00234 if(indices[i] < lastQuad)
00235 {
00236
00237 if(m_container->hasQuadVertexShell())
00238 {
00239 for(unsigned int v=0; v<4; ++v)
00240 {
00241 sofa::helper::vector< unsigned int > &shell = m_container->m_quadVertexShell[ q[v] ];
00242 replace(shell.begin(), shell.end(), lastQuad, indices[i]);
00243 }
00244 }
00245
00246 if(m_container->hasQuadEdgeShell())
00247 {
00248 for(unsigned int e=0; e<4; ++e)
00249 {
00250 sofa::helper::vector< unsigned int > &shell = m_container->m_quadEdgeShell[ m_container->m_quadEdge[lastQuad][e]];
00251 replace(shell.begin(), shell.end(), lastQuad, indices[i]);
00252 }
00253 }
00254 }
00255
00256
00257 if(m_container->hasQuadEdges())
00258 {
00259 m_container->m_quadEdge[ indices[i] ] = m_container->m_quadEdge[ lastQuad ];
00260 m_container->m_quadEdge.resize( lastQuad );
00261 }
00262
00263
00264 m_container->m_quad[ indices[i] ] = m_container->m_quad[ lastQuad ];
00265 m_container->m_quad.resize( lastQuad );
00266 }
00267
00268 if(!edgeToBeRemoved.empty())
00269 {
00271 removeEdgesWarning(edgeToBeRemoved);
00272 propagateTopologicalChanges();
00274 removeEdgesProcess(edgeToBeRemoved,false);
00275 }
00276
00277 if(!vertexToBeRemoved.empty())
00278 {
00279 removePointsWarning(vertexToBeRemoved);
00281 propagateTopologicalChanges();
00282 removePointsProcess(vertexToBeRemoved);
00283 }
00284 }
00285
00286 void QuadSetTopologyModifier::addPointsProcess(const unsigned int nPoints)
00287 {
00288
00289 EdgeSetTopologyModifier::addPointsProcess( nPoints );
00290
00291
00292 if(m_container->hasQuadVertexShell())
00293 m_container->m_quadVertexShell.resize( m_container->getNbPoints() );
00294 }
00295
00296 void QuadSetTopologyModifier::addEdgesProcess(const sofa::helper::vector< Edge > &edges)
00297 {
00298 if(!m_container->hasEdges())
00299 {
00300 m_container->createEdgeSetArray();
00301 }
00302
00303
00304 EdgeSetTopologyModifier::addEdgesProcess( edges );
00305
00306 if(m_container->hasQuadEdgeShell())
00307 m_container->m_quadEdgeShell.resize( m_container->m_quadEdgeShell.size() + edges.size() );
00308 }
00309
00310 void QuadSetTopologyModifier::removePointsProcess( sofa::helper::vector<unsigned int> &indices,
00311 const bool removeDOF)
00312 {
00313 if(m_container->hasQuads())
00314 {
00315 if(!m_container->hasQuadVertexShell())
00316 m_container->createQuadVertexShellArray();
00317
00318 unsigned int lastPoint = m_container->getNbPoints() - 1;
00319 for(unsigned int i=0; i<indices.size(); ++i, --lastPoint)
00320 {
00321
00322
00323
00324 sofa::helper::vector<unsigned int> &shell = m_container->m_quadVertexShell[lastPoint];
00325 for(unsigned int j=0; j<shell.size(); ++j)
00326 {
00327 const unsigned int q = shell[j];
00328 for(unsigned int k=0; k<4; ++k)
00329 {
00330 if(m_container->m_quad[q][k] == lastPoint)
00331 m_container->m_quad[q][k] = indices[i];
00332 }
00333 }
00334
00335
00336 m_container->m_quadVertexShell[ indices[i] ] = m_container->m_quadVertexShell[ lastPoint ];
00337 }
00338
00339 m_container->m_quadVertexShell.resize( m_container->m_quadVertexShell.size() - indices.size() );
00340 }
00341
00342
00343
00344 EdgeSetTopologyModifier::removePointsProcess( indices, removeDOF );
00345 }
00346
00347 void QuadSetTopologyModifier::removeEdgesProcess( const sofa::helper::vector<unsigned int> &indices,
00348 const bool removeIsolatedItems)
00349 {
00350
00351
00352 if(m_container->hasQuadEdges())
00353 {
00354 if(!m_container->hasQuadEdgeShell())
00355 m_container->createQuadEdgeShellArray();
00356
00357 unsigned int lastEdge = m_container->getNumberOfEdges() - 1;
00358 for(unsigned int i = 0; i < indices.size(); ++i, --lastEdge)
00359 {
00360
00361
00362 for(sofa::helper::vector<unsigned int>::iterator itt = m_container->m_quadEdgeShell[lastEdge].begin();
00363 itt != m_container->m_quadEdgeShell[lastEdge].end(); ++itt)
00364 {
00365 unsigned int edgeIndex = m_container->getEdgeIndexInQuad(m_container->m_quadEdge[*itt], lastEdge);
00366 m_container->m_quadEdge[*itt][edgeIndex] = indices[i];
00367 }
00368
00369
00370 m_container->m_quadEdgeShell[ indices[i] ] = m_container->m_quadEdgeShell[ lastEdge ];
00371 }
00372
00373 m_container->m_quadEdgeShell.resize( m_container->getNumberOfEdges() - indices.size() );
00374 }
00375
00376
00377 EdgeSetTopologyModifier::removeEdgesProcess(indices, removeIsolatedItems);
00378 }
00379
00380 void QuadSetTopologyModifier::renumberPointsProcess( const sofa::helper::vector<unsigned int> &index,
00381 const sofa::helper::vector<unsigned int> &inv_index,
00382 const bool renumberDOF)
00383 {
00384 if(m_container->hasQuads())
00385 {
00386 if(m_container->hasQuadVertexShell())
00387 {
00388 sofa::helper::vector< sofa::helper::vector< unsigned int > > quadVertexShell_cp = m_container->m_quadVertexShell;
00389 for(unsigned int i=0; i<index.size(); ++i)
00390 {
00391 m_container->m_quadVertexShell[i] = quadVertexShell_cp[ index[i] ];
00392 }
00393 }
00394
00395 for(unsigned int i=0; i<m_container->m_quad.size(); ++i)
00396 {
00397 m_container->m_quad[i][0] = inv_index[ m_container->m_quad[i][0] ];
00398 m_container->m_quad[i][1] = inv_index[ m_container->m_quad[i][1] ];
00399 m_container->m_quad[i][2] = inv_index[ m_container->m_quad[i][2] ];
00400 m_container->m_quad[i][3] = inv_index[ m_container->m_quad[i][3] ];
00401 }
00402 }
00403
00404
00405 EdgeSetTopologyModifier::renumberPointsProcess( index, inv_index, renumberDOF );
00406 }
00407
00408 void QuadSetTopologyModifier::removeQuads(sofa::helper::vector< unsigned int >& quads,
00409 const bool removeIsolatedEdges,
00410 const bool removeIsolatedPoints)
00411 {
00413 removeQuadsWarning(quads);
00414
00415 propagateTopologicalChanges();
00416
00417 removeQuadsProcess( quads, removeIsolatedEdges, removeIsolatedPoints);
00418
00419 m_container->checkTopology();
00420 }
00421
00422 void QuadSetTopologyModifier::removeItems(sofa::helper::vector< unsigned int >& items)
00423 {
00424 removeQuads(items, true, true);
00425 }
00426
00427 void QuadSetTopologyModifier::renumberPoints( const sofa::helper::vector<unsigned int> &index,
00428 const sofa::helper::vector<unsigned int> &inv_index)
00429 {
00431 renumberPointsWarning(index, inv_index);
00432
00433 propagateTopologicalChanges();
00434
00435 renumberPointsProcess(index, inv_index);
00436
00437 m_container->checkTopology();
00438 }
00439
00440 }
00441
00442 }
00443
00444 }
00445