Back to index

salome-smesh  6.5.0
StdMeshers_Projection_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_Projection_1D.cxx
00025 // Module    : SMESH
00026 // Created   : Fri Oct 20 11:37:07 2006
00027 // Author    : Edward AGAPOV (eap)
00028 //
00029 #include "StdMeshers_Projection_1D.hxx"
00030 
00031 #include "StdMeshers_ProjectionSource1D.hxx"
00032 #include "StdMeshers_ProjectionUtils.hxx"
00033 
00034 #include "SMDS_MeshNode.hxx"
00035 #include "SMDS_MeshElement.hxx"
00036 #include "SMESHDS_Mesh.hxx"
00037 #include "SMESHDS_SubMesh.hxx"
00038 #include "SMESH_Mesh.hxx"
00039 #include "SMESH_MesherHelper.hxx"
00040 #include "SMESH_subMesh.hxx"
00041 #include "SMESH_subMeshEventListener.hxx"
00042 #include "SMESH_Gen.hxx"
00043 #include "SMESH_Comment.hxx"
00044 
00045 #include <BRepAdaptor_Curve.hxx>
00046 #include <BRep_Tool.hxx>
00047 #include <GCPnts_AbscissaPoint.hxx>
00048 #include <TopExp.hxx>
00049 #include <TopoDS.hxx>
00050 #include <gp_Pnt.hxx>
00051 #include <TopTools_ListIteratorOfListOfShape.hxx>
00052 
00053 #include "utilities.h"
00054 
00055 
00056 using namespace std;
00057 
00058 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
00059 
00060 typedef StdMeshers_ProjectionUtils TAssocTool;
00061 
00062 //=======================================================================
00063 //function : StdMeshers_Projection_1D
00064 //purpose  : 
00065 //=======================================================================
00066 
00067 StdMeshers_Projection_1D::StdMeshers_Projection_1D(int hypId, int studyId, SMESH_Gen* gen)
00068   :SMESH_1D_Algo(hypId, studyId, gen)
00069 {
00070   _name = "Projection_1D";
00071   _shapeType = (1 << TopAbs_EDGE);      // 1 bit per shape type
00072 
00073   _compatibleHypothesis.push_back("ProjectionSource1D");
00074   _sourceHypo = 0;
00075 }
00076 
00077 //================================================================================
00081 //================================================================================
00082 
00083 StdMeshers_Projection_1D::~StdMeshers_Projection_1D()
00084 {}
00085 
00086 //=======================================================================
00087 //function : CheckHypothesis
00088 //purpose  : 
00089 //=======================================================================
00090 
00091 bool StdMeshers_Projection_1D::CheckHypothesis(SMESH_Mesh&                          aMesh,
00092                                                const TopoDS_Shape&                  aShape,
00093                                                SMESH_Hypothesis::Hypothesis_Status& aStatus)
00094 {
00095   _sourceHypo = 0;
00096   list <const SMESHDS_Hypothesis * >::const_iterator itl;
00097 
00098   const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
00099   if ( hyps.size() == 0 )
00100   {
00101     aStatus = HYP_MISSING;
00102     return false;  // can't work with no hypothesis
00103   }
00104 
00105   if ( hyps.size() > 1 )
00106   {
00107     aStatus = HYP_ALREADY_EXIST;
00108     return false;
00109   }
00110 
00111   const SMESHDS_Hypothesis *theHyp = hyps.front();
00112 
00113   string hypName = theHyp->GetName();
00114 
00115   aStatus = HYP_OK;
00116 
00117   if (hypName == "ProjectionSource1D")
00118   {
00119     _sourceHypo = static_cast<const StdMeshers_ProjectionSource1D *>(theHyp);
00120 
00121     // Check hypo parameters
00122 
00123     SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
00124     SMESH_Mesh* tgtMesh = & aMesh;
00125     if ( !srcMesh )
00126       srcMesh = tgtMesh;
00127 
00128     // check vertices
00129     if ( _sourceHypo->HasVertexAssociation() )
00130     {
00131       // source and target vertices
00132       if ( !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh ) ||
00133            !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh ) ||
00134            !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(),
00135                                             _sourceHypo->GetSourceEdge() ))
00136       {
00137         aStatus = HYP_BAD_PARAMETER;
00138         SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh )));
00139         SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh )));
00140         SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(),
00141                                                 _sourceHypo->GetSourceEdge() )));
00142       }
00143       // PAL16202
00144       else
00145       {
00146         bool isSub = SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), aShape );
00147         if ( !_sourceHypo->IsCompoundSource() ) {
00148           if ( !isSub ) {
00149             aStatus = HYP_BAD_PARAMETER;
00150             SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), aShape)));
00151           }
00152         }
00153         else if ( isSub ) {
00154           // is Ok provided that source vertex is shared only by one edge
00155           // of the source group
00156           TopoDS_Shape sharingEdge;
00157           TopTools_ListIteratorOfListOfShape ancestIt
00158             ( aMesh.GetAncestors( _sourceHypo->GetSourceVertex() ));
00159           for ( ; ancestIt.More(); ancestIt.Next() )
00160           {
00161             const TopoDS_Shape& ancestor = ancestIt.Value();
00162             if ( ancestor.ShapeType() == TopAbs_EDGE &&
00163                  SMESH_MesherHelper::IsSubShape( ancestor, _sourceHypo->GetSourceEdge() ))
00164             {
00165               if ( sharingEdge.IsNull() || ancestor.IsSame( sharingEdge ))
00166                 sharingEdge = ancestor;
00167               else {
00168                 // the second encountered
00169                 aStatus = HYP_BAD_PARAMETER;
00170                 MESSAGE("Source vertex is shared by several edges of a group");
00171                 break;
00172               }
00173             }
00174           }
00175         }
00176       }
00177     }
00178     // check source edge
00179     if ( !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh ) ||
00180          ( srcMesh == tgtMesh && aShape == _sourceHypo->GetSourceEdge() ))
00181     {
00182       aStatus = HYP_BAD_PARAMETER;
00183       SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh )));
00184       SCRUTE((srcMesh == tgtMesh));
00185       SCRUTE(( aShape == _sourceHypo->GetSourceEdge() ));
00186     }
00187   }
00188   else
00189   {
00190     aStatus = HYP_INCOMPATIBLE;
00191   }
00192   return ( aStatus == HYP_OK );
00193 }
00194 
00195 //=======================================================================
00196 //function : Compute
00197 //purpose  : 
00198 //=======================================================================
00199 
00200 bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
00201 {
00202   if ( !_sourceHypo )
00203     return false;
00204 
00205   SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); 
00206   SMESH_Mesh * tgtMesh = & theMesh;
00207   if ( !srcMesh )
00208     srcMesh = tgtMesh;
00209 
00210   SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00211 
00212   // ---------------------------
00213   // Make sub-shapes association
00214   // ---------------------------
00215 
00216   TopoDS_Edge srcEdge, tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD));
00217   TopoDS_Shape srcShape = _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD);
00218 
00219   TAssocTool::TShapeShapeMap shape2ShapeMap;
00220   TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
00221   if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcShape, srcMesh,
00222                                              shape2ShapeMap) ||
00223        !shape2ShapeMap.IsBound( tgtEdge ))
00224     return error("Vertices association failed" );
00225 
00226   srcEdge = TopoDS::Edge( shape2ShapeMap( tgtEdge ).Oriented(TopAbs_FORWARD));
00227 //   cout << " srcEdge #" << srcMesh->GetMeshDS()->ShapeToIndex( srcEdge )
00228 //        << " tgtEdge #" << tgtMesh->GetMeshDS()->ShapeToIndex( tgtEdge ) << endl;
00229 
00230   TopoDS_Vertex tgtV[2], srcV[2];
00231   TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] );
00232   TopExp::Vertices( srcEdge, srcV[0], srcV[1] );
00233 
00234   // ----------------------------------------------
00235   // Assure that mesh on a source edge is computed
00236   // ----------------------------------------------
00237 
00238   SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge );
00239   //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtEdge );
00240 
00241   if ( tgtMesh == srcMesh ) {
00242     if ( !TAssocTool::MakeComputed( srcSubMesh ))
00243       return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00244   }
00245   else {
00246     if ( !srcSubMesh->IsMeshComputed() )
00247       return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00248   }
00249   // -----------------------------------------------
00250   // Find out nodes distribution on the source edge
00251   // -----------------------------------------------
00252 
00253   double srcLength = EdgeLength( srcEdge );
00254   double tgtLength = EdgeLength( tgtEdge );
00255   
00256   vector< double > params; // sorted parameters of nodes on the source edge
00257   if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params ))
00258     return error(COMPERR_BAD_INPUT_MESH,"Bad node parameters on the source edge");
00259 
00260   int i, nbNodes = params.size();
00261 
00262   vector< double > lengths( nbNodes - 1 ); // lengths of segments of the source edge
00263   if ( srcLength > 0 )
00264   {
00265     BRepAdaptor_Curve curveAdaptor( srcEdge );
00266     for ( i = 1; i < nbNodes; ++i )
00267       lengths[ i-1 ] = GCPnts_AbscissaPoint::Length( curveAdaptor, params[i-1], params[i]);
00268   }
00269   else // degenerated source edge
00270   {
00271     for ( i = 1; i < nbNodes; ++i )
00272       lengths[ i-1 ] = params[i] - params[i-1];
00273     srcLength = params.back() - params[0];
00274   }
00275 
00276   bool reverse = ( srcV[0].IsSame( shape2ShapeMap( tgtV[1] )));
00277   if ( tgtV[0].IsSame( tgtV[1] )) // case of closed edge
00278     reverse = ( shape2ShapeMap( tgtEdge ).Orientation() == TopAbs_REVERSED );
00279   if ( reverse ) // reverse lengths of segments
00280     std::reverse( lengths.begin(), lengths.end() );
00281 
00282   // ----------
00283   // Make mesh
00284   // ----------
00285 
00286   // vector of target nodes
00287   vector< const SMDS_MeshNode* > nodes ( nbNodes );
00288 
00289   // Get the first and last nodes
00290   nodes.front() = VertexNode( tgtV[0], meshDS );
00291   nodes.back()  = VertexNode( tgtV[1], meshDS );
00292   if ( !nodes.front() || !nodes.back() )
00293     return error(COMPERR_BAD_INPUT_MESH,"No node on vertex");
00294 
00295   // Compute parameters on the target edge and make internal nodes
00296   // --------------------------------------------------------------
00297 
00298   vector< double > tgtParams( nbNodes );
00299 
00300   BRep_Tool::Range( tgtEdge, tgtParams.front(), tgtParams.back() );
00301   if ( tgtLength <= 0 )
00302     tgtLength = tgtParams.back() - tgtParams.front();
00303   double dl = tgtLength / srcLength;
00304 
00305   if ( tgtLength > 0 )
00306   {
00307     BRepAdaptor_Curve curveAdaptor( tgtEdge );
00308 
00309     // compute params on internal nodes
00310     for ( i = 1; i < nbNodes - 1; ++i )
00311     {
00312       // computes a point on a <curveAdaptor> at the given distance
00313       // from the point at given parameter.
00314       GCPnts_AbscissaPoint Discret( curveAdaptor, dl * lengths[ i-1 ], tgtParams[ i-1 ] );
00315       if ( !Discret.IsDone() )
00316         return error("GCPnts_AbscissaPoint failed");
00317       tgtParams[ i ] = Discret.Parameter();
00318     }
00319     // make internal nodes 
00320     for ( i = 1; i < nbNodes - 1; ++i )
00321     {
00322       gp_Pnt P = curveAdaptor.Value( tgtParams[ i ]);
00323       SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00324       meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
00325       nodes[ i ] = node;
00326     }
00327   }
00328   else // degenerated target edge
00329   {
00330     // compute params and make internal nodes
00331     gp_Pnt P = BRep_Tool::Pnt( tgtV[0] );
00332 
00333     for ( i = 1; i < nbNodes - 1; ++i )
00334     {
00335       SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00336       tgtParams[ i ] = tgtParams[ i-1 ] + dl * lengths[ i-1 ];
00337       meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
00338       nodes[ i ] = node;
00339     }
00340   }
00341 
00342   // Quadratic mesh?
00343   // ----------------
00344 
00345   bool quadratic = false;
00346   SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
00347   if ( elemIt->more() )
00348     quadratic = elemIt->next()->IsQuadratic();
00349   else {
00350     SMDS_NodeIteratorPtr nodeIt = srcSubMesh->GetSubMeshDS()->GetNodes();
00351     while ( nodeIt->more() && !quadratic )
00352       quadratic = SMESH_MesherHelper::IsMedium( nodeIt->next() );
00353   }
00354   // enough nodes to make all edges quadratic?
00355   if ( quadratic && ( nbNodes < 3 || ( nbNodes % 2 != 1 )))
00356     return error(COMPERR_BAD_INPUT_MESH,
00357                  SMESH_Comment("Wrong number of nodes to make quadratic mesh: ")<<nbNodes);
00358 
00359   // Create edges
00360   // -------------
00361 
00362   SMDS_MeshElement* edge = 0;
00363   int di = quadratic ? 2 : 1;
00364   for ( i = di; i < nbNodes; i += di)
00365   {
00366     if ( quadratic )
00367       edge = meshDS->AddEdge( nodes[i-2], nodes[i], nodes[i-1] );
00368     else
00369       edge = meshDS->AddEdge( nodes[i-1], nodes[i] );
00370     meshDS->SetMeshElementOnShape(edge, tgtEdge );
00371   }
00372 
00373   return true;
00374 }
00375 
00376 
00377 //=======================================================================
00378 //function : Evaluate
00379 //purpose  : 
00380 //=======================================================================
00381 
00382 bool StdMeshers_Projection_1D::Evaluate(SMESH_Mesh& theMesh,
00383                                         const TopoDS_Shape& theShape,
00384                                         MapShapeNbElems& aResMap)
00385 {
00386   if ( !_sourceHypo )
00387     return false;
00388 
00389   SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); 
00390   SMESH_Mesh * tgtMesh = & theMesh;
00391   if ( !srcMesh )
00392     srcMesh = tgtMesh;
00393 
00394   //SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00395 
00396   // ---------------------------
00397   // Make sub-shapes association
00398   // ---------------------------
00399 
00400   TopoDS_Edge srcEdge, tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD));
00401   TopoDS_Shape srcShape = _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD);
00402 
00403   TAssocTool::TShapeShapeMap shape2ShapeMap;
00404   TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
00405   if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcShape, srcMesh,
00406                                              shape2ShapeMap) ||
00407        !shape2ShapeMap.IsBound( tgtEdge ))
00408     return error("Vertices association failed" );
00409 
00410   srcEdge = TopoDS::Edge( shape2ShapeMap( tgtEdge ).Oriented(TopAbs_FORWARD));
00411 //   cout << " srcEdge #" << srcMesh->GetMeshDS()->ShapeToIndex( srcEdge )
00412 //        << " tgtEdge #" << tgtMesh->GetMeshDS()->ShapeToIndex( tgtEdge ) << endl;
00413 
00414   TopoDS_Vertex tgtV[2], srcV[2];
00415   TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] );
00416   TopExp::Vertices( srcEdge, srcV[0], srcV[1] );
00417 
00418   // ----------------------------------------------
00419   // Assure that mesh on a source edge is computed
00420   // ----------------------------------------------
00421 
00422   SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge );
00423   //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtEdge );
00424 
00425   if ( tgtMesh == srcMesh ) {
00426     if ( !TAssocTool::MakeComputed( srcSubMesh ))
00427       return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00428   }
00429   else {
00430     if ( !srcSubMesh->IsMeshComputed() )
00431       return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00432   }
00433   // -----------------------------------------------
00434   // Find out nodes distribution on the source edge
00435   // -----------------------------------------------
00436 
00437   //double srcLength = EdgeLength( srcEdge );
00438   //double tgtLength = EdgeLength( tgtEdge );
00439   
00440   vector< double > params; // sorted parameters of nodes on the source edge
00441   if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params ))
00442     return error(COMPERR_BAD_INPUT_MESH,"Bad node parameters on the source edge");
00443 
00444   int nbNodes = params.size();
00445 
00446   std::vector<int> aVec(SMDSEntity_Last);
00447   for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
00448 
00449   aVec[SMDSEntity_Node] = nbNodes;
00450 
00451   bool quadratic = false;
00452   SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
00453   if ( elemIt->more() )
00454     quadratic = elemIt->next()->IsQuadratic();
00455   if(quadratic)
00456     aVec[SMDSEntity_Quad_Edge] = (nbNodes-1)/2;
00457   else
00458     aVec[SMDSEntity_Edge] = nbNodes - 1;
00459 
00460   SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
00461   aResMap.insert(std::make_pair(sm,aVec));
00462 
00463   return true;
00464 }
00465 
00466 
00467 //=============================================================================
00477 //=============================================================================
00478 
00479 void StdMeshers_Projection_1D::SetEventListener(SMESH_subMesh* subMesh)
00480 {
00481   TAssocTool::SetEventListener( subMesh,
00482                                 _sourceHypo->GetSourceEdge(),
00483                                 _sourceHypo->GetSourceMesh() );
00484 }