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
00026
00027
00028 #include "SMESH_Algo.hxx"
00029 #include "SMESH_Comment.hxx"
00030 #include "SMESH_Gen.hxx"
00031 #include "SMESH_Mesh.hxx"
00032 #include "SMESH_HypoFilter.hxx"
00033 #include "SMDS_FacePosition.hxx"
00034 #include "SMDS_EdgePosition.hxx"
00035 #include "SMDS_MeshElement.hxx"
00036 #include "SMDS_MeshNode.hxx"
00037 #include "SMESHDS_Mesh.hxx"
00038 #include "SMESHDS_SubMesh.hxx"
00039
00040 #include <BRepAdaptor_Curve.hxx>
00041 #include <BRepLProp.hxx>
00042 #include <BRep_Tool.hxx>
00043 #include <GCPnts_AbscissaPoint.hxx>
00044 #include <GeomAdaptor_Curve.hxx>
00045 #include <Geom_Surface.hxx>
00046 #include <TopExp.hxx>
00047 #include <TopLoc_Location.hxx>
00048 #include <TopTools_ListIteratorOfListOfShape.hxx>
00049 #include <TopTools_ListOfShape.hxx>
00050 #include <TopoDS.hxx>
00051 #include <TopoDS_Edge.hxx>
00052 #include <TopoDS_Face.hxx>
00053 #include <TopoDS_Vertex.hxx>
00054 #include <gp_Pnt.hxx>
00055 #include <gp_Pnt2d.hxx>
00056 #include <gp_Vec.hxx>
00057
00058 #include <Standard_ErrorHandler.hxx>
00059 #include <Standard_Failure.hxx>
00060
00061 #include "utilities.h"
00062
00063 #include <algorithm>
00064 #include <limits>
00065
00066 using namespace std;
00067
00068
00072
00073
00074 SMESH_Algo::SMESH_Algo (int hypId, int studyId, SMESH_Gen * gen)
00075 : SMESH_Hypothesis(hypId, studyId, gen)
00076 {
00077 gen->_mapAlgo[hypId] = this;
00078
00079 _onlyUnaryInput = _requireDescretBoundary = _requireShape = true;
00080 _quadraticMesh = _supportSubmeshes = false;
00081 _error = COMPERR_OK;
00082 }
00083
00084
00088
00089
00090 SMESH_Algo::~SMESH_Algo()
00091 {
00092 }
00093
00094
00098
00099
00100 ostream & SMESH_Algo::SaveTo(ostream & save) { return save; }
00101 istream & SMESH_Algo::LoadFrom(istream & load) { return load; }
00102
00103
00107
00108
00109 const vector < string > &SMESH_Algo::GetCompatibleHypothesis()
00110 {
00111 return _compatibleHypothesis;
00112 }
00113
00114
00122
00123
00124 const list <const SMESHDS_Hypothesis *> &
00125 SMESH_Algo::GetUsedHypothesis(SMESH_Mesh & aMesh,
00126 const TopoDS_Shape & aShape,
00127 const bool ignoreAuxiliary)
00128 {
00129 _usedHypList.clear();
00130 SMESH_HypoFilter filter;
00131 if ( InitCompatibleHypoFilter( filter, ignoreAuxiliary ))
00132 {
00133 aMesh.GetHypotheses( aShape, filter, _usedHypList, true );
00134 if ( ignoreAuxiliary && _usedHypList.size() > 1 )
00135 _usedHypList.clear();
00136 }
00137 return _usedHypList;
00138 }
00139
00140
00146
00147
00148 const list<const SMESHDS_Hypothesis *> &
00149 SMESH_Algo::GetAppliedHypothesis(SMESH_Mesh & aMesh,
00150 const TopoDS_Shape & aShape,
00151 const bool ignoreAuxiliary)
00152 {
00153 _appliedHypList.clear();
00154 SMESH_HypoFilter filter;
00155 if ( InitCompatibleHypoFilter( filter, ignoreAuxiliary ))
00156 aMesh.GetHypotheses( aShape, filter, _appliedHypList, false );
00157
00158 return _appliedHypList;
00159 }
00160
00161
00165
00166
00167 double SMESH_Algo::EdgeLength(const TopoDS_Edge & E)
00168 {
00169 double UMin = 0, UMax = 0;
00170 if (BRep_Tool::Degenerated(E))
00171 return 0;
00172 TopLoc_Location L;
00173 Handle(Geom_Curve) C = BRep_Tool::Curve(E, L, UMin, UMax);
00174 GeomAdaptor_Curve AdaptCurve(C, UMin, UMax);
00175 double length = GCPnts_AbscissaPoint::Length(AdaptCurve, UMin, UMax);
00176 return length;
00177 }
00178
00179
00183
00184
00185 bool SMESH_Algo::FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool normalized)
00186 {
00187 if ( !F || F->GetType() != SMDSAbs_Face )
00188 return false;
00189
00190 normal.SetCoord(0,0,0);
00191 int nbNodes = F->IsQuadratic() ? F->NbNodes()/2 : F->NbNodes();
00192 for ( int i = 0; i < nbNodes-2; ++i )
00193 {
00194 gp_XYZ p[3];
00195 for ( int n = 0; n < 3; ++n )
00196 {
00197 const SMDS_MeshNode* node = F->GetNode( i + n );
00198 p[n].SetCoord( node->X(), node->Y(), node->Z() );
00199 }
00200 normal += ( p[2] - p[1] ) ^ ( p[0] - p[1] );
00201 }
00202 double size2 = normal.SquareModulus();
00203 bool ok = ( size2 > numeric_limits<double>::min() * numeric_limits<double>::min());
00204 if ( normalized && ok )
00205 normal /= sqrt( size2 );
00206
00207 return ok;
00208 }
00209
00210
00218
00219
00220 bool SMESH_Algo::IsReversedSubMesh (const TopoDS_Face& theFace,
00221 SMESHDS_Mesh* theMeshDS)
00222 {
00223 if ( theFace.IsNull() || !theMeshDS )
00224 return false;
00225
00226
00227 int faceID = theMeshDS->ShapeToIndex( theFace );
00228 TopoDS_Shape aMeshedFace = theMeshDS->IndexToShape( faceID );
00229 bool isReversed = ( theFace.Orientation() != aMeshedFace.Orientation() );
00230
00231 const SMESHDS_SubMesh * aSubMeshDSFace = theMeshDS->MeshElements( faceID );
00232 if ( !aSubMeshDSFace )
00233 return isReversed;
00234
00235
00236 const SMDS_FacePosition* facePos = 0;
00237 int vertexID = 0;
00238 gp_Pnt nPnt[3];
00239 gp_Vec Ne;
00240 bool normalOK = false;
00241 SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
00242 while ( iteratorElem->more() )
00243 {
00244 const SMDS_MeshElement* elem = iteratorElem->next();
00245 if ( elem && elem->NbNodes() > 2 ) {
00246 SMDS_ElemIteratorPtr nodesIt = elem->nodesIterator();
00247 const SMDS_FacePosition* fPos = 0;
00248 int i = 0, vID = 0;
00249 while ( nodesIt->more() ) {
00250 const SMDS_MeshNode* node
00251 = static_cast<const SMDS_MeshNode *>(nodesIt->next());
00252 if ( i == 3 ) i = 2;
00253 nPnt[ i++ ].SetCoord( node->X(), node->Y(), node->Z() );
00254
00255 const SMDS_PositionPtr& pos = node->GetPosition();
00256 if ( !pos ) continue;
00257 if ( pos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
00258 fPos = dynamic_cast< const SMDS_FacePosition* >( pos );
00259 }
00260 else if ( pos->GetTypeOfPosition() == SMDS_TOP_VERTEX ) {
00261 vID = node->getshapeId();
00262 }
00263 }
00264 if ( fPos || ( !normalOK && vID )) {
00265
00266 gp_Vec v01( nPnt[0], nPnt[1] ), v02( nPnt[0], nPnt[2] );
00267 if ( v01.SquareMagnitude() > RealSmall() &&
00268 v02.SquareMagnitude() > RealSmall() )
00269 {
00270 Ne = v01 ^ v02;
00271 normalOK = ( Ne.SquareMagnitude() > RealSmall() );
00272 }
00273
00274 if ( normalOK ) {
00275 vertexID = vID;
00276 if ((facePos = fPos))
00277 break;
00278 }
00279 }
00280 }
00281 }
00282 if ( !normalOK )
00283 return isReversed;
00284
00285
00286 double u,v;
00287 if ( facePos ) {
00288 u = facePos->GetUParameter();
00289 v = facePos->GetVParameter();
00290 }
00291 else if ( vertexID ) {
00292 TopoDS_Shape V = theMeshDS->IndexToShape( vertexID );
00293 if ( V.IsNull() || V.ShapeType() != TopAbs_VERTEX )
00294 return isReversed;
00295 gp_Pnt2d uv = BRep_Tool::Parameters( TopoDS::Vertex( V ), theFace );
00296 u = uv.X();
00297 v = uv.Y();
00298 }
00299 else
00300 {
00301 return isReversed;
00302 }
00303
00304
00305 TopLoc_Location loc;
00306 Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc );
00307 if ( surf.IsNull() || surf->Continuity() < GeomAbs_C1 ) return isReversed;
00308 gp_Vec d1u, d1v;
00309 surf->D1( u, v, nPnt[0], d1u, d1v );
00310 gp_Vec Nf = (d1u ^ d1v).Transformed( loc );
00311
00312 if ( theFace.Orientation() == TopAbs_REVERSED )
00313 Nf.Reverse();
00314
00315 return Ne * Nf < 0.;
00316 }
00317
00318
00322
00323
00324 bool SMESH_Algo::SetParametersByMesh(const SMESH_Mesh* ,
00325 const TopoDS_Shape& )
00326 {
00327 return false;
00328 }
00329 bool SMESH_Algo::SetParametersByDefaults(const TDefaults& , const SMESH_Mesh*)
00330 {
00331 return false;
00332 }
00333
00341
00342
00343 bool SMESH_Algo::GetNodeParamOnEdge(const SMESHDS_Mesh* theMesh,
00344 const TopoDS_Edge& theEdge,
00345 vector< double > & theParams)
00346 {
00347 theParams.clear();
00348
00349 if ( !theMesh || theEdge.IsNull() )
00350 return false;
00351
00352 SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge );
00353 if ( !eSubMesh || !eSubMesh->GetElements()->more() )
00354 return false;
00355
00356
00357 set < double > paramSet;
00358 if ( eSubMesh )
00359 {
00360
00361 SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes();
00362 while ( nIt->more() )
00363 {
00364 const SMDS_MeshNode* node = nIt->next();
00365 const SMDS_PositionPtr& pos = node->GetPosition();
00366 if ( pos->GetTypeOfPosition() != SMDS_TOP_EDGE )
00367 return false;
00368 const SMDS_EdgePosition* epos =
00369 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
00370 if ( !paramSet.insert( epos->GetUParameter() ).second )
00371 return false;
00372 }
00373 }
00374
00375 TopoDS_Vertex V1,V2;
00376 TopExp::Vertices( theEdge, V1, V2);
00377 if ( VertexNode( V1, theMesh ) &&
00378 !paramSet.insert( BRep_Tool::Parameter(V1,theEdge) ).second )
00379 return false;
00380 if ( VertexNode( V2, theMesh ) &&
00381 !paramSet.insert( BRep_Tool::Parameter(V2,theEdge) ).second )
00382 return false;
00383
00384
00385 theParams.resize( paramSet.size() );
00386 set < double >::iterator par = paramSet.begin();
00387 vector< double >::iterator vecPar = theParams.begin();
00388 for ( ; par != paramSet.end(); ++par, ++vecPar )
00389 *vecPar = *par;
00390
00391 return theParams.size() > 1;
00392 }
00393
00394
00402
00403
00404 bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theMesh,
00405 const TopoDS_Edge& theEdge,
00406 const bool ignoreMediumNodes,
00407 map< double, const SMDS_MeshNode* > & theNodes)
00408 {
00409 theNodes.clear();
00410
00411 if ( !theMesh || theEdge.IsNull() )
00412 return false;
00413
00414 SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge );
00415 if ( !eSubMesh || !eSubMesh->GetElements()->more() )
00416 return false;
00417
00418 int nbNodes = 0;
00419 set < double > paramSet;
00420 if ( eSubMesh )
00421 {
00422
00423 SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes();
00424 while ( nIt->more() )
00425 {
00426 const SMDS_MeshNode* node = nIt->next();
00427 if ( ignoreMediumNodes ) {
00428 SMDS_ElemIteratorPtr elemIt = node->GetInverseElementIterator();
00429 if ( elemIt->more() && elemIt->next()->IsMediumNode( node ))
00430 continue;
00431 }
00432 const SMDS_PositionPtr& pos = node->GetPosition();
00433 if ( pos->GetTypeOfPosition() != SMDS_TOP_EDGE )
00434 return false;
00435 const SMDS_EdgePosition* epos =
00436 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
00437 theNodes.insert( make_pair( epos->GetUParameter(), node ));
00438
00439 ++nbNodes;
00440 }
00441 }
00442
00443 TopoDS_Vertex v1, v2;
00444 TopExp::Vertices(theEdge, v1, v2);
00445 const SMDS_MeshNode* n1 = VertexNode( v1, (SMESHDS_Mesh*) theMesh );
00446 const SMDS_MeshNode* n2 = VertexNode( v2, (SMESHDS_Mesh*) theMesh );
00447
00448 Standard_Real f, l;
00449 BRep_Tool::Range(theEdge, f, l);
00450 if ( v1.Orientation() != TopAbs_FORWARD )
00451 std::swap( f, l );
00452 if ( n1 && ++nbNodes )
00453 theNodes.insert( make_pair( f, n1 ));
00454 if ( n2 && ++nbNodes )
00455 theNodes.insert( make_pair( l, n2 ));
00456
00457 return theNodes.size() == nbNodes;
00458 }
00459
00460
00466
00467
00468 bool SMESH_Algo::InitCompatibleHypoFilter( SMESH_HypoFilter & theFilter,
00469 const bool ignoreAuxiliary) const
00470 {
00471 if ( !_compatibleHypothesis.empty() )
00472 {
00473 theFilter.Init( theFilter.HasName( _compatibleHypothesis[0] ));
00474 for ( int i = 1; i < _compatibleHypothesis.size(); ++i )
00475 theFilter.Or( theFilter.HasName( _compatibleHypothesis[ i ] ));
00476
00477 if ( ignoreAuxiliary )
00478 theFilter.AndNot( theFilter.IsAuxiliary() );
00479
00480 return true;
00481 }
00482 return false;
00483 }
00484
00485
00492
00493
00494 GeomAbs_Shape SMESH_Algo::Continuity(TopoDS_Edge E1,
00495 TopoDS_Edge E2)
00496 {
00497
00498 if (E1.Orientation() > TopAbs_REVERSED)
00499 E1.Orientation( TopAbs_FORWARD );
00500 if (E2.Orientation() > TopAbs_REVERSED)
00501 E2.Orientation( TopAbs_FORWARD );
00502 TopoDS_Vertex V = TopExp::LastVertex (E1, true);
00503 if ( !V.IsSame( TopExp::FirstVertex(E2, true )))
00504 if ( !TopExp::CommonVertex( E1, E2, V ))
00505 return GeomAbs_C0;
00506 Standard_Real u1 = BRep_Tool::Parameter( V, E1 );
00507 Standard_Real u2 = BRep_Tool::Parameter( V, E2 );
00508 BRepAdaptor_Curve C1( E1 ), C2( E2 );
00509 Standard_Real tol = BRep_Tool::Tolerance( V );
00510 Standard_Real angTol = 2e-3;
00511 try {
00512 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
00513 OCC_CATCH_SIGNALS;
00514 #endif
00515 return BRepLProp::Continuity(C1, C2, u1, u2, tol, angTol);
00516 }
00517 catch (Standard_Failure) {
00518 }
00519 return GeomAbs_C0;
00520 }
00521
00522
00529
00530
00531 const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex& V,
00532 const SMESHDS_Mesh* meshDS)
00533 {
00534 if ( SMESHDS_SubMesh* sm = meshDS->MeshElements(V) ) {
00535 SMDS_NodeIteratorPtr nIt= sm->GetNodes();
00536 if (nIt->more())
00537 return nIt->next();
00538 }
00539 return 0;
00540 }
00541
00542
00543
00544
00545
00546
00547 vector< const SMDS_MeshNode*> SMESH_Algo::GetCommonNodes(const SMDS_MeshElement* e1,
00548 const SMDS_MeshElement* e2)
00549 {
00550 vector< const SMDS_MeshNode*> common;
00551 for ( int i = 0 ; i < e1->NbNodes(); ++i )
00552 if ( e2->GetNodeIndex( e1->GetNode( i )) >= 0 )
00553 common.push_back( e1->GetNode( i ));
00554 return common;
00555 }
00556
00557
00565
00566
00567 void SMESH_Algo::SetEventListener(SMESH_subMesh* )
00568 {
00569 }
00570
00571
00578
00579
00580 void SMESH_Algo::SubmeshRestored(SMESH_subMesh* )
00581 {
00582 }
00583
00584
00591
00592
00593 bool SMESH_Algo::Compute(SMESH_Mesh & , SMESH_MesherHelper* )
00594 {
00595 return error( COMPERR_BAD_INPUT_MESH, "Mesh built on shape expected");
00596 }
00597
00598 #ifdef WITH_SMESH_CANCEL_COMPUTE
00599 void SMESH_Algo::CancelCompute()
00600 {
00601 }
00602 #endif
00603
00604
00608
00609
00610 bool SMESH_Algo::error(int error, const SMESH_Comment& comment)
00611 {
00612 _error = error;
00613 _comment = comment;
00614 return ( error == COMPERR_OK );
00615 }
00616
00617
00621
00622
00623 bool SMESH_Algo::error(SMESH_ComputeErrorPtr error)
00624 {
00625 if ( error ) {
00626 _error = error->myName;
00627 _comment = error->myComment;
00628 _badInputElements = error->myBadElements;
00629 return error->IsOK();
00630 }
00631 return true;
00632 }
00633
00634
00638
00639
00640 SMESH_ComputeErrorPtr SMESH_Algo::GetComputeError() const
00641 {
00642 SMESH_ComputeErrorPtr err = SMESH_ComputeError::New( _error, _comment, this );
00643
00644 err->myBadElements.splice( err->myBadElements.end(),
00645 (list<const SMDS_MeshElement*>&) _badInputElements );
00646 return err;
00647 }
00648
00649
00653
00654
00655 void SMESH_Algo::InitComputeError()
00656 {
00657 _error = COMPERR_OK;
00658 _comment.clear();
00659 list<const SMDS_MeshElement*>::iterator elem = _badInputElements.begin();
00660 for ( ; elem != _badInputElements.end(); ++elem )
00661 if ( (*elem)->GetID() < 1 )
00662 delete *elem;
00663 _badInputElements.clear();
00664 }
00665
00666
00672
00673
00674 void SMESH_Algo::addBadInputElement(const SMDS_MeshElement* elem)
00675 {
00676 if ( elem )
00677 _badInputElements.push_back( elem );
00678 }