Back to index

salome-smesh  6.5.0
StdMeshers_Projection_1D2D.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 // File      : StdMeshers_Projection_1D2D.cxx
00023 // Module    : SMESH
00024 // Author    : Edward AGAPOV (eap)
00025 //
00026 #include "StdMeshers_Projection_1D2D.hxx"
00027 
00028 #include "SMESH_Gen.hxx"
00029 #include "SMESH_MesherHelper.hxx"
00030 #include "SMESH_subMeshEventListener.hxx"
00031 #include "StdMeshers_FaceSide.hxx"
00032 #include "StdMeshers_ProjectionSource2D.hxx"
00033 #include "StdMeshers_ProjectionUtils.hxx"
00034 
00035 #include <TopoDS.hxx>
00036 #include <TopExp_Explorer.hxx>
00037 
00038 using namespace std;
00039 
00040 namespace
00041 {
00042   // --------------------------------------------------------------------------------
00047   struct EventProparatorToEdges : public SMESH_subMeshEventListener
00048   {
00049     EventProparatorToEdges(): SMESH_subMeshEventListener(/*isDeletable=*/false,
00050                                                          "Projection_1D2D::EventProparatorToEdges")
00051     {}
00052     static EventProparatorToEdges* Instance() { static EventProparatorToEdges E; return &E; }
00053 
00054     static void Set(SMESH_subMesh* faceSubMesh)
00055     {
00056       SMESH_subMeshEventListenerData* edgeSubMeshes =
00057         new SMESH_subMeshEventListenerData(/*isDeletable=*/true);
00058       SMESH_Mesh* mesh = faceSubMesh->GetFather();
00059       TopExp_Explorer eExp( faceSubMesh->GetSubShape(), TopAbs_EDGE );
00060       for ( ; eExp.More(); eExp.Next() )
00061         edgeSubMeshes->mySubMeshes.push_back( mesh->GetSubMesh( eExp.Current() ));
00062 
00063       // set a listener
00064       faceSubMesh->SetEventListener( Instance(), edgeSubMeshes, faceSubMesh );
00065     }
00066   };
00067   // --------------------------------------------------------------------------------
00074   struct UnsetterOfEventProparatorToEdges
00075   {
00076     SMESH_subMesh* _faceSubMesh;
00077     UnsetterOfEventProparatorToEdges( SMESH_subMesh* faceSubMesh ):_faceSubMesh(faceSubMesh)
00078     {
00079       faceSubMesh->DeleteEventListener( EventProparatorToEdges::Instance() );
00080     }
00081     ~UnsetterOfEventProparatorToEdges()
00082     {
00083       EventProparatorToEdges::Set(_faceSubMesh);
00084     }
00085   };
00086 }
00087 
00088 //=======================================================================
00089 //function : StdMeshers_Projection_1D2D
00090 //purpose  : 
00091 //=======================================================================
00092 
00093 StdMeshers_Projection_1D2D::StdMeshers_Projection_1D2D(int hypId, int studyId, SMESH_Gen* gen)
00094   :StdMeshers_Projection_2D(hypId, studyId, gen)
00095 {
00096   _name = "Projection_1D2D";
00097   _requireDiscreteBoundary = false;
00098   _supportSubmeshes = true;
00099 }
00100 
00101 //=======================================================================
00102 //function : Compute
00103 //purpose  : 
00104 //=======================================================================
00105 
00106 bool StdMeshers_Projection_1D2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
00107 {
00108   UnsetterOfEventProparatorToEdges eventBarrier( theMesh.GetSubMesh( theShape ));
00109 
00110   if ( !StdMeshers_Projection_2D::Compute(theMesh, theShape))
00111     return false;
00112 
00113   SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00114 
00115   SMESHDS_SubMesh * faceSubMesh = meshDS->MeshElements( theShape );
00116   if ( !faceSubMesh || faceSubMesh->NbElements() == 0 ) return false;
00117   _quadraticMesh = faceSubMesh->GetElements()->next()->IsQuadratic();
00118 
00119   SMESH_MesherHelper helper( theMesh );
00120   helper.SetSubShape( theShape );
00121 
00122   TopoDS_Face F = TopoDS::Face( theShape );
00123   TError err;
00124   TSideVector wires = StdMeshers_FaceSide::GetFaceWires( F, theMesh,
00125                                                          /*ignoreMediumNodes=*/false, err);
00126   if ( err && !err->IsOK() )
00127     return error( err );
00128 
00129   for ( size_t iWire = 0; iWire < wires.size(); ++iWire )
00130   {
00131     vector<const SMDS_MeshNode*> nodes = wires[ iWire ]->GetOrderedNodes();
00132     if ( nodes.empty() )
00133       return error("Wrong nodes on a wire");
00134 
00135     // check that all nodes are shared by faces generated on F
00136     for ( size_t i = 0; i < nodes.size(); ++i )
00137     {
00138       SMDS_ElemIteratorPtr fIt = nodes[i]->GetInverseElementIterator(SMDSAbs_Face);
00139       bool faceFound = false;
00140       while ( !faceFound && fIt->more() )
00141         faceFound = ( helper.GetSubShapeID() == fIt->next()->getshapeId() );
00142       if ( !faceFound )
00143         return error("The existing 1D mesh mismatches the generated 2D mesh");
00144     }
00145 
00146     const bool checkExisting = ( wires[ iWire ]->NbSegments() || helper.HasSeam() );
00147 
00148     if ( _quadraticMesh )
00149     {
00150       for ( size_t i = 2; i < nodes.size(); i += 2 )
00151       {
00152         if ( checkExisting && meshDS->FindEdge( nodes[i-2], nodes[i], nodes[i-1]))
00153           continue;
00154         SMDS_MeshElement* e = meshDS->AddEdge( nodes[i-2], nodes[i], nodes[i-1] );
00155         meshDS->SetMeshElementOnShape( e, nodes[i-1]->getshapeId() );
00156       }
00157     }
00158     else
00159     {
00160       int edgeID = meshDS->ShapeToIndex( wires[ iWire ]->Edge(0) );
00161       for ( size_t i = 1; i < nodes.size(); ++i )
00162       {
00163         if ( checkExisting && meshDS->FindEdge( nodes[i-1], nodes[i]))
00164           continue;
00165         SMDS_MeshElement* e = meshDS->AddEdge( nodes[i-1], nodes[i] );
00166         if ( nodes[i-1]->getshapeId() != edgeID &&
00167              nodes[i  ]->getshapeId() != edgeID )
00168         {
00169           edgeID = helper.GetMediumPos( nodes[i-1], nodes[i] ).first;
00170           if ( edgeID < 1 ) edgeID = helper.GetSubShapeID();
00171         }
00172         meshDS->SetMeshElementOnShape( e, edgeID );
00173       }
00174     }
00175   }   
00176 
00177   return true;
00178 }
00179 
00180 //=======================================================================
00181 //function : Evaluate
00182 //purpose  : 
00183 //=======================================================================
00184 
00185 bool StdMeshers_Projection_1D2D::Evaluate(SMESH_Mesh&         theMesh,
00186                                           const TopoDS_Shape& theShape,
00187                                           MapShapeNbElems&    aResMap)
00188 {
00189   if ( !StdMeshers_Projection_2D::Evaluate(theMesh,theShape,aResMap))
00190     return false;
00191 
00192   TopoDS_Shape srcFace = _sourceHypo->GetSourceFace();
00193   SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
00194   if ( !srcMesh ) srcMesh = & theMesh;
00195   SMESH_subMesh* srcFaceSM = srcMesh->GetSubMesh( srcFace );
00196 
00197   typedef StdMeshers_ProjectionUtils SPU;
00198   SPU::TShapeShapeMap shape2ShapeMap;
00199   SPU::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
00200   if ( !SPU::FindSubShapeAssociation( theShape, &theMesh, srcFace, srcMesh, shape2ShapeMap))
00201     return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
00202 
00203   MapShapeNbElems srcResMap;
00204   if ( !srcFaceSM->IsMeshComputed() )
00205     _gen->Evaluate( *srcMesh, srcFace, srcResMap);
00206 
00207   SMESH_subMeshIteratorPtr smIt = srcFaceSM->getDependsOnIterator(/*includeSelf=*/false,
00208                                                                   /*complexShapeFirst=*/true);
00209   while ( smIt->more() )
00210   {
00211     SMESH_subMesh* srcSM = smIt->next();
00212     TopAbs_ShapeEnum shapeType = srcSM->GetSubShape().ShapeType();
00213     if ( shapeType == TopAbs_EDGE )
00214     {
00215       std::vector<int> aVec;
00216       SMESHDS_SubMesh* srcSubMeshDS = srcSM->GetSubMeshDS();
00217       if ( srcSubMeshDS && srcSubMeshDS->NbElements() )
00218       {
00219         aVec.resize(SMDSEntity_Last, 0);
00220         SMDS_ElemIteratorPtr eIt = srcSubMeshDS->GetElements();
00221         _quadraticMesh = ( eIt->more() && eIt->next()->IsQuadratic() );
00222 
00223         aVec[SMDSEntity_Node] = srcSubMeshDS->NbNodes();
00224         aVec[_quadraticMesh ? SMDSEntity_Quad_Edge : SMDSEntity_Edge] = srcSubMeshDS->NbElements();
00225       }
00226       else
00227       {
00228         if ( srcResMap.empty() )
00229           if ( !_gen->Evaluate( *srcMesh, srcSM->GetSubShape(), srcResMap ))
00230             return error(COMPERR_BAD_INPUT_MESH,"Source mesh not evaluatable");
00231         aVec = srcResMap[ srcSM ];
00232         if ( aVec.empty() )
00233           return error(COMPERR_BAD_INPUT_MESH,"Source mesh is wrongly evaluated");
00234       }
00235       TopoDS_Shape tgtEdge = shape2ShapeMap( srcSM->GetSubShape(), /*isSrc=*/true  );
00236       SMESH_subMesh* tgtSM = theMesh.GetSubMesh( tgtEdge );
00237       aResMap.insert(std::make_pair(tgtSM,aVec));
00238     }
00239     if ( shapeType == TopAbs_VERTEX ) break;
00240   }
00241 
00242   return true;
00243 }
00244 
00245 //=======================================================================
00246 //function : SetEventListener
00247 //purpose  : Sets a default event listener to submesh of the source face.
00248 //           faceSubMesh - submesh where algo is set
00249 // After being set, event listener is notified on each event of a submesh.
00250 // This method is called when a submesh gets HYP_OK algo_state.
00251 // Arranges that CLEAN event is translated from source submesh to
00252 // the faceSubMesh submesh.
00253 //=======================================================================
00254 
00255 void StdMeshers_Projection_1D2D::SetEventListener(SMESH_subMesh* faceSubMesh)
00256 {
00257   // set a listener of events on a source submesh
00258   StdMeshers_Projection_2D::SetEventListener(faceSubMesh);
00259 
00260   // set a listener to the target FACE submesh in order to update submehses
00261   // of EDGEs according to events on the target FACE submesh
00262   EventProparatorToEdges::Set( faceSubMesh );
00263 }
00264