Back to index

salome-smesh  6.5.0
SMESH_Gen.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH : implementaion of SMESH idl descriptions
00024 //  File   : SMESH_Gen.cxx
00025 //  Author : Paul RASCLE, EDF
00026 //  Module : SMESH
00027 //
00028 
00029 //#define CHRONODEF
00030 
00031 #include "SMESH_Gen.hxx"
00032 
00033 #include "SMDS_Mesh.hxx"
00034 #include "SMDS_MeshElement.hxx"
00035 #include "SMDS_MeshNode.hxx"
00036 #include "SMESHDS_Document.hxx"
00037 #include "SMESH_HypoFilter.hxx"
00038 #include "SMESH_MesherHelper.hxx"
00039 #include "SMESH_subMesh.hxx"
00040 
00041 #include "utilities.h"
00042 #include "OpUtil.hxx"
00043 #include "Utils_ExceptHandlers.hxx"
00044 
00045 #include <TopoDS_Iterator.hxx>
00046 
00047 #include "memoire.h"
00048 
00049 using namespace std;
00050 
00051 //=============================================================================
00055 //=============================================================================
00056 
00057 SMESH_Gen::SMESH_Gen()
00058 {
00059         MESSAGE("SMESH_Gen::SMESH_Gen");
00060         _localId = 0;
00061         _hypId = 0;
00062         _segmentation = _nbSegments = 10;
00063         SMDS_Mesh::_meshList.clear();
00064         MESSAGE(SMDS_Mesh::_meshList.size());
00065         _counters = new counters(100);
00066 #ifdef WITH_SMESH_CANCEL_COMPUTE
00067         _compute_canceled = false;
00068         _sm_current = NULL;
00069 #endif
00070 }
00071 
00072 //=============================================================================
00076 //=============================================================================
00077 
00078 SMESH_Gen::~SMESH_Gen()
00079 {
00080   MESSAGE("SMESH_Gen::~SMESH_Gen");
00081 }
00082 
00083 //=============================================================================
00088 //=============================================================================
00089 
00090 SMESH_Mesh* SMESH_Gen::CreateMesh(int theStudyId, bool theIsEmbeddedMode)
00091   throw(SALOME_Exception)
00092 {
00093   Unexpect aCatch(SalomeException);
00094   MESSAGE("SMESH_Gen::CreateMesh");
00095 
00096   // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document
00097   StudyContextStruct *aStudyContext = GetStudyContext(theStudyId);
00098 
00099   // create a new SMESH_mesh object
00100   SMESH_Mesh *aMesh = new SMESH_Mesh(_localId++,
00101                                      theStudyId,
00102                                      this,
00103                                      theIsEmbeddedMode,
00104                                      aStudyContext->myDocument);
00105   aStudyContext->mapMesh[_localId-1] = aMesh;
00106 
00107   return aMesh;
00108 }
00109 
00110 //=============================================================================
00114 //=============================================================================
00115 
00116 bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
00117                         const TopoDS_Shape &  aShape,
00118                         const bool            anUpward,
00119                         const ::MeshDimension aDim,
00120                         TSetOfInt*            aShapesId)
00121 {
00122   MESSAGE("SMESH_Gen::Compute");
00123   MEMOSTAT;
00124 
00125   bool ret = true;
00126 
00127   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
00128 
00129   const bool includeSelf = true;
00130   const bool complexShapeFirst = true;
00131   const int  globalAlgoDim = 100;
00132 
00133   SMESH_subMeshIteratorPtr smIt;
00134 
00135   if ( anUpward ) // is called from below code here
00136   {
00137     // -----------------------------------------------
00138     // mesh all the sub-shapes starting from vertices
00139     // -----------------------------------------------
00140     smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
00141     while ( smIt->more() )
00142     {
00143       SMESH_subMesh* smToCompute = smIt->next();
00144 
00145       // do not mesh vertices of a pseudo shape
00146       const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType();
00147       if ( !aMesh.HasShapeToMesh() && aShType == TopAbs_VERTEX )
00148         continue;
00149 
00150       // check for preview dimension limitations
00151       if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
00152       {
00153         // clear compute state to not show previous compute errors
00154         //  if preview invoked less dimension less than previous
00155         smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
00156         continue;
00157       }
00158 
00159       if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
00160       {
00161 #ifdef WITH_SMESH_CANCEL_COMPUTE
00162         if (_compute_canceled)
00163           return false;
00164         _sm_current = smToCompute;
00165 #endif
00166         smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE );
00167 #ifdef WITH_SMESH_CANCEL_COMPUTE
00168         _sm_current = NULL;
00169 #endif
00170       }
00171 
00172       // we check all the submeshes here and detect if any of them failed to compute
00173       if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE)
00174         ret = false;
00175       else if ( aShapesId )
00176         aShapesId->insert( smToCompute->GetId() );
00177     }
00178     //aMesh.GetMeshDS()->Modified();
00179     return ret;
00180   }
00181   else
00182   {
00183     // -----------------------------------------------------------------
00184     // apply algos that DO NOT require Discreteized boundaries and DO NOT
00185     // support submeshes, starting from the most complex shapes
00186     // and collect submeshes with algos that DO support submeshes
00187     // -----------------------------------------------------------------
00188     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes;
00189 
00190     // map to sort sm with same dim algos according to dim of
00191     // the shape the algo assigned to (issue 0021217)
00192     multimap< int, SMESH_subMesh* > shDim2sm;
00193     multimap< int, SMESH_subMesh* >::reverse_iterator shDim2smIt;
00194     TopoDS_Shape algoShape;
00195     int prevShapeDim = -1;
00196 
00197     smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
00198     while ( smIt->more() )
00199     {
00200       SMESH_subMesh* smToCompute = smIt->next();
00201       if ( smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE )
00202         continue;
00203 
00204       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
00205       int aShapeDim = GetShapeDim( aSubShape );
00206       if ( aShapeDim < 1 ) break;
00207       
00208       // check for preview dimension limitations
00209       if ( aShapesId && aShapeDim > (int)aDim )
00210         continue;
00211 
00212       SMESH_Algo* algo = GetAlgo( aMesh, aSubShape, &algoShape );
00213       if ( algo && !algo->NeedDiscreteBoundary() )
00214       {
00215         if ( algo->SupportSubmeshes() )
00216         {
00217           // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
00218           // so that more local algos to go first
00219           if ( prevShapeDim != aShapeDim )
00220           {
00221             prevShapeDim = aShapeDim;
00222             for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
00223               if ( shDim2smIt->first == globalAlgoDim )
00224                 smWithAlgoSupportingSubmeshes.push_back( shDim2smIt->second );
00225               else
00226                 smWithAlgoSupportingSubmeshes.push_front( shDim2smIt->second );
00227             shDim2sm.clear();
00228           }
00229           // add smToCompute to shDim2sm map
00230           if ( algoShape.IsSame( aMesh.GetShapeToMesh() ))
00231           {
00232             aShapeDim = globalAlgoDim; // to compute last
00233           }
00234           else
00235           {
00236             aShapeDim = GetShapeDim( algoShape );
00237             if ( algoShape.ShapeType() == TopAbs_COMPOUND )
00238             {
00239               TopoDS_Iterator it( algoShape );
00240               aShapeDim += GetShapeDim( it.Value() );
00241             }
00242           }
00243           shDim2sm.insert( make_pair( aShapeDim, smToCompute ));
00244         }
00245         else
00246         {
00247 #ifdef WITH_SMESH_CANCEL_COMPUTE
00248           if (_compute_canceled)
00249             return false;
00250           _sm_current = smToCompute;
00251 #endif
00252           smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE );
00253 #ifdef WITH_SMESH_CANCEL_COMPUTE
00254           _sm_current = NULL;
00255 #endif
00256           if ( aShapesId )
00257             aShapesId->insert( smToCompute->GetId() );
00258         }
00259       }
00260     }
00261     // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
00262     for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
00263       if ( shDim2smIt->first == globalAlgoDim )
00264         smWithAlgoSupportingSubmeshes.push_back( shDim2smIt->second );
00265       else
00266         smWithAlgoSupportingSubmeshes.push_front( shDim2smIt->second );
00267 
00268     // ------------------------------------------------------------
00269     // sort list of submeshes according to mesh order
00270     // ------------------------------------------------------------
00271     aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
00272 
00273     // ------------------------------------------------------------
00274     // compute submeshes under shapes with algos that DO NOT require
00275     // Discreteized boundaries and DO support submeshes
00276     // ------------------------------------------------------------
00277     list< SMESH_subMesh* >::iterator subIt, subEnd;
00278     subIt  = smWithAlgoSupportingSubmeshes.begin();
00279     subEnd = smWithAlgoSupportingSubmeshes.end();
00280     // start from lower shapes
00281     for ( ; subIt != subEnd; ++subIt )
00282     {
00283       sm = *subIt;
00284 
00285       // get a shape the algo is assigned to
00286       if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
00287         continue; // strange...
00288 
00289       // look for more local algos
00290       smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
00291       while ( smIt->more() )
00292       {
00293         SMESH_subMesh* smToCompute = smIt->next();
00294 
00295         const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
00296         const int aShapeDim = GetShapeDim( aSubShape );
00297         //if ( aSubShape.ShapeType() == TopAbs_VERTEX ) continue;
00298         if ( aShapeDim < 1 ) continue;
00299 
00300         // check for preview dimension limitations
00301         if ( aShapesId && GetShapeDim( aSubShape.ShapeType() ) > (int)aDim )
00302           continue;
00303         
00304         SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
00305         filter
00306           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
00307           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
00308 
00309         if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
00310           SMESH_Hypothesis::Hypothesis_Status status;
00311           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
00312             // mesh a lower smToCompute starting from vertices
00313             Compute( aMesh, aSubShape, /*anUpward=*/true, aDim, aShapesId );
00314         }
00315       }
00316     }
00317     // ----------------------------------------------------------
00318     // apply the algos that do not require Discreteized boundaries
00319     // ----------------------------------------------------------
00320     for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
00321     {
00322       sm = *subIt;
00323       if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
00324       {
00325         const TopAbs_ShapeEnum aShType = sm->GetSubShape().ShapeType();
00326         // check for preview dimension limitations
00327         if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
00328           continue;
00329 
00330 #ifdef WITH_SMESH_CANCEL_COMPUTE
00331         if (_compute_canceled)
00332           return false;
00333         _sm_current = sm;
00334 #endif
00335         sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
00336 #ifdef WITH_SMESH_CANCEL_COMPUTE
00337         _sm_current = NULL;
00338 #endif
00339         if ( aShapesId )
00340           aShapesId->insert( sm->GetId() );
00341       }
00342     }
00343     // -----------------------------------------------
00344     // mesh the rest sub-shapes starting from vertices
00345     // -----------------------------------------------
00346     ret = Compute( aMesh, aShape, /*anUpward=*/true, aDim, aShapesId );
00347   }
00348 
00349   MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret);
00350   MEMOSTAT;
00351 
00352   SMESHDS_Mesh *myMesh = aMesh.GetMeshDS();
00353   myMesh->adjustStructure();
00354   MESSAGE("*** compactMesh after compute");
00355   myMesh->compactMesh();
00356   //myMesh->adjustStructure();
00357   list<int> listind = myMesh->SubMeshIndices();
00358   list<int>::iterator it = listind.begin();
00359   int total = 0;
00360   for(; it != listind.end(); ++it)
00361     {
00362       ::SMESHDS_SubMesh *subMesh = myMesh->MeshElements(*it);
00363       total +=  subMesh->getSize();
00364     }
00365   MESSAGE("total elements and nodes in submesh sets:" << total);
00366   MESSAGE("Number of node objects " << SMDS_MeshNode::nbNodes);
00367   MESSAGE("Number of cell objects " << SMDS_MeshCell::nbCells);
00368   //myMesh->dumpGrid();
00369   //aMesh.GetMeshDS()->Modified();
00370 
00371   // fix quadratic mesh by bending iternal links near concave boundary
00372   if ( aShape.IsSame( aMesh.GetShapeToMesh() ) &&
00373        !aShapesId ) // not preview
00374   {
00375     SMESH_MesherHelper aHelper( aMesh );
00376     if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR )
00377       aHelper.FixQuadraticElements();
00378   }
00379   return ret;
00380 }
00381 
00382 
00383 #ifdef WITH_SMESH_CANCEL_COMPUTE
00384 //=============================================================================
00388 //=============================================================================
00389 void SMESH_Gen::PrepareCompute(SMESH_Mesh &          aMesh,
00390                                const TopoDS_Shape &  aShape)
00391 {
00392   _compute_canceled = false;
00393   _sm_current = NULL;
00394 }
00395 //=============================================================================
00399 //=============================================================================
00400 void SMESH_Gen::CancelCompute(SMESH_Mesh &          aMesh,
00401                               const TopoDS_Shape &  aShape)
00402 {
00403   _compute_canceled = true;
00404   if(_sm_current)
00405     {
00406       _sm_current->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
00407     }
00408 }
00409 #endif
00410 
00411 //=============================================================================
00415 //=============================================================================
00416 
00417 bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
00418                          const TopoDS_Shape &  aShape,
00419                          MapShapeNbElems&      aResMap,
00420                          const bool            anUpward,
00421                          TSetOfInt*            aShapesId)
00422 {
00423   MESSAGE("SMESH_Gen::Evaluate");
00424 
00425   bool ret = true;
00426 
00427   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
00428 
00429   const bool includeSelf = true;
00430   const bool complexShapeFirst = true;
00431   SMESH_subMeshIteratorPtr smIt;
00432 
00433   if ( anUpward ) { // is called from below code here
00434     // -----------------------------------------------
00435     // mesh all the sub-shapes starting from vertices
00436     // -----------------------------------------------
00437     smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
00438     while ( smIt->more() ) {
00439       SMESH_subMesh* smToCompute = smIt->next();
00440 
00441       // do not mesh vertices of a pseudo shape
00442       const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType();
00443       //if ( !aMesh.HasShapeToMesh() && aShType == TopAbs_VERTEX )
00444       //  continue;
00445       if ( !aMesh.HasShapeToMesh() ) {
00446         if( aShType == TopAbs_VERTEX || aShType == TopAbs_WIRE ||
00447             aShType == TopAbs_SHELL )
00448           continue;
00449       }
00450 
00451       smToCompute->Evaluate(aResMap);
00452       if( aShapesId )
00453         aShapesId->insert( smToCompute->GetId() );
00454     }
00455     return ret;
00456   }
00457   else {
00458     // -----------------------------------------------------------------
00459     // apply algos that DO NOT require Discreteized boundaries and DO NOT
00460     // support submeshes, starting from the most complex shapes
00461     // and collect submeshes with algos that DO support submeshes
00462     // -----------------------------------------------------------------
00463     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes;
00464     smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
00465     while ( smIt->more() ) {
00466       SMESH_subMesh* smToCompute = smIt->next();
00467       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
00468       const int aShapeDim = GetShapeDim( aSubShape );
00469       if ( aShapeDim < 1 ) break;
00470       
00471       SMESH_Algo* algo = GetAlgo( aMesh, aSubShape );
00472       if ( algo && !algo->NeedDiscreteBoundary() ) {
00473         if ( algo->SupportSubmeshes() ) {
00474           smWithAlgoSupportingSubmeshes.push_front( smToCompute );
00475         }
00476         else {
00477           smToCompute->Evaluate(aResMap);
00478           if ( aShapesId )
00479             aShapesId->insert( smToCompute->GetId() );
00480         }
00481       }
00482     }
00483 
00484     // ------------------------------------------------------------
00485     // sort list of meshes according to mesh order
00486     // ------------------------------------------------------------
00487     aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
00488 
00489     // ------------------------------------------------------------
00490     // compute submeshes under shapes with algos that DO NOT require
00491     // Discreteized boundaries and DO support submeshes
00492     // ------------------------------------------------------------
00493     list< SMESH_subMesh* >::iterator subIt, subEnd;
00494     subIt  = smWithAlgoSupportingSubmeshes.begin();
00495     subEnd = smWithAlgoSupportingSubmeshes.end();
00496     // start from lower shapes
00497     for ( ; subIt != subEnd; ++subIt ) {
00498       sm = *subIt;
00499 
00500       // get a shape the algo is assigned to
00501       TopoDS_Shape algoShape;
00502       if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
00503         continue; // strange...
00504 
00505       // look for more local algos
00506       smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
00507       while ( smIt->more() ) {
00508         SMESH_subMesh* smToCompute = smIt->next();
00509 
00510         const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
00511         const int aShapeDim = GetShapeDim( aSubShape );
00512         if ( aShapeDim < 1 ) continue;
00513 
00514         //const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType();
00515 
00516         SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
00517         filter
00518           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
00519           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
00520 
00521         if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
00522           SMESH_Hypothesis::Hypothesis_Status status;
00523           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
00524             // mesh a lower smToCompute starting from vertices
00525             Evaluate( aMesh, aSubShape, aResMap, /*anUpward=*/true, aShapesId );
00526         }
00527       }
00528     }
00529     // ----------------------------------------------------------
00530     // apply the algos that do not require Discreteized boundaries
00531     // ----------------------------------------------------------
00532     for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
00533     {
00534       sm = *subIt;
00535       sm->Evaluate(aResMap);
00536       if ( aShapesId )
00537         aShapesId->insert( sm->GetId() );
00538     }
00539 
00540     // -----------------------------------------------
00541     // mesh the rest sub-shapes starting from vertices
00542     // -----------------------------------------------
00543     ret = Evaluate( aMesh, aShape, aResMap, /*anUpward=*/true, aShapesId );
00544   }
00545 
00546   MESSAGE( "VSR - SMESH_Gen::Evaluate() finished, OK = " << ret);
00547   return ret;
00548 }
00549 
00550 
00551 //=======================================================================
00552 //function : checkConformIgnoredAlgos
00553 //purpose  :
00554 //=======================================================================
00555 
00556 static bool checkConformIgnoredAlgos(SMESH_Mesh&               aMesh,
00557                                      SMESH_subMesh*            aSubMesh,
00558                                      const SMESH_Algo*         aGlobIgnoAlgo,
00559                                      const SMESH_Algo*         aLocIgnoAlgo,
00560                                      bool &                    checkConform,
00561                                      set<SMESH_subMesh*>&      aCheckedMap,
00562                                      list< SMESH_Gen::TAlgoStateError > & theErrors)
00563 {
00564   ASSERT( aSubMesh );
00565   if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX)
00566     return true;
00567 
00568 
00569   bool ret = true;
00570 
00571   const list<const SMESHDS_Hypothesis*>& listHyp =
00572     aMesh.GetMeshDS()->GetHypothesis( aSubMesh->GetSubShape() );
00573   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
00574   for ( ; it != listHyp.end(); it++)
00575   {
00576     const SMESHDS_Hypothesis * aHyp = *it;
00577     if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
00578       continue;
00579 
00580     const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp);
00581     ASSERT ( algo );
00582 
00583     if ( aLocIgnoAlgo ) // algo is hidden by a local algo of upper dim
00584     {
00585       INFOS( "Local <" << algo->GetName() << "> is hidden by local <"
00586             << aLocIgnoAlgo->GetName() << ">");
00587     }
00588     else
00589     {
00590       bool isGlobal = (aMesh.IsMainShape( aSubMesh->GetSubShape() ));
00591       int dim = algo->GetDim();
00592       int aMaxGlobIgnoDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->GetDim() : -1 );
00593 
00594       if ( dim < aMaxGlobIgnoDim )
00595       {
00596         // algo is hidden by a global algo
00597         INFOS( ( isGlobal ? "Global" : "Local" )
00598               << " <" << algo->GetName() << "> is hidden by global <"
00599               << aGlobIgnoAlgo->GetName() << ">");
00600       }
00601       else if ( !algo->NeedDiscreteBoundary() && !isGlobal)
00602       {
00603         // local algo is not hidden and hides algos on sub-shapes
00604         if (checkConform && !aSubMesh->IsConform( algo ))
00605         {
00606           ret = false;
00607           checkConform = false; // no more check conformity
00608           INFOS( "ERROR: Local <" << algo->GetName() <<
00609                 "> would produce not conform mesh: "
00610                 "<Not Conform Mesh Allowed> hypotesis is missing");
00611           theErrors.push_back( SMESH_Gen::TAlgoStateError() );
00612           theErrors.back().Set( SMESH_Hypothesis::HYP_NOTCONFORM, algo, false );
00613         }
00614 
00615         // sub-algos will be hidden by a local <algo>
00616         SMESH_subMeshIteratorPtr revItSub =
00617           aSubMesh->getDependsOnIterator( /*includeSelf=*/false, /*complexShapeFirst=*/true);
00618         bool checkConform2 = false;
00619         while ( revItSub->more() )
00620         {
00621           SMESH_subMesh* sm = revItSub->next();
00622           checkConformIgnoredAlgos (aMesh, sm, aGlobIgnoAlgo,
00623                                     algo, checkConform2, aCheckedMap, theErrors);
00624           aCheckedMap.insert( sm );
00625         }
00626       }
00627     }
00628   }
00629 
00630   return ret;
00631 }
00632 
00633 //=======================================================================
00634 //function : checkMissing
00635 //purpose  : notify on missing hypothesis
00636 //           Return false if algo or hipothesis is missing
00637 //=======================================================================
00638 
00639 static bool checkMissing(SMESH_Gen*                aGen,
00640                          SMESH_Mesh&               aMesh,
00641                          SMESH_subMesh*            aSubMesh,
00642                          const int                 aTopAlgoDim,
00643                          bool*                     globalChecked,
00644                          const bool                checkNoAlgo,
00645                          set<SMESH_subMesh*>&      aCheckedMap,
00646                          list< SMESH_Gen::TAlgoStateError > & theErrors)
00647 {
00648   if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX)
00649     return true;
00650 
00651   //MESSAGE("=====checkMissing");
00652 
00653   int ret = true;
00654   SMESH_Algo* algo = 0;
00655 
00656   switch (aSubMesh->GetAlgoState())
00657   {
00658   case SMESH_subMesh::NO_ALGO: {
00659     if (checkNoAlgo)
00660     {
00661       // should there be any algo?
00662       int shapeDim = SMESH_Gen::GetShapeDim( aSubMesh->GetSubShape() );
00663       if (aTopAlgoDim > shapeDim)
00664       {
00665         MESSAGE( "ERROR: " << shapeDim << "D algorithm is missing" );
00666         ret = false;
00667         theErrors.push_back( SMESH_Gen::TAlgoStateError() );
00668         theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, shapeDim, true );
00669       }
00670     }
00671     return ret;
00672   }
00673   case SMESH_subMesh::MISSING_HYP: {
00674     // notify if an algo missing hyp is attached to aSubMesh
00675     algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() );
00676     ASSERT( algo );
00677     bool IsGlobalHypothesis = aGen->IsGlobalHypothesis( algo, aMesh );
00678     if (!IsGlobalHypothesis || !globalChecked[ algo->GetDim() ])
00679     {
00680       TAlgoStateErrorName errName = SMESH_Hypothesis::HYP_MISSING;
00681       SMESH_Hypothesis::Hypothesis_Status status;
00682       algo->CheckHypothesis( aMesh, aSubMesh->GetSubShape(), status );
00683       if ( status == SMESH_Hypothesis::HYP_BAD_PARAMETER ) {
00684         MESSAGE( "ERROR: hypothesis of " << (IsGlobalHypothesis ? "Global " : "Local ")
00685                  << "<" << algo->GetName() << "> has a bad parameter value");
00686         errName = status;
00687       } else if ( status == SMESH_Hypothesis::HYP_BAD_GEOMETRY ) {
00688         MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ")
00689                  << "<" << algo->GetName() << "> assigned to mismatching geometry");
00690         errName = status;
00691       } else {
00692         MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ")
00693                  << "<" << algo->GetName() << "> misses some hypothesis");
00694       }
00695       if (IsGlobalHypothesis)
00696         globalChecked[ algo->GetDim() ] = true;
00697       theErrors.push_back( SMESH_Gen::TAlgoStateError() );
00698       theErrors.back().Set( errName, algo, IsGlobalHypothesis );
00699     }
00700     ret = false;
00701     break;
00702   }
00703   case SMESH_subMesh::HYP_OK:
00704     algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() );
00705     ret = true;
00706     break;
00707   default: ASSERT(0);
00708   }
00709 
00710   // do not check under algo that hides sub-algos or
00711   // re-start checking NO_ALGO state
00712   ASSERT (algo);
00713   bool isTopLocalAlgo =
00714     ( aTopAlgoDim <= algo->GetDim() && !aGen->IsGlobalHypothesis( algo, aMesh ));
00715   if (!algo->NeedDiscreteBoundary() || isTopLocalAlgo)
00716   {
00717     bool checkNoAlgo2 = ( algo->NeedDiscreteBoundary() );
00718     SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false,
00719                                                                      /*complexShapeFirst=*/false);
00720     while ( itsub->more() )
00721     {
00722       // sub-meshes should not be checked further more
00723       SMESH_subMesh* sm = itsub->next();
00724       aCheckedMap.insert( sm );
00725 
00726       if (isTopLocalAlgo)
00727       {
00728         //check algo on sub-meshes
00729         int aTopAlgoDim2 = algo->GetDim();
00730         if (!checkMissing (aGen, aMesh, sm, aTopAlgoDim2,
00731                            globalChecked, checkNoAlgo2, aCheckedMap, theErrors))
00732         {
00733           ret = false;
00734           if (sm->GetAlgoState() == SMESH_subMesh::NO_ALGO )
00735             checkNoAlgo2 = false;
00736         }
00737       }
00738     }
00739   }
00740   return ret;
00741 }
00742 
00743 //=======================================================================
00744 //function : CheckAlgoState
00745 //purpose  : notify on bad state of attached algos, return false
00746 //           if Compute() would fail because of some algo bad state
00747 //=======================================================================
00748 
00749 bool SMESH_Gen::CheckAlgoState(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
00750 {
00751   list< TAlgoStateError > errors;
00752   return GetAlgoState( aMesh, aShape, errors );
00753 }
00754 
00755 //=======================================================================
00756 //function : GetAlgoState
00757 //purpose  : notify on bad state of attached algos, return false
00758 //           if Compute() would fail because of some algo bad state
00759 //           theErrors list contains problems description
00760 //=======================================================================
00761 
00762 bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
00763                              const TopoDS_Shape&       theShape,
00764                              list< TAlgoStateError > & theErrors)
00765 {
00766   //MESSAGE("SMESH_Gen::CheckAlgoState");
00767 
00768   bool ret = true;
00769   bool hasAlgo = false;
00770 
00771   SMESH_subMesh* sm = theMesh.GetSubMesh(theShape);
00772   const SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
00773   TopoDS_Shape mainShape = meshDS->ShapeToMesh();
00774 
00775   // -----------------
00776   // get global algos
00777   // -----------------
00778 
00779   const SMESH_Algo* aGlobAlgoArr[] = {0,0,0,0};
00780 
00781   const list<const SMESHDS_Hypothesis*>& listHyp = meshDS->GetHypothesis( mainShape );
00782   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
00783   for ( ; it != listHyp.end(); it++)
00784   {
00785     const SMESHDS_Hypothesis * aHyp = *it;
00786     if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
00787       continue;
00788 
00789     const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp);
00790     ASSERT ( algo );
00791 
00792     int dim = algo->GetDim();
00793     aGlobAlgoArr[ dim ] = algo;
00794 
00795     hasAlgo = true;
00796   }
00797 
00798   // --------------------------------------------------------
00799   // info on algos that will be ignored because of ones that
00800   // don't NeedDiscreteBoundary() attached to super-shapes,
00801   // check that a conform mesh will be produced
00802   // --------------------------------------------------------
00803 
00804 
00805   // find a global algo possibly hiding sub-algos
00806   int dim;
00807   const SMESH_Algo* aGlobIgnoAlgo = 0;
00808   for (dim = 3; dim > 0; dim--)
00809   {
00810     if (aGlobAlgoArr[ dim ] &&
00811         !aGlobAlgoArr[ dim ]->NeedDiscreteBoundary())
00812     {
00813       aGlobIgnoAlgo = aGlobAlgoArr[ dim ];
00814       break;
00815     }
00816   }
00817 
00818   set<SMESH_subMesh*> aCheckedSubs;
00819   bool checkConform = ( !theMesh.IsNotConformAllowed() );
00820 
00821   // loop on theShape and its sub-shapes
00822   SMESH_subMeshIteratorPtr revItSub = sm->getDependsOnIterator( /*includeSelf=*/true,
00823                                                                 /*complexShapeFirst=*/true);
00824   while ( revItSub->more() )
00825   {
00826     SMESH_subMesh* smToCheck = revItSub->next();
00827     if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
00828       break;
00829 
00830     if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked
00831       if (!checkConformIgnoredAlgos (theMesh, smToCheck, aGlobIgnoAlgo,
00832                                      0, checkConform, aCheckedSubs, theErrors))
00833         ret = false;
00834 
00835     if ( smToCheck->GetAlgoState() != SMESH_subMesh::NO_ALGO )
00836       hasAlgo = true;
00837   }
00838 
00839   // ----------------------------------------------------------------
00840   // info on missing hypothesis and find out if all needed algos are
00841   // well defined
00842   // ----------------------------------------------------------------
00843 
00844   //MESSAGE( "---info on missing hypothesis and find out if all needed algos are");
00845 
00846   // find max dim of global algo
00847   int aTopAlgoDim = 0;
00848   for (dim = 3; dim > 0; dim--)
00849   {
00850     if (aGlobAlgoArr[ dim ])
00851     {
00852       aTopAlgoDim = dim;
00853       break;
00854     }
00855   }
00856   bool checkNoAlgo = theMesh.HasShapeToMesh() ? bool( aTopAlgoDim ) : false;
00857   bool globalChecked[] = { false, false, false, false };
00858 
00859   // loop on theShape and its sub-shapes
00860   aCheckedSubs.clear();
00861   revItSub = sm->getDependsOnIterator( /*includeSelf=*/true, /*complexShapeFirst=*/true);
00862   while ( revItSub->more() )
00863   {
00864     SMESH_subMesh* smToCheck = revItSub->next();
00865     if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
00866       break;
00867 
00868     if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked
00869       if (!checkMissing (this, theMesh, smToCheck, aTopAlgoDim,
00870                          globalChecked, checkNoAlgo, aCheckedSubs, theErrors))
00871       {
00872         ret = false;
00873         if (smToCheck->GetAlgoState() == SMESH_subMesh::NO_ALGO )
00874           checkNoAlgo = false;
00875       }
00876   }
00877 
00878   if ( !hasAlgo ) {
00879     ret = false;
00880     INFOS( "None algorithm attached" );
00881     theErrors.push_back( TAlgoStateError() );
00882     theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, 1, true );
00883   }
00884 
00885   return ret;
00886 }
00887 
00888 //=======================================================================
00889 //function : IsGlobalHypothesis
00890 //purpose  : check if theAlgo is attached to the main shape
00891 //=======================================================================
00892 
00893 bool SMESH_Gen::IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& aMesh)
00894 {
00895   SMESH_HypoFilter filter( SMESH_HypoFilter::Is( theHyp ));
00896   return aMesh.GetHypothesis( aMesh.GetMeshDS()->ShapeToMesh(), filter, false );
00897 }
00898 
00899 //=============================================================================
00903 //=============================================================================
00904 
00905 SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
00906                                const TopoDS_Shape & aShape,
00907                                TopoDS_Shape*        assignedTo)
00908 {
00909   SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
00910   filter.And( filter.IsApplicableTo( aShape ));
00911 
00912   return (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, assignedTo );
00913 }
00914 
00915 //=============================================================================
00919 //=============================================================================
00920 
00921 StudyContextStruct *SMESH_Gen::GetStudyContext(int studyId)
00922 {
00923   // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document
00924 
00925   if (_mapStudyContext.find(studyId) == _mapStudyContext.end())
00926   {
00927     _mapStudyContext[studyId] = new StudyContextStruct;
00928     _mapStudyContext[studyId]->myDocument = new SMESHDS_Document(studyId);
00929   }
00930   StudyContextStruct *myStudyContext = _mapStudyContext[studyId];
00931   return myStudyContext;
00932 }
00933 
00934 //================================================================================
00938 //================================================================================
00939 
00940 int SMESH_Gen::GetShapeDim(const TopAbs_ShapeEnum & aShapeType)
00941 {
00942   static vector<int> dim;
00943   if ( dim.empty() )
00944   {
00945     dim.resize( TopAbs_SHAPE, -1 );
00946     dim[ TopAbs_COMPOUND ]  = MeshDim_3D;
00947     dim[ TopAbs_COMPSOLID ] = MeshDim_3D;
00948     dim[ TopAbs_SOLID ]     = MeshDim_3D;
00949     dim[ TopAbs_SHELL ]     = MeshDim_2D;
00950     dim[ TopAbs_FACE  ]     = MeshDim_2D;
00951     dim[ TopAbs_WIRE ]      = MeshDim_1D;
00952     dim[ TopAbs_EDGE ]      = MeshDim_1D;
00953     dim[ TopAbs_VERTEX ]    = MeshDim_0D;
00954   }
00955   return dim[ aShapeType ];
00956 }
00957 
00958 //=============================================================================
00962 //=============================================================================
00963 
00964 int SMESH_Gen::GetANewId()
00965 {
00966   return _hypId++;
00967 }