Version: 6.3.1

src/StdMeshers/StdMeshers_Import_1D.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  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   : StdMeshers_Import_1D.cxx
00025 //  Module : SMESH
00026 //
00027 #include "StdMeshers_Import_1D.hxx"
00028 #include "StdMeshers_ImportSource.hxx"
00029 
00030 #include "SMDS_MeshElement.hxx"
00031 #include "SMDS_MeshNode.hxx"
00032 #include "SMESHDS_Group.hxx"
00033 #include "SMESHDS_Mesh.hxx"
00034 #include "SMESH_Comment.hxx"
00035 #include "SMESH_Gen.hxx"
00036 #include "SMESH_Group.hxx"
00037 #include "SMESH_HypoFilter.hxx"
00038 #include "SMESH_Mesh.hxx"
00039 #include "SMESH_MesherHelper.hxx"
00040 #include "SMESH_subMesh.hxx"
00041 #include "SMESH_subMeshEventListener.hxx"
00042 
00043 #include "Utils_SALOME_Exception.hxx"
00044 #include "utilities.h"
00045 
00046 #include <BRep_Builder.hxx>
00047 #include <BRep_Tool.hxx>
00048 #include <TopExp.hxx>
00049 #include <TopExp_Explorer.hxx>
00050 #include <TopoDS.hxx>
00051 #include <TopoDS_Compound.hxx>
00052 #include <TopoDS_Edge.hxx>
00053 #include <TopoDS_Vertex.hxx>
00054 
00055 using namespace std;
00056 
00057 //=============================================================================
00061 //=============================================================================
00062 
00063 StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, int studyId, SMESH_Gen * gen)
00064   :SMESH_1D_Algo(hypId, studyId, gen), _sourceHyp(0)
00065 {
00066   MESSAGE("StdMeshers_Import_1D::StdMeshers_Import_1D");
00067   _name = "Import_1D";
00068   _shapeType = (1 << TopAbs_EDGE);
00069 
00070   _compatibleHypothesis.push_back("ImportSource1D");
00071 }
00072 
00073 //=============================================================================
00077 //=============================================================================
00078 
00079 bool StdMeshers_Import_1D::CheckHypothesis
00080                          (SMESH_Mesh&                          aMesh,
00081                           const TopoDS_Shape&                  aShape,
00082                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
00083 {
00084   _sourceHyp = 0;
00085 
00086   const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
00087   if ( hyps.size() == 0 )
00088   {
00089     aStatus = SMESH_Hypothesis::HYP_MISSING;
00090     return false;  // can't work with no hypothesis
00091   }
00092 
00093   if ( hyps.size() > 1 )
00094   {
00095     aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
00096     return false;
00097   }
00098 
00099   const SMESHDS_Hypothesis *theHyp = hyps.front();
00100 
00101   string hypName = theHyp->GetName();
00102 
00103   if (hypName == _compatibleHypothesis.front())
00104   {
00105     _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
00106     aStatus = SMESH_Hypothesis::HYP_OK;
00107     return true;
00108   }
00109 
00110   aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00111   return true;
00112 }
00113 
00114 //================================================================================
00115 namespace // INTERNAL STUFF
00116 //================================================================================
00117 {
00118   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh);
00119 
00120   enum _ListenerDataType
00121     {
00122       WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp
00123       LISTEN_SRC_MESH, // data storing submesh depending on source mesh state
00124       SRC_HYP // data storing ImportSource hyp
00125     };
00126   //================================================================================
00131   struct _ListenerData : public SMESH_subMeshEventListenerData
00132   {
00133     const StdMeshers_ImportSource1D* _srcHyp;
00134     _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP):
00135       SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
00136     {
00137       myType = type; 
00138     }
00139   };
00140   //================================================================================
00144   struct _SubLess
00145   {
00146     bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const
00147     {
00148       if ( sm1 == sm2 ) return false;
00149       if ( !sm1 || !sm2 ) return sm1 < sm2;
00150       const TopoDS_Shape& s1 = sm1->GetSubShape();
00151       const TopoDS_Shape& s2 = sm2->GetSubShape();
00152       TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType();
00153       TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType();
00154       if ( t1 == t2)
00155         return (sm1 < sm2);
00156       return t1 < t2; // to have: face < edge
00157     }
00158   };
00159   //================================================================================
00163   struct _ImportData
00164   {
00165     const SMESH_Mesh* _srcMesh;
00166     StdMeshers_Import_1D::TNodeNodeMap _n2n;
00167     StdMeshers_Import_1D::TElemElemMap _e2e;
00168 
00169     set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh
00170     set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying
00171     set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting mesh copying
00172     set< SMESH_subMesh*, _SubLess > _computedSubM;
00173 
00174     SMESHDS_SubMesh*     _importMeshSubDS; // submesh storing a copy of _srcMesh
00175     int                  _importMeshSubID; // id of _importMeshSubDS
00176 
00177     _ImportData(const SMESH_Mesh* srcMesh=0):
00178       _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
00179 
00180     void removeImportedMesh( SMESHDS_Mesh* meshDS )
00181     {
00182       if ( !_importMeshSubDS ) return;
00183       SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
00184       while ( eIt->more() )
00185         meshDS->RemoveFreeElement( eIt->next(), _importMeshSubDS, /*fromGroups=*/false );
00186       SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
00187       while ( nIt->more() )
00188         meshDS->RemoveFreeNode( nIt->next(), _importMeshSubDS, /*fromGroups=*/false );
00189       _n2n.clear();
00190       _e2e.clear();
00191     }
00192     void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
00193     {
00194       if ( !srcHyp ) return;
00195       SMESH_Mesh*           tgtMesh = subM->GetFather();
00196       const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
00197       const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
00198       vector<SMESH_Group*>*  groups =
00199         const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
00200       if ( groups )
00201       {
00202         for ( unsigned i = 0; i < groups->size(); ++i )
00203           tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
00204         groups->clear();
00205       }
00206     }
00207     void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
00208     {
00209       if ( !srcHyp ) return;
00210       bool toCopyMesh, toCopyGroups;
00211       srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
00212 
00213       if ( toCopyMesh )_copyMeshSubM.insert( sm );
00214       else             _copyMeshSubM.erase( sm );
00215 
00216       if ( toCopyGroups ) _copyGroupSubM.insert( sm );
00217       else                _copyGroupSubM.erase( sm );
00218     }
00219     void addComputed( SMESH_subMesh* sm )
00220     {
00221       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
00222                                                                /*complexShapeFirst=*/true);
00223       while ( smIt->more() )
00224       {
00225         sm = smIt->next();
00226         switch ( sm->GetSubShape().ShapeType() )
00227         {
00228         case TopAbs_EDGE:
00229         case TopAbs_FACE:
00230           _subM.insert( sm );
00231           if ( !sm->IsEmpty() )
00232             _computedSubM.insert( sm );
00233         case TopAbs_VERTEX:
00234           break;
00235         default:;
00236         }
00237       }
00238     }
00239   };
00240   //================================================================================
00244   class _Listener : public SMESH_subMeshEventListener
00245   {
00246     typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
00247     TMesh2ImpData _tgtMesh2ImportData;
00248 
00249     _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false){}
00250 
00251   public:
00252     // return poiter to a static listener
00253     static _Listener* get() { static _Listener theListener; return &theListener; }
00254 
00255     static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh);
00256 
00257     static void storeImportSubmesh(SMESH_subMesh*                   importSub,
00258                                    const SMESH_Mesh*                srcMesh,
00259                                    const StdMeshers_ImportSource1D* srcHyp);
00260 
00261     virtual void ProcessEvent(const int                       event,
00262                               const int                       eventType,
00263                               SMESH_subMesh*                  subMesh,
00264                               SMESH_subMeshEventListenerData* data,
00265                               const SMESH_Hypothesis*         hyp);
00266     void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data );
00267     void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub );
00268 
00269     // mark sm as missing src hyp with valid groups
00270     static void waitHypModification(SMESH_subMesh* sm)
00271     {
00272       sm->SetEventListener
00273         (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
00274     }
00275   };
00276   //--------------------------------------------------------------------------------
00280   _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh,
00281                                         SMESH_Mesh*       tgtMesh)
00282   {
00283     list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
00284     list< _ImportData >::iterator d = dList.begin();
00285     for ( ; d != dList.end(); ++d )
00286       if ( d->_srcMesh == srcMesh )
00287         return &*d;
00288     dList.push_back(_ImportData(srcMesh));
00289     return &dList.back();
00290   }
00291 
00292   //--------------------------------------------------------------------------------
00299   void _Listener::storeImportSubmesh(SMESH_subMesh*                   importSub,
00300                                      const SMESH_Mesh*                srcMesh,
00301                                      const StdMeshers_ImportSource1D* srcHyp)
00302   {
00303     // set listener to hear events of the submesh computed by "Import" algo
00304     importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
00305 
00306     // set a listener to hear events of the source mesh
00307     SMESH_subMesh* smToNotify = importSub;
00308     SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1);
00309     SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH);
00310     data->mySubMeshes.push_back( smToNotify );
00311     importSub->SetEventListener( get(), data, smToListen );
00312 
00313     // remeber the submesh importSub and its sub-submeshes
00314     _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
00315     iData->trackHypParams( importSub, srcHyp );
00316     iData->addComputed( importSub );
00317     if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
00318     {
00319       SMESH_Mesh* tgtMesh = importSub->GetFather();
00320       iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
00321       iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
00322     }
00323   }
00324   //--------------------------------------------------------------------------------
00330   void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
00331   {
00332     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
00333     list< _ImportData >::iterator d = dList.begin();
00334     for ( ; d != dList.end(); ++d )
00335       if ( (*d)._subM.erase( sm ))
00336       {
00337         d->_computedSubM.erase( sm );
00338         bool rmMesh   = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
00339         bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
00340         if ( rmMesh )
00341           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
00342         if ( rmGroups && data )
00343           d->removeGroups( sm, data->_srcHyp );
00344       }
00345   }
00346   //--------------------------------------------------------------------------------
00352   void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub)
00353   {
00354     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
00355     list< _ImportData >::iterator d = dList.begin();
00356     for ( ; d != dList.end(); ++d )
00357     {
00358       if ( !d->_subM.count( sm )) continue;
00359       if ( (*d)._computedSubM.erase( sm ) )
00360       {
00361         bool copyMesh = !d->_copyMeshSubM.empty();
00362         if ( copyMesh || clearAllSub )
00363         {
00364           // remove imported mesh and groups
00365           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
00366 
00367           if ( data )
00368             d->removeGroups( sm, data->_srcHyp );
00369 
00370           // clear the rest submeshes
00371           if ( !d->_computedSubM.empty() )
00372           {
00373             set< SMESH_subMesh*, _SubLess> subs;
00374             subs.swap( d->_computedSubM ); // avoid recursion via events
00375             while ( !subs.empty() )
00376             {
00377               SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() );
00378               _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
00379               if ( hypData )
00380                 d->removeGroups( sm, hypData->_srcHyp );
00381 
00382               subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
00383               if ( subM->GetSubShape().ShapeType() == TopAbs_FACE )
00384                 subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
00385             }
00386           }
00387         }
00388         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
00389         if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
00390           sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
00391       }
00392       if ( data )
00393         d->trackHypParams( sm, data->_srcHyp );
00394       d->_n2n.clear();
00395       d->_e2e.clear();
00396     }
00397   }
00398   //--------------------------------------------------------------------------------
00402   void _Listener::ProcessEvent(const int                       event,
00403                                const int                       eventType,
00404                                SMESH_subMesh*                  subMesh,
00405                                SMESH_subMeshEventListenerData* data,
00406                                const SMESH_Hypothesis*         /*hyp*/)
00407   {
00408     if ( data && data->myType == WAIT_HYP_MODIF )
00409     {
00410       // event of Import submesh
00411       if ( SMESH_subMesh::MODIF_HYP  == event &&
00412            SMESH_subMesh::ALGO_EVENT == eventType )
00413       {
00414         // re-call SetEventListener() to take into account valid parameters
00415         // of ImportSource hypothesis
00416         SMESH_Gen* gen = subMesh->GetFather()->GetGen();
00417         if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape()))
00418           algo->SetEventListener( subMesh );
00419       }
00420     }
00421     else if ( data && data->myType == LISTEN_SRC_MESH )
00422     {
00423       // event of source mesh
00424       if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
00425       {
00426         switch ( event ) {
00427         case SMESH_subMesh::CLEAN:
00428           // source mesh cleaned -> clean target mesh
00429           clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true );
00430           break;
00431         case SMESH_subMesh::SUBMESH_COMPUTED: {
00432           // source mesh computed -> reset FAILED state of Import submeshes to
00433           // READY_TO_COMPUTE
00434           SMESH_Mesh* srcMesh = subMesh->GetFather();
00435           if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 )
00436           {
00437             SMESH_Mesh* m = data->mySubMeshes.front()->GetFather();
00438             if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1))
00439             {
00440               sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED );
00441               sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
00442             }
00443           }
00444           break;
00445         }
00446         default:;
00447         }
00448       }
00449     }
00450     else // event of Import submesh
00451     {
00452       // find out what happens: import hyp modified or removed
00453       bool removeImport = false, modifHyp = false;
00454       if ( SMESH_subMesh::ALGO_EVENT == eventType )
00455         modifHyp = true;
00456       if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
00457       {
00458         removeImport = true;
00459       }
00460       else if ( SMESH_subMesh::REMOVE_ALGO == event ||
00461                 SMESH_subMesh::REMOVE_FATHER_ALGO == event )
00462       {
00463         SMESH_Gen* gen = subMesh->GetFather()->GetGen();
00464         SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(),subMesh->GetSubShape() );
00465         removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 );
00466       }
00467 
00468       if ( removeImport )
00469       {
00470         // treate removal of Import algo from subMesh
00471         removeSubmesh( subMesh, (_ListenerData*) data );
00472       }
00473       else if ( modifHyp )
00474       {
00475         // treate modification of ImportSource hypothesis
00476         clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false );
00477       }
00478       else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
00479                 SMESH_subMesh::COMPUTE_EVENT       == eventType )
00480       {
00481         // check compute state of all submeshes impoting from same src mesh;
00482         // this is to take into account 1D computed submeshes hidden by 2D import algo;
00483         // else source mesh is not copied as _subM.size != _computedSubM.size()
00484         list< _ImportData > &  dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
00485         list< _ImportData >::iterator d = dList.begin();
00486         for ( ; d != dList.end(); ++d )
00487           if ( d->_subM.count( subMesh ))
00488           {
00489             set<SMESH_subMesh*>::iterator smIt = d->_subM.begin();
00490             for( ; smIt != d->_subM.end(); ++smIt )
00491               if ( (*smIt)->IsMeshComputed() )
00492                 d->_computedSubM.insert( *smIt);
00493           }
00494       }
00495     }
00496   }
00497 
00498   //================================================================================
00502   //================================================================================
00503 
00504   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
00505                                 SMESH_Mesh*         tgtMesh)
00506   {
00507     // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
00508     // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
00509     // And this shape must be different from subshapes of the main shape.
00510     // So we create a compound containing
00511     // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
00512     //    srcMeshDS->GetPersistentId()
00513     // 2) the 1-st vertex of the main shape to assure
00514     //    SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
00515     TopoDS_Shape shapeForSrcMesh;
00516     TopTools_IndexedMapOfShape pseudoSubShapes;
00517     TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
00518 
00519     // index of pseudoSubShapes corresponding to srcMeshDS
00520     int subIndex = srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
00521     int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
00522 
00523     // try to find already present shapeForSrcMesh
00524     SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
00525     for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
00526     {
00527       const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
00528       if ( s.ShapeType() != TopAbs_COMPOUND ) break;
00529       TopoDS_Iterator sSubIt( s );
00530       for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
00531         if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
00532           if ( iSub+1 == nbSubShapes )
00533           {
00534             shapeForSrcMesh = s;
00535             break;
00536           }
00537     }
00538     if ( shapeForSrcMesh.IsNull() )
00539     {
00540       // make a new shapeForSrcMesh
00541       BRep_Builder aBuilder;
00542       TopoDS_Compound comp;
00543       aBuilder.MakeCompound( comp );
00544       shapeForSrcMesh = comp;
00545       for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
00546         aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
00547       TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
00548       aBuilder.Add( comp, vExp.Current() );
00549     }
00550     SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
00551     SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
00552     if ( !smDS )
00553       smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
00554 
00555     // make ordinary submesh from a complex one
00556     if ( smDS->IsComplexSubmesh() )
00557     {
00558       list< const SMESHDS_SubMesh* > subSM;
00559       SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
00560       while ( smIt->more() ) subSM.push_back( smIt->next() );
00561       list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
00562       for ( ; sub != subSM.end(); ++sub)
00563         smDS->RemoveSubMesh( *sub );
00564     }
00565     return sm->GetId();
00566   }
00567 
00568   //================================================================================
00574   //================================================================================
00575 
00576   SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh*                    srcMesh,
00577                                            SMESH_Mesh*                          tgtMesh,
00578                                            const TopoDS_Shape&                  tgtShape,
00579                                            StdMeshers_Import_1D::TNodeNodeMap*& n2n,
00580                                            StdMeshers_Import_1D::TElemElemMap*& e2e,
00581                                            bool &                               toCopyGroups)
00582   {
00583     StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
00584 
00585     _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
00586 
00587     SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
00588     iData->addComputed( importedSM );
00589     if ( iData->_computedSubM.size() != iData->_subM.size() )
00590       return 0; // not all submeshes computed yet
00591 
00592     toCopyGroups = !iData->_copyGroupSubM.empty();
00593 
00594     if ( !iData->_copyMeshSubM.empty())
00595     {
00596       // make submesh to store a copied mesh
00597       int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
00598       SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
00599 
00600       iData->_importMeshSubID = smID;
00601       iData->_importMeshSubDS = subDS;
00602       return subDS;
00603     }
00604     return 0;
00605   }
00606 
00607 } // namespace
00608 
00609 
00610 //=============================================================================
00614 //=============================================================================
00615 
00616 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
00617 {
00618   if ( !_sourceHyp ) return false;
00619 
00620   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
00621   if ( srcGroups.empty() )
00622     return error("Invalid source groups");
00623 
00624   SMESH_MesherHelper helper(theMesh);
00625   helper.SetSubShape(theShape);
00626   SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
00627 
00628   const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
00629   const double edgeTol = BRep_Tool::Tolerance( geomEdge );
00630   const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
00631 
00632   set<int> subShapeIDs;
00633   subShapeIDs.insert( shapeID );
00634 
00635   // get nodes on vertices
00636   list < SMESH_TNodeXYZ > vertexNodes; 
00637  list < SMESH_TNodeXYZ >::iterator vNIt;
00638   TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
00639   for ( ; vExp.More(); vExp.Next() )
00640   {
00641     const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
00642     if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
00643       continue; // closed edge
00644     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
00645     if ( !n )
00646     {
00647       _gen->Compute(theMesh,v,/*anUpward=*/true);
00648       n = SMESH_Algo::VertexNode( v, tgtMesh );
00649       if ( !n ) return false; // very strange
00650     }
00651     vertexNodes.push_back( SMESH_TNodeXYZ( n ));
00652   }
00653 
00654   // import edges from groups
00655   TNodeNodeMap* n2n;
00656   TElemElemMap* e2e;
00657   for ( int iG = 0; iG < srcGroups.size(); ++iG )
00658   {
00659     const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
00660 
00661     const int meshID = srcGroup->GetMesh()->GetPersistentId();
00662     const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
00663     if ( !srcMesh ) continue;
00664     getMaps( srcMesh, &theMesh, n2n, e2e );
00665 
00666     SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
00667     vector<const SMDS_MeshNode*> newNodes;
00668     SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
00669     double u;
00670     while ( srcElems->more() ) // loop on group contents
00671     {
00672       const SMDS_MeshElement* edge = srcElems->next();
00673       // find or create nodes of a new edge
00674       newNodes.resize( edge->NbNodes() );
00675       newNodes.back() = 0;
00676       SMDS_MeshElement::iterator node = edge->begin_nodes();
00677       for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
00678       {
00679         TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
00680         if ( n2nIt->second )
00681         {
00682           if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
00683             break;
00684         }
00685         else
00686         {
00687           // find an existing vertex node
00688           for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
00689             if ( vNIt->SquareDistance( *node ) < 10 * edgeTol * edgeTol)
00690             {
00691               (*n2nIt).second = vNIt->_node;
00692               vertexNodes.erase( vNIt );
00693               break;
00694             }
00695         }
00696         if ( !n2nIt->second )
00697         {
00698           // find out if node lies on theShape
00699           tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
00700           if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
00701           {
00702             SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
00703             n2nIt->second = newNode;
00704             tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
00705           }
00706         }
00707         if ( !(newNodes[i] = n2nIt->second ))
00708           break;
00709       }
00710       if ( !newNodes.back() )
00711         continue; // not all nodes of edge lie on theShape
00712 
00713       // make a new edge
00714       SMDS_MeshElement * newEdge;
00715       if ( newNodes.size() == 3 )
00716         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
00717       else
00718         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
00719       tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
00720       e2e->insert( make_pair( edge, newEdge ));
00721     }
00722     helper.GetMeshDS()->RemoveNode(tmpNode);
00723   }
00724   if ( n2n->empty())
00725     return error("Empty source groups");
00726 
00727   // check if the whole geom edge is covered by imported segments;
00728   // the check consist in passing by segments from one vetrex node to another
00729   bool isEdgeMeshed = false;
00730   if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
00731   {
00732     const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
00733     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
00734     const SMDS_MeshElement* seg = 0;
00735     SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
00736     while ( segIt->more() && !seg )
00737       if ( !tgtSM->Contains( seg = segIt->next()))
00738         seg = 0;
00739     int nbPassedSegs = 0;
00740     while ( seg )
00741     {
00742       ++nbPassedSegs;
00743       const SMDS_MeshNode* n2 = seg->GetNode(0);
00744       n = ( n2 == n ? seg->GetNode(1) : n2 );
00745       if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
00746         break;
00747       const SMDS_MeshElement* seg2 = 0;
00748       segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
00749       while ( segIt->more() && !seg2 )
00750         if ( seg == ( seg2 = segIt->next()))
00751           seg2 = 0;
00752       seg = seg2;
00753     }
00754     if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
00755       return error( "Source elements overlap one another");
00756 
00757     isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
00758                      n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
00759   }
00760   if ( !isEdgeMeshed )
00761     return error( "Source elements don't cover totally the geometrical edge" );
00762 
00763   // copy meshes
00764   vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
00765   for ( unsigned i = 0; i < srcMeshes.size(); ++i )
00766     importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
00767 
00768   return true;
00769 }
00770 
00771 //================================================================================
00775 //================================================================================
00776 
00777 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
00778                                       SMESH_Mesh &               tgtMesh,
00779                                       StdMeshers_ImportSource1D* srcHyp,
00780                                       const TopoDS_Shape&        tgtShape)
00781 {
00782   // get submesh to store the imported mesh
00783   TNodeNodeMap* n2n;
00784   TElemElemMap* e2e;
00785   bool toCopyGroups;
00786   SMESHDS_SubMesh* tgtSubMesh =
00787     getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
00788   if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
00789     return; // not to copy srcMeshDS twice
00790 
00791   SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
00792   SMESH_MeshEditor additor( &tgtMesh );
00793 
00794   // 1. Copy mesh
00795 
00796   vector<const SMDS_MeshNode*> newNodes;
00797   const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
00798   SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
00799   while ( eIt->more() )
00800   {
00801     const SMDS_MeshElement* elem = eIt->next();
00802     TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
00803     if ( e2eIt->second ) continue; // already copied by Compute()
00804     newNodes.resize( elem->NbNodes() );
00805     SMDS_MeshElement::iterator node = elem->begin_nodes();
00806     for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
00807     {
00808       TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
00809       if ( !n2nIt->second )
00810       {
00811         (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
00812         tgtSubMesh->AddNode( n2nIt->second );
00813       }
00814       newNodes[i] = n2nIt->second;
00815     }
00816     const SMDS_MeshElement* newElem =
00817       tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
00818     if ( !newElem )
00819     {
00820       newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
00821       tgtSubMesh->AddElement( newElem );
00822     }
00823     if ( toCopyGroups )
00824       (*e2eIt).second = newElem;
00825   }
00826   // copy free nodes
00827   if ( srcMeshDS->NbNodes() > n2n->size() )
00828   {
00829     SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
00830     while( nIt->more() )
00831     {
00832       const SMDS_MeshNode* node = nIt->next();
00833       if ( node->NbInverseElements() == 0 )
00834       {
00835         const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
00836         n2n->insert( make_pair( node, newNode ));
00837         tgtSubMesh->AddNode( newNode );
00838       }
00839     }
00840   }
00841 
00842   // 2. Copy groups
00843 
00844   vector<SMESH_Group*> resultGroups;
00845   if ( toCopyGroups )
00846   {
00847     // collect names of existing groups to assure uniqueness of group names within a type
00848     map< SMDSAbs_ElementType, set<string> > namesByType;
00849     SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
00850     while ( groupIt->more() )
00851     {
00852       SMESH_Group* tgtGroup = groupIt->next();
00853       namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
00854     }
00855     if (srcMesh)
00856     {
00857       SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
00858       while ( groupIt->more() )
00859       {
00860         SMESH_Group* srcGroup = groupIt->next();
00861         SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
00862         string name = srcGroup->GetName();
00863         int nb = 1;
00864         while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
00865           name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
00866         SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str(), nb );
00867         SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
00868         resultGroups.push_back( newGroup );
00869 
00870         eIt = srcGroupDS->GetElements();
00871         if ( srcGroupDS->GetType() == SMDSAbs_Node )
00872           while (eIt->more())
00873           {
00874             TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
00875             if ( n2nIt != n2n->end() && n2nIt->second )
00876               newGroupDS->SMDSGroup().Add((*n2nIt).second );
00877           }
00878         else
00879           while (eIt->more())
00880           {
00881             TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
00882             if ( e2eIt != e2e->end() && e2eIt->second )
00883               newGroupDS->SMDSGroup().Add((*e2eIt).second );
00884           }
00885       }
00886     }
00887   }
00888   n2n->clear();
00889   e2e->clear();
00890 
00891   // Remember created groups in order to remove them as soon as the srcHyp is
00892   // modified or something other similar happens. Store them in a hypothesis
00893   // as it stores its values anyway
00894   srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
00895 }
00896 
00897 //=============================================================================
00903 //=============================================================================
00904 
00905 void StdMeshers_Import_1D::setEventListener(SMESH_subMesh*             subMesh, 
00906                                             StdMeshers_ImportSource1D* sourceHyp)
00907 {
00908   if ( sourceHyp )
00909   {
00910     vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
00911     if ( srcMeshes.empty() )
00912       _Listener::waitHypModification( subMesh );
00913     for ( unsigned i = 0; i < srcMeshes.size(); ++i )
00914       // set a listener to remove the imported mesh and groups
00915       _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
00916   }
00917 }
00918 void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
00919 {
00920   if ( !_sourceHyp )
00921   {
00922     const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
00923     SMESH_Mesh*         tgtMesh  = subMesh->GetFather();
00924     Hypothesis_Status aStatus;
00925     CheckHypothesis( *tgtMesh, tgtShape, aStatus );
00926   }
00927   setEventListener( subMesh, _sourceHyp );
00928 }
00929 
00930 void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
00931 {
00932   SetEventListener(subMesh);
00933 }
00934 
00935 //=============================================================================
00939 //=============================================================================
00940 
00941 bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh &         theMesh,
00942                                     const TopoDS_Shape & theShape,
00943                                     MapShapeNbElems&     aResMap)
00944 {
00945   if ( !_sourceHyp ) return false;
00946 
00947   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
00948   if ( srcGroups.empty() )
00949     return error("Invalid source groups");
00950 
00951   vector<int> aVec(SMDSEntity_Last,0);
00952 
00953   bool toCopyMesh, toCopyGroups;
00954   _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
00955   if ( toCopyMesh ) // the whole mesh is copied
00956   {
00957     vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
00958     for ( unsigned i = 0; i < srcMeshes.size(); ++i )
00959     {
00960       SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
00961       if ( !sm || aResMap.count( sm )) continue; // already counted
00962       aVec.assign( SMDSEntity_Last, 0);
00963       const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
00964       for (int i = 0; i < SMDSEntity_Last; i++)
00965         aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
00966     }
00967   }
00968   else
00969   {
00970     SMESH_MesherHelper helper(theMesh);
00971 
00972     const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
00973     const double edgeTol = helper.MaxTolerance( geomEdge );
00974 
00975     // take into account nodes on vertices
00976     TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
00977     for ( ; vExp.More(); vExp.Next() )
00978       theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
00979 
00980     // count edges imported from groups
00981     int nbEdges = 0, nbQuadEdges = 0;
00982     for ( int iG = 0; iG < srcGroups.size(); ++iG )
00983     {
00984       const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
00985       SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
00986       SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
00987       while ( srcElems->more() ) // loop on group contents
00988       {
00989         const SMDS_MeshElement* edge = srcElems->next();
00990         // find out if edge is located on geomEdge by projecting
00991         // a middle of edge to geomEdge
00992         SMESH_TNodeXYZ p1( edge->GetNode(0));
00993         SMESH_TNodeXYZ p2( edge->GetNode(1));
00994         gp_XYZ middle = ( p1 + p2 ) / 2.;
00995         tmpNode->setXYZ( middle.X(), middle.Y(), middle.Z());
00996         double u = 0;
00997         if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
00998           ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
00999       }
01000       helper.GetMeshDS()->RemoveNode(tmpNode);
01001     }
01002 
01003     int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
01004 
01005     aVec[SMDSEntity_Node     ] = nbNodes;
01006     aVec[SMDSEntity_Edge     ] = nbEdges;
01007     aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
01008   }
01009 
01010   SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01011   aResMap.insert(make_pair(sm,aVec));
01012 
01013   return true;
01014 }
01015 
01016 //================================================================================
01020 //================================================================================
01021 
01022 void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
01023                                    SMESH_Mesh*       tgtMesh,
01024                                    TNodeNodeMap*&    n2n,
01025                                    TElemElemMap*&    e2e)
01026 {
01027   _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
01028   n2n = &iData->_n2n;
01029   e2e = &iData->_e2e;
01030   if ( iData->_copyMeshSubM.empty() )
01031   {
01032     n2n->clear();
01033     e2e->clear();
01034   }
01035 }
01036 
01037 //================================================================================
01041 //================================================================================
01042 
01043 SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
01044                                                              SMESH_Mesh& srcMesh )
01045 {
01046   _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
01047   if ( iData->_copyMeshSubM.empty() ) return 0;
01048   SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );
01049   return sm;
01050 }
01051 
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS