Back to index

salome-smesh  6.5.0
StdMeshers_Import_1D.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   : 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 group 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                                            "StdMeshers_Import_1D::_Listener") {}
00251 
00252   public:
00253     // return poiter to a static listener
00254     static _Listener* get() { static _Listener theListener; return &theListener; }
00255 
00256     static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh);
00257 
00258     static void storeImportSubmesh(SMESH_subMesh*                   importSub,
00259                                    const SMESH_Mesh*                srcMesh,
00260                                    const StdMeshers_ImportSource1D* srcHyp);
00261 
00262     virtual void ProcessEvent(const int                       event,
00263                               const int                       eventType,
00264                               SMESH_subMesh*                  subMesh,
00265                               SMESH_subMeshEventListenerData* data,
00266                               const SMESH_Hypothesis*         hyp);
00267     void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data );
00268     void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub );
00269 
00270     // mark sm as missing src hyp with valid groups
00271     static void waitHypModification(SMESH_subMesh* sm)
00272     {
00273       sm->SetEventListener
00274         (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
00275     }
00276   };
00277   //--------------------------------------------------------------------------------
00281   _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh,
00282                                         SMESH_Mesh*       tgtMesh)
00283   {
00284     list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
00285     list< _ImportData >::iterator d = dList.begin();
00286     for ( ; d != dList.end(); ++d )
00287       if ( d->_srcMesh == srcMesh )
00288         return &*d;
00289     dList.push_back(_ImportData(srcMesh));
00290     return &dList.back();
00291   }
00292 
00293   //--------------------------------------------------------------------------------
00300   void _Listener::storeImportSubmesh(SMESH_subMesh*                   importSub,
00301                                      const SMESH_Mesh*                srcMesh,
00302                                      const StdMeshers_ImportSource1D* srcHyp)
00303   {
00304     // set listener to hear events of the submesh computed by "Import" algo
00305     importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
00306 
00307     // set listeners to hear events of the source mesh
00308     SMESH_subMesh* smToNotify = importSub;
00309     vector<SMESH_subMesh*> smToListen = srcHyp->GetSourceSubMeshes( srcMesh );
00310     for ( size_t i = 0; i < smToListen.size(); ++i )
00311     {
00312       SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH);
00313       data->mySubMeshes.push_back( smToNotify );
00314       importSub->SetEventListener( get(), data, smToListen[i] );
00315     }
00316     // remember the submesh importSub and its sub-submeshes
00317     _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
00318     iData->trackHypParams( importSub, srcHyp );
00319     iData->addComputed( importSub );
00320     if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
00321     {
00322       SMESH_Mesh* tgtMesh = importSub->GetFather();
00323       iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
00324       iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
00325     }
00326   }
00327   //--------------------------------------------------------------------------------
00333   void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
00334   {
00335     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
00336     list< _ImportData >::iterator d = dList.begin();
00337     for ( ; d != dList.end(); ++d )
00338       if ( (*d)._subM.erase( sm ))
00339       {
00340         d->_computedSubM.erase( sm );
00341         bool rmMesh   = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
00342         bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
00343         if ( rmMesh )
00344           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
00345         if ( rmGroups && data )
00346           d->removeGroups( sm, data->_srcHyp );
00347       }
00348   }
00349   //--------------------------------------------------------------------------------
00355   void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub)
00356   {
00357     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
00358     list< _ImportData >::iterator d = dList.begin();
00359     for ( ; d != dList.end(); ++d )
00360     {
00361       if ( !d->_subM.count( sm )) continue;
00362       if ( (*d)._computedSubM.erase( sm ) )
00363       {
00364         bool copyMesh = !d->_copyMeshSubM.empty();
00365         if ( copyMesh || clearAllSub )
00366         {
00367           // remove imported mesh and groups
00368           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
00369 
00370           if ( data )
00371             d->removeGroups( sm, data->_srcHyp );
00372 
00373           // clear the rest submeshes
00374           if ( !d->_computedSubM.empty() )
00375           {
00376             d->_computedSubM.clear();
00377             set< SMESH_subMesh*, _SubLess>::iterator sub = d->_subM.begin();
00378             for ( ; sub != d->_subM.end(); ++sub )
00379             {
00380               SMESH_subMesh* subM = *sub;
00381               _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
00382               if ( hypData )
00383                 d->removeGroups( sm, hypData->_srcHyp );
00384 
00385               subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
00386               if ( subM->GetSubShape().ShapeType() == TopAbs_FACE )
00387                 subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
00388             }
00389           }
00390         }
00391         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
00392         if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
00393           sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
00394       }
00395       if ( data )
00396         d->trackHypParams( sm, data->_srcHyp );
00397       d->_n2n.clear();
00398       d->_e2e.clear();
00399     }
00400   }
00401   //--------------------------------------------------------------------------------
00405   void _Listener::ProcessEvent(const int                       event,
00406                                const int                       eventType,
00407                                SMESH_subMesh*                  subMesh,
00408                                SMESH_subMeshEventListenerData* data,
00409                                const SMESH_Hypothesis*         /*hyp*/)
00410   {
00411     if ( data && data->myType == WAIT_HYP_MODIF )
00412     {
00413       // event of Import submesh
00414       if ( SMESH_subMesh::MODIF_HYP  == event &&
00415            SMESH_subMesh::ALGO_EVENT == eventType )
00416       {
00417         // re-call SetEventListener() to take into account valid parameters
00418         // of ImportSource hypothesis
00419         if ( SMESH_Algo* algo = subMesh->GetAlgo() )
00420           algo->SetEventListener( subMesh );
00421       }
00422     }
00423     else if ( data && data->myType == LISTEN_SRC_MESH )
00424     {
00425       // event of source mesh
00426       if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
00427       {
00428         switch ( event ) {
00429         case SMESH_subMesh::CLEAN:
00430           // source mesh cleaned -> clean target mesh
00431           clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true );
00432           break;
00433         case SMESH_subMesh::SUBMESH_COMPUTED: {
00434           // source mesh computed -> reset FAILED state of Import submeshes to
00435           // READY_TO_COMPUTE
00436           SMESH_Mesh* srcMesh = subMesh->GetFather();
00437           if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 )
00438           {
00439             SMESH_Mesh* m = data->mySubMeshes.front()->GetFather();
00440             if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1))
00441             {
00442               sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED );
00443               sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
00444             }
00445           }
00446           break;
00447         }
00448         default:;
00449         }
00450       }
00451     }
00452     else // event of Import submesh
00453     {
00454       // find out what happens: import hyp modified or removed
00455       bool removeImport = false, modifHyp = false;
00456       if ( SMESH_subMesh::ALGO_EVENT == eventType )
00457         modifHyp = true;
00458       if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
00459       {
00460         removeImport = true;
00461       }
00462       else if (( SMESH_subMesh::REMOVE_ALGO == event ||
00463                  SMESH_subMesh::REMOVE_FATHER_ALGO == event ) &&
00464                SMESH_subMesh::ALGO_EVENT == eventType )
00465       {
00466         SMESH_Algo* algo = subMesh->GetAlgo();
00467         removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 );
00468       }
00469 
00470       if ( removeImport )
00471       {
00472         // treate removal of Import algo from subMesh
00473         removeSubmesh( subMesh, (_ListenerData*) data );
00474       }
00475       else if ( modifHyp ||
00476                 ( SMESH_subMesh::CLEAN         == event &&
00477                   SMESH_subMesh::COMPUTE_EVENT == eventType))
00478       {
00479         // treate modification of ImportSource hypothesis
00480         clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false );
00481       }
00482       else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
00483                 SMESH_subMesh::COMPUTE_EVENT       == eventType )
00484       {
00485         // check compute state of all submeshes impoting from same src mesh;
00486         // this is to take into account 1D computed submeshes hidden by 2D import algo;
00487         // else source mesh is not copied as _subM.size != _computedSubM.size()
00488         list< _ImportData > &  dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
00489         list< _ImportData >::iterator d = dList.begin();
00490         for ( ; d != dList.end(); ++d )
00491           if ( d->_subM.count( subMesh ))
00492           {
00493             set<SMESH_subMesh*,_SubLess>::iterator smIt = d->_subM.begin();
00494             for( ; smIt != d->_subM.end(); ++smIt )
00495               if ( (*smIt)->IsMeshComputed() )
00496                 d->_computedSubM.insert( *smIt);
00497           }
00498       }
00499     }
00500   }
00501 
00502   //================================================================================
00506   //================================================================================
00507 
00508   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
00509                                 SMESH_Mesh*         tgtMesh)
00510   {
00511     // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
00512     // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
00513     // And this shape must be different from sub-shapes of the main shape.
00514     // So we create a compound containing
00515     // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
00516     //    srcMeshDS->GetPersistentId()
00517     // 2) the 1-st vertex of the main shape to assure
00518     //    SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
00519     TopoDS_Shape shapeForSrcMesh;
00520     TopTools_IndexedMapOfShape pseudoSubShapes;
00521     TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
00522 
00523     // index of pseudoSubShapes corresponding to srcMeshDS
00524     int subIndex = srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
00525     int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
00526 
00527     // try to find already present shapeForSrcMesh
00528     SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
00529     for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
00530     {
00531       const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
00532       if ( s.ShapeType() != TopAbs_COMPOUND ) break;
00533       TopoDS_Iterator sSubIt( s );
00534       for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
00535         if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
00536           if ( iSub+1 == nbSubShapes )
00537           {
00538             shapeForSrcMesh = s;
00539             break;
00540           }
00541     }
00542     if ( shapeForSrcMesh.IsNull() )
00543     {
00544       // make a new shapeForSrcMesh
00545       BRep_Builder aBuilder;
00546       TopoDS_Compound comp;
00547       aBuilder.MakeCompound( comp );
00548       shapeForSrcMesh = comp;
00549       for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
00550         aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
00551       TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
00552       aBuilder.Add( comp, vExp.Current() );
00553     }
00554     SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
00555     SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
00556     if ( !smDS )
00557       smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
00558 
00559     // make ordinary submesh from a complex one
00560     if ( smDS->IsComplexSubmesh() )
00561     {
00562       list< const SMESHDS_SubMesh* > subSM;
00563       SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
00564       while ( smIt->more() ) subSM.push_back( smIt->next() );
00565       list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
00566       for ( ; sub != subSM.end(); ++sub)
00567         smDS->RemoveSubMesh( *sub );
00568     }
00569     return sm->GetId();
00570   }
00571 
00572   //================================================================================
00578   //================================================================================
00579 
00580   SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh*                    srcMesh,
00581                                            SMESH_Mesh*                          tgtMesh,
00582                                            const TopoDS_Shape&                  tgtShape,
00583                                            StdMeshers_Import_1D::TNodeNodeMap*& n2n,
00584                                            StdMeshers_Import_1D::TElemElemMap*& e2e,
00585                                            bool &                               toCopyGroups)
00586   {
00587     StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
00588 
00589     _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
00590 
00591     SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
00592     iData->addComputed( importedSM );
00593     if ( iData->_computedSubM.size() != iData->_subM.size() )
00594       return 0; // not all submeshes computed yet
00595 
00596     toCopyGroups = !iData->_copyGroupSubM.empty();
00597 
00598     if ( !iData->_copyMeshSubM.empty())
00599     {
00600       // make submesh to store a copied mesh
00601       int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
00602       SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
00603 
00604       iData->_importMeshSubID = smID;
00605       iData->_importMeshSubDS = subDS;
00606       return subDS;
00607     }
00608     return 0;
00609   }
00610 
00611 } // namespace
00612 
00613 
00614 //=============================================================================
00618 //=============================================================================
00619 
00620 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
00621 {
00622   if ( !_sourceHyp ) return false;
00623 
00624   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
00625   if ( srcGroups.empty() )
00626     return error("Invalid source groups");
00627 
00628   SMESH_MesherHelper helper(theMesh);
00629   helper.SetSubShape(theShape);
00630   SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
00631 
00632   const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
00633   const double edgeTol = BRep_Tool::Tolerance( geomEdge );
00634   const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
00635 
00636   set<int> subShapeIDs;
00637   subShapeIDs.insert( shapeID );
00638 
00639   // get nodes on vertices
00640   list < SMESH_TNodeXYZ > vertexNodes; 
00641  list < SMESH_TNodeXYZ >::iterator vNIt;
00642   TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
00643   for ( ; vExp.More(); vExp.Next() )
00644   {
00645     const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
00646     if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
00647       continue; // closed edge
00648     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
00649     if ( !n )
00650     {
00651       _gen->Compute(theMesh,v,/*anUpward=*/true);
00652       n = SMESH_Algo::VertexNode( v, tgtMesh );
00653       if ( !n ) return false; // very strange
00654     }
00655     vertexNodes.push_back( SMESH_TNodeXYZ( n ));
00656   }
00657 
00658   // import edges from groups
00659   TNodeNodeMap* n2n;
00660   TElemElemMap* e2e;
00661   for ( int iG = 0; iG < srcGroups.size(); ++iG )
00662   {
00663     const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
00664 
00665     const int meshID = srcGroup->GetMesh()->GetPersistentId();
00666     const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
00667     if ( !srcMesh ) continue;
00668     getMaps( srcMesh, &theMesh, n2n, e2e );
00669 
00670     SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
00671     vector<const SMDS_MeshNode*> newNodes;
00672     SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
00673     double u;
00674     while ( srcElems->more() ) // loop on group contents
00675     {
00676       const SMDS_MeshElement* edge = srcElems->next();
00677       // find or create nodes of a new edge
00678       newNodes.resize( edge->NbNodes() );
00679       newNodes.back() = 0;
00680       SMDS_MeshElement::iterator node = edge->begin_nodes();
00681       for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
00682       {
00683         TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
00684         if ( n2nIt->second )
00685         {
00686           if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
00687             break;
00688         }
00689         else
00690         {
00691           // find an existing vertex node
00692           for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
00693             if ( vNIt->SquareDistance( *node ) < 10 * edgeTol * edgeTol)
00694             {
00695               (*n2nIt).second = vNIt->_node;
00696               vertexNodes.erase( vNIt );
00697               break;
00698             }
00699         }
00700         if ( !n2nIt->second )
00701         {
00702           // find out if node lies on theShape
00703           tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
00704           if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
00705           {
00706             SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
00707             n2nIt->second = newNode;
00708             tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
00709           }
00710         }
00711         if ( !(newNodes[i] = n2nIt->second ))
00712           break;
00713       }
00714       if ( !newNodes.back() )
00715         continue; // not all nodes of edge lie on theShape
00716 
00717       // make a new edge
00718       SMDS_MeshElement * newEdge;
00719       if ( newNodes.size() == 3 )
00720         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
00721       else
00722         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
00723       tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
00724       e2e->insert( make_pair( edge, newEdge ));
00725     }
00726     helper.GetMeshDS()->RemoveNode(tmpNode);
00727   }
00728   if ( n2n->empty())
00729     return error("Empty source groups");
00730 
00731   // check if the whole geom edge is covered by imported segments;
00732   // the check consist in passing by segments from one vetrex node to another
00733   bool isEdgeMeshed = false;
00734   if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
00735   {
00736     const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
00737     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
00738     const SMDS_MeshElement* seg = 0;
00739     SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
00740     while ( segIt->more() && !seg )
00741       if ( !tgtSM->Contains( seg = segIt->next()))
00742         seg = 0;
00743     int nbPassedSegs = 0;
00744     while ( seg )
00745     {
00746       ++nbPassedSegs;
00747       const SMDS_MeshNode* n2 = seg->GetNode(0);
00748       n = ( n2 == n ? seg->GetNode(1) : n2 );
00749       if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
00750         break;
00751       const SMDS_MeshElement* seg2 = 0;
00752       segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
00753       while ( segIt->more() && !seg2 )
00754         if ( seg == ( seg2 = segIt->next()))
00755           seg2 = 0;
00756       seg = seg2;
00757     }
00758     if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
00759       return error( "Source elements overlap one another");
00760 
00761     isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
00762                      n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
00763   }
00764   if ( !isEdgeMeshed )
00765     return error( "Source elements don't cover totally the geometrical edge" );
00766 
00767   // copy meshes
00768   vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
00769   for ( unsigned i = 0; i < srcMeshes.size(); ++i )
00770     importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
00771 
00772   return true;
00773 }
00774 
00775 //================================================================================
00779 //================================================================================
00780 
00781 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
00782                                       SMESH_Mesh &               tgtMesh,
00783                                       StdMeshers_ImportSource1D* srcHyp,
00784                                       const TopoDS_Shape&        tgtShape)
00785 {
00786   // get submesh to store the imported mesh
00787   TNodeNodeMap* n2n;
00788   TElemElemMap* e2e;
00789   bool toCopyGroups;
00790   SMESHDS_SubMesh* tgtSubMesh =
00791     getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
00792   if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
00793     return; // not to copy srcMeshDS twice
00794 
00795   SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
00796   SMESH_MeshEditor additor( &tgtMesh );
00797 
00798   // 1. Copy mesh
00799 
00800   vector<const SMDS_MeshNode*> newNodes;
00801   const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
00802   SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
00803   while ( eIt->more() )
00804   {
00805     const SMDS_MeshElement* elem = eIt->next();
00806     TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
00807     if ( e2eIt->second ) continue; // already copied by Compute()
00808     newNodes.resize( elem->NbNodes() );
00809     SMDS_MeshElement::iterator node = elem->begin_nodes();
00810     for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
00811     {
00812       TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
00813       if ( !n2nIt->second )
00814       {
00815         (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
00816         tgtSubMesh->AddNode( n2nIt->second );
00817       }
00818       newNodes[i] = n2nIt->second;
00819     }
00820     const SMDS_MeshElement* newElem =
00821       tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
00822     if ( !newElem )
00823     {
00824       newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
00825       tgtSubMesh->AddElement( newElem );
00826     }
00827     if ( toCopyGroups )
00828       (*e2eIt).second = newElem;
00829   }
00830   // copy free nodes
00831   if ( srcMeshDS->NbNodes() > n2n->size() )
00832   {
00833     SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
00834     while( nIt->more() )
00835     {
00836       const SMDS_MeshNode* node = nIt->next();
00837       if ( node->NbInverseElements() == 0 )
00838       {
00839         const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
00840         n2n->insert( make_pair( node, newNode ));
00841         tgtSubMesh->AddNode( newNode );
00842       }
00843     }
00844   }
00845 
00846   // 2. Copy groups
00847 
00848   vector<SMESH_Group*> resultGroups;
00849   if ( toCopyGroups )
00850   {
00851     // collect names of existing groups to assure uniqueness of group names within a type
00852     map< SMDSAbs_ElementType, set<string> > namesByType;
00853     SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
00854     while ( groupIt->more() )
00855     {
00856       SMESH_Group* tgtGroup = groupIt->next();
00857       namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
00858     }
00859     if (srcMesh)
00860     {
00861       SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
00862       while ( groupIt->more() )
00863       {
00864         SMESH_Group* srcGroup = groupIt->next();
00865         SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
00866         string name = srcGroup->GetName();
00867         int nb = 1;
00868         while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
00869           name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
00870         SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str(), nb );
00871         SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
00872         resultGroups.push_back( newGroup );
00873 
00874         eIt = srcGroupDS->GetElements();
00875         if ( srcGroupDS->GetType() == SMDSAbs_Node )
00876           while (eIt->more())
00877           {
00878             TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
00879             if ( n2nIt != n2n->end() && n2nIt->second )
00880               newGroupDS->SMDSGroup().Add((*n2nIt).second );
00881           }
00882         else
00883           while (eIt->more())
00884           {
00885             TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
00886             if ( e2eIt != e2e->end() && e2eIt->second )
00887               newGroupDS->SMDSGroup().Add((*e2eIt).second );
00888           }
00889       }
00890     }
00891   }
00892   n2n->clear();
00893   e2e->clear();
00894 
00895   // Remember created groups in order to remove them as soon as the srcHyp is
00896   // modified or something other similar happens. This imformation must be persistent,
00897   // for that store them in a hypothesis as it stores its values in the file anyway
00898   srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
00899 }
00900 
00901 //=============================================================================
00907 //=============================================================================
00908 
00909 void StdMeshers_Import_1D::setEventListener(SMESH_subMesh*             subMesh, 
00910                                             StdMeshers_ImportSource1D* sourceHyp)
00911 {
00912   if ( sourceHyp )
00913   {
00914     vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
00915     if ( srcMeshes.empty() )
00916       _Listener::waitHypModification( subMesh );
00917     for ( unsigned i = 0; i < srcMeshes.size(); ++i )
00918       // set a listener to remove the imported mesh and groups
00919       _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
00920   }
00921 }
00922 void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
00923 {
00924   if ( !_sourceHyp )
00925   {
00926     const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
00927     SMESH_Mesh*         tgtMesh  = subMesh->GetFather();
00928     Hypothesis_Status aStatus;
00929     CheckHypothesis( *tgtMesh, tgtShape, aStatus );
00930   }
00931   setEventListener( subMesh, _sourceHyp );
00932 }
00933 
00934 void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
00935 {
00936   SetEventListener(subMesh);
00937 }
00938 
00939 //=============================================================================
00943 //=============================================================================
00944 
00945 bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh &         theMesh,
00946                                     const TopoDS_Shape & theShape,
00947                                     MapShapeNbElems&     aResMap)
00948 {
00949   if ( !_sourceHyp ) return false;
00950 
00951   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
00952   if ( srcGroups.empty() )
00953     return error("Invalid source groups");
00954 
00955   vector<int> aVec(SMDSEntity_Last,0);
00956 
00957   bool toCopyMesh, toCopyGroups;
00958   _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
00959   if ( toCopyMesh ) // the whole mesh is copied
00960   {
00961     vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
00962     for ( unsigned i = 0; i < srcMeshes.size(); ++i )
00963     {
00964       SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
00965       if ( !sm || aResMap.count( sm )) continue; // already counted
00966       aVec.assign( SMDSEntity_Last, 0);
00967       const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
00968       for (int i = 0; i < SMDSEntity_Last; i++)
00969         aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
00970     }
00971   }
00972   else
00973   {
00974     SMESH_MesherHelper helper(theMesh);
00975 
00976     const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
00977     const double edgeTol = helper.MaxTolerance( geomEdge );
00978 
00979     // take into account nodes on vertices
00980     TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
00981     for ( ; vExp.More(); vExp.Next() )
00982       theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
00983 
00984     // count edges imported from groups
00985     int nbEdges = 0, nbQuadEdges = 0;
00986     for ( int iG = 0; iG < srcGroups.size(); ++iG )
00987     {
00988       const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
00989       SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
00990       SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
00991       while ( srcElems->more() ) // loop on group contents
00992       {
00993         const SMDS_MeshElement* edge = srcElems->next();
00994         // find out if edge is located on geomEdge by projecting
00995         // a middle of edge to geomEdge
00996         SMESH_TNodeXYZ p1( edge->GetNode(0));
00997         SMESH_TNodeXYZ p2( edge->GetNode(1));
00998         gp_XYZ middle = ( p1 + p2 ) / 2.;
00999         tmpNode->setXYZ( middle.X(), middle.Y(), middle.Z());
01000         double u = 0;
01001         if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
01002           ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
01003       }
01004       helper.GetMeshDS()->RemoveNode(tmpNode);
01005     }
01006 
01007     int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
01008 
01009     aVec[SMDSEntity_Node     ] = nbNodes;
01010     aVec[SMDSEntity_Edge     ] = nbEdges;
01011     aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
01012   }
01013 
01014   SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01015   aResMap.insert(make_pair(sm,aVec));
01016 
01017   return true;
01018 }
01019 
01020 //================================================================================
01024 //================================================================================
01025 
01026 void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
01027                                    SMESH_Mesh*       tgtMesh,
01028                                    TNodeNodeMap*&    n2n,
01029                                    TElemElemMap*&    e2e)
01030 {
01031   _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
01032   n2n = &iData->_n2n;
01033   e2e = &iData->_e2e;
01034   if ( iData->_copyMeshSubM.empty() )
01035   {
01036     n2n->clear();
01037     e2e->clear();
01038   }
01039 }
01040 
01041 //================================================================================
01045 //================================================================================
01046 
01047 SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
01048                                                              SMESH_Mesh& srcMesh )
01049 {
01050   _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
01051   if ( iData->_copyMeshSubM.empty() ) return 0;
01052   SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );
01053   return sm;
01054 }
01055