-// 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"
#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"
#include "utilities.h"
#include <BRep_Tool.hxx>
+#include <Bnd_B2d.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
// 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 );
} // 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<const SMDS_MeshNode* , const SMDS_MeshNode*> src2tgtNodes;
+ map<const SMDS_MeshNode* , const SMDS_MeshNode*>::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 :
if ( !_sourceHypo )
return false;
- SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
+ SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
SMESH_Mesh * tgtMesh = & theMesh;
if ( !srcMesh )
srcMesh = tgtMesh;
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<const SMDS_MeshNode*>( 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");
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
// 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;
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() )
{
}
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());
// 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
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<int> aVec(SMDSEntity_Last);
+ for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
+
+ aVec[SMDSEntity_Node] = srcSubMesh->GetSubMeshDS()->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