X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Projection_2D.cxx;h=a433e2dc3ab469e2a8977c265b4650c0b9573fd5;hb=3e09f90deb9769d11685f5d5948f14a1fb8a37e0;hp=0ac6f9ea4b0c40d36d71af643c80b37e093a75cc;hpb=79b1ac2b6df9117f16f11d444b1f165d477a1813;p=modules%2Fsmesh.git diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index 0ac6f9ea4..a433e2dc3 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -1,32 +1,30 @@ -// SMESH SMESH : implementaion of SMESH idl descriptions +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. // -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// SMESH SMESH : implementaion of SMESH idl descriptions // File : StdMeshers_Projection_2D.cxx // Module : SMESH // Created : Fri Oct 20 11:37:07 2006 // Author : Edward AGAPOV (eap) - - +// #include "StdMeshers_Projection_2D.hxx" #include "StdMeshers_ProjectionSource2D.hxx" @@ -37,7 +35,7 @@ #include "SMESH_Block.hxx" #include "SMESH_Gen.hxx" #include "SMESH_Mesh.hxx" -#include "SMESH_MeshEditor.hxx" +#include "SMESH_MesherHelper.hxx" #include "SMESH_Pattern.hxx" #include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" @@ -47,6 +45,7 @@ #include "utilities.h" #include +#include #include #include #include @@ -294,16 +293,14 @@ namespace { // Find a new node connected to nV1 and belonging to edge submesh; const SMDS_MeshNode* nE = 0; SMESHDS_SubMesh* smDS = sm->GetSubMeshDS(); - SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(); + SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(SMDSAbs_Face); while ( vElems->more() && !nE ) { const SMDS_MeshElement* elem = vElems->next(); - if ( elem->GetType() != SMDSAbs_Face ) - continue; // new nodes are shared by faces int nbNodes = elem->NbNodes(); if ( elem->IsQuadratic() ) nbNodes /= 2; int iV1 = elem->GetNodeIndex( nV1 ); - // try next aftre nV1 + // try next after nV1 int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes ); if ( smDS->Contains( elem->GetNode( iE ) )) nE = elem->GetNode( iE ); @@ -357,8 +354,103 @@ namespace { } // bool getBoundaryNodes() + //================================================================================ + /*! + * \brief Preform projection in case if tgtFace.IsPartner( srcFace ) + * \param tgtFace - target face + * \param srcFace - source face + * \param tgtMesh - target mesh + * \param srcMesh - source mesh + * \retval bool - true if succeeded + */ + //================================================================================ + + bool projectPartner(const TopoDS_Face& tgtFace, + const TopoDS_Face& srcFace, + SMESH_Mesh * tgtMesh, + SMESH_Mesh * srcMesh, + const TAssocTool::TShapeShapeMap& shape2ShapeMap) + { + if ( !tgtFace.IsPartner( srcFace )) + return false; + + // Fill map of src to tgt nodes with nodes on edges + + map src2tgtNodes; + map::iterator srcN_tgtN; + + for ( TopExp_Explorer srcEdge( srcFace, TopAbs_EDGE); srcEdge.More(); srcEdge.Next() ) + { + const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current() ); + if ( !tgtEdge.IsPartner( srcEdge.Current() )) + return false; + + map< double, const SMDS_MeshNode* > srcNodes, tgtNodes; + if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(), + TopoDS::Edge( srcEdge.Current() ), + /*ignoreMediumNodes = */true, + srcNodes ) + || + !SMESH_Algo::GetSortedNodesOnEdge( tgtMesh->GetMeshDS(), + TopoDS::Edge( tgtEdge ), + /*ignoreMediumNodes = */true, + tgtNodes ) + || + srcNodes.size() != tgtNodes.size()) + return false; + + map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin(); + map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin(); + for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn) + src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second )); + } + + // Make new faces + + // transformation to get location of target nodes from source ones + gp_Trsf srcTrsf = srcFace.Location(); + gp_Trsf tgtTrsf = tgtFace.Location(); + gp_Trsf trsf = srcTrsf.Inverted() * tgtTrsf; + + // prepare the helper adding quadratic elements if necessary + SMESH_MesherHelper helper( *tgtMesh ); + helper.IsQuadraticSubMesh( tgtFace ); + helper.SetElementsOnShape( true ); + + const SMDS_MeshNode* nullNode = 0; + + SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace ); + SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements(); + while ( elemIt->more() ) // loop on all mesh faces on srcFace + { + const SMDS_MeshElement* elem = elemIt->next(); + vector< const SMDS_MeshNode* > tgtFaceNodes; + tgtFaceNodes.reserve( elem->NbNodes() ); + SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); + while ( nodeIt->more() ) // loop on nodes of the source element + { + const SMDS_MeshNode* srcNode = (const SMDS_MeshNode*) nodeIt->next(); + srcN_tgtN = src2tgtNodes.insert( make_pair( srcNode, nullNode )).first; + if ( srcN_tgtN->second == nullNode ) + { + // create a new node + gp_Pnt tgtP = gp_Pnt(srcNode->X(),srcNode->Y(),srcNode->Z()).Transformed( trsf ); + srcN_tgtN->second = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() ); + } + tgtFaceNodes.push_back( srcN_tgtN->second ); + } + // create a new face (with reversed orientation) + if ( tgtFaceNodes.size() == 3 ) + helper.AddFace( tgtFaceNodes[0],tgtFaceNodes[2],tgtFaceNodes[1]); + else + helper.AddFace( tgtFaceNodes[0],tgtFaceNodes[3],tgtFaceNodes[2],tgtFaceNodes[1]); + } + return true; + } + } // namespace + //======================================================================= //function : Compute //purpose : @@ -369,7 +461,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& if ( !_sourceHypo ) return false; - SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); + SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); SMESH_Mesh * tgtMesh = & theMesh; if ( !srcMesh ) srcMesh = tgtMesh; @@ -408,13 +500,38 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); } + // try to project from same face with different location + if ( projectPartner( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap )) + return true; + // -------------------- // Prepare to mapping // -------------------- + SMESH_MesherHelper helper( theMesh ); + helper.SetSubShape( tgtFace ); + + // Check if node projection to a face is needed + Bnd_B2d uvBox; + SMDS_ElemIteratorPtr faceIt = srcSubMesh->GetSubMeshDS()->GetElements(); + int nbFaceNodes = 0; + for ( ; nbFaceNodes < 3 && faceIt->more(); ) { + const SMDS_MeshElement* face = faceIt->next(); + SMDS_ElemIteratorPtr nodeIt = face->nodesIterator(); + while ( nodeIt->more() ) { + const SMDS_MeshNode* node = static_cast( nodeIt->next() ); + if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) { + nbFaceNodes++; + uvBox.Add( helper.GetNodeUV( srcFace, node )); + } + } + } + const bool toProjectNodes = + ( nbFaceNodes > 0 && ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN )); + // Load pattern from the source face SMESH_Pattern mapper; - mapper.Load( srcMesh, srcFace ); + mapper.Load( srcMesh, srcFace, toProjectNodes ); if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face"); @@ -484,9 +601,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& SMESH_MeshEditor editor( tgtMesh ); SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes; - SMESH_MesherHelper helper( theMesh ); - helper.SetSubShape( tgtFace ); - // Make groups of nodes to merge // loop on edge and vertex submeshes of a target face @@ -498,7 +612,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // Sort new and old nodes of a submesh separately - bool isSeam = helper.IsSeamShape( sm->GetId() ); + bool isSeam = helper.IsRealSeam( sm->GetId() ); enum { NEW_NODES = 0, OLD_NODES }; map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam; @@ -520,7 +634,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& continue; // node is already in the map } - // sort nodes on edges by its position + // sort nodes on edges by their position map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES]; switch ( node->GetPosition()->GetTypeOfPosition() ) { @@ -541,12 +655,13 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& } if ( u2nodesMaps[ NEW_NODES ].size() != u2nodesMaps[ OLD_NODES ].size() ) { - if ( u2nodesMaps[ NEW_NODES ].size() == 0 && - sm->GetSubShape().ShapeType() == TopAbs_EDGE && - BRep_Tool::Degenerated( TopoDS::Edge( sm->GetSubShape() ))) + if ( u2nodesMaps[ NEW_NODES ].size() == 0 && + sm->GetSubShape().ShapeType() == TopAbs_EDGE && + helper.IsDegenShape( sm->GetId() ) ) // NPAL15894 (tt88bis.py) - project mesh built by NETGEN_1d_2D that - // does not make segments/nodes on degenerated edges + // does not make segments/nodes on degenerated edges continue; + RETURN_BAD_RESULT("Different nb of old and new nodes on shape #"<< sm->GetId() <<" "<< u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesMaps[ NEW_NODES ].size()); @@ -571,7 +686,11 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // Merge + int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements(); editor.MergeNodes( groupsOfNodes ); + int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements(); + if ( nbFaceBeforeMerge != nbFaceAtferMerge ) + return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces"); // --------------------------- // Check elements orientation @@ -622,6 +741,83 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& return true; } + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_Projection_2D::Evaluate(SMESH_Mesh& theMesh, + const TopoDS_Shape& theShape, + MapShapeNbElems& aResMap) +{ + if ( !_sourceHypo ) + return false; + + SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); + SMESH_Mesh * tgtMesh = & theMesh; + if ( !srcMesh ) + srcMesh = tgtMesh; + + // --------------------------- + // Make subshapes association + // --------------------------- + + TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD)); + TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD); + + TAssocTool::TShapeShapeMap shape2ShapeMap; + TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace ); + if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh, + shape2ShapeMap) || + !shape2ShapeMap.IsBound( tgtFace )) + return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" ); + + TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD)); + + // ---------------------------------------------- + // Assure that mesh on a source Face is computed + // ---------------------------------------------- + + SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace ); + + if ( !srcSubMesh->IsMeshComputed() ) + return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); + + + std::vector aVec(SMDSEntity_Last); + for(int i=SMDSEntity_Node; iGetSubMeshDS()->NbNodes(); + + //bool quadratic = false; + SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements(); + while ( elemIt->more() ) { + const SMDS_MeshElement* E = elemIt->next(); + if( E->NbNodes()==3 ) { + aVec[SMDSEntity_Triangle]++; + } + else if( E->NbNodes()==4 ) { + aVec[SMDSEntity_Quadrangle]++; + } + else if( E->NbNodes()==6 && E->IsQuadratic() ) { + aVec[SMDSEntity_Quad_Triangle]++; + } + else if( E->NbNodes()==8 && E->IsQuadratic() ) { + aVec[SMDSEntity_Quad_Quadrangle]++; + } + else { + aVec[SMDSEntity_Polygon]++; + } + } + + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //============================================================================= /*! * \brief Sets a default event listener to submesh of the source face