-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014 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.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#include <Bnd_B2d.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopoDS.hxx>
#include <gp_Ax2.hxx>
#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
-typedef StdMeshers_ProjectionUtils TAssocTool;
+namespace TAssocTool = StdMeshers_ProjectionUtils;
+//typedef StdMeshers_ProjectionUtils TAssocTool;
//=======================================================================
//function : StdMeshers_Projection_2D
/*!
* \brief find new nodes belonging to one free border of mesh on face
* \param sm - submesh on edge or vertex containg nodes to choose from
- * \param face - the face bound the submesh
+ * \param face - the face bound by the submesh
* \param u2nodes - map to fill with nodes
* \param seamNodes - set of found nodes
* \retval bool - is a success
if ( !smV1->IsMeshComputed() || !smV2->IsMeshComputed() )
RETURN_BAD_RESULT("Empty vertex submeshes");
- // Look for a new node on V1
- nIt = smV1->GetSubMeshDS()->GetNodes();
const SMDS_MeshNode* nV1 = 0;
- while ( nIt->more() && !nV1 ) {
- const SMDS_MeshNode* node = nIt->next();
- if ( !isOldNode( node ) ) nV1 = node;
- }
- if ( !nV1 )
- RETURN_BAD_RESULT("No new node found on V1");
-
- // 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(SMDSAbs_Face);
- while ( vElems->more() && !nE ) {
- const SMDS_MeshElement* elem = vElems->next();
- int nbNodes = elem->NbNodes();
- if ( elem->IsQuadratic() )
- nbNodes /= 2;
- int iV1 = elem->GetNodeIndex( nV1 );
- // try next after nV1
- int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
- if ( smDS->Contains( elem->GetNode( iE ) ))
- nE = elem->GetNode( iE );
- if ( !nE ) {
- // try node before nV1
- iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
- if ( smDS->Contains( elem->GetNode( iE )))
+
+ // Look for nV1 - a new node on V1
+ nIt = smV1->GetSubMeshDS()->GetNodes();
+ while ( nIt->more() && !nE ) {
+ const SMDS_MeshNode* node = nIt->next();
+ if ( isOldNode( node ) ) continue;
+ nV1 = node;
+
+ // Find nE - a new node connected to nV1 and belonging to edge submesh;
+ SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
+ SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(SMDSAbs_Face);
+ while ( vElems->more() && !nE ) {
+ const SMDS_MeshElement* elem = vElems->next();
+ int nbNodes = elem->NbNodes();
+ if ( elem->IsQuadratic() )
+ nbNodes /= 2;
+ int iV1 = elem->GetNodeIndex( nV1 );
+ // try next after nV1
+ int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
+ if ( smDS->Contains( elem->GetNode( iE ) ))
nE = elem->GetNode( iE );
- }
- if ( nE && elem->IsQuadratic() ) { // find medium node between nV1 and nE
- if ( Abs( iV1 - iE ) == 1 )
- nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
- else
- nE = elem->GetNode( elem->NbNodes() - 1 );
+ if ( !nE ) {
+ // try node before nV1
+ iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
+ if ( smDS->Contains( elem->GetNode( iE )))
+ nE = elem->GetNode( iE );
+ }
+ if ( nE && elem->IsQuadratic() ) { // find medium node between nV1 and nE
+ if ( Abs( iV1 - iE ) == 1 )
+ nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
+ else
+ nE = elem->GetNode( elem->NbNodes() - 1 );
+ }
}
}
+ if ( !nV1 )
+ RETURN_BAD_RESULT("No new node found on V1");
if ( !nE )
RETURN_BAD_RESULT("new node on edge not found");
SMESH_Mesh * srcMesh,
const TAssocTool::TShapeShapeMap& shape2ShapeMap)
{
- MESSAGE("projectPartner");
- const double tol = 1.e-7*srcMesh->GetMeshDS()->getMaxDim();
+ SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
+ SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
+
+ const double tol = 1.e-7 * srcMeshDS->getMaxDim();
gp_Trsf trsf; // transformation to get location of target nodes from source ones
if ( tgtFace.IsPartner( srcFace ))
// make any local coord systems of src and tgt faces
vector<gp_Pnt> srcPP, tgtPP; // 3 points on face boundaries to make axes of CS
- SMESH_subMesh * srcSM = srcMesh->GetSubMesh( srcFace );
+ int tgtNbVert = SMESH_MesherHelper::Count( tgtFace, TopAbs_VERTEX, /*ignoreSame=*/true );
+ int srcNbVert = SMESH_MesherHelper::Count( srcFace, TopAbs_VERTEX, /*ignoreSame=*/true );
+ SMESH_subMesh * srcSM = srcMesh->GetSubMesh( srcFace );
SMESH_subMeshIteratorPtr smIt = srcSM->getDependsOnIterator(/*includeSelf=*/false,false);
srcSM = smIt->next(); // sm of a vertex
while ( smIt->more() && srcPP.size() < 3 )
if ( tgtShape.ShapeType() == TopAbs_VERTEX )
{
tgtP = BRep_Tool::Pnt( TopoDS::Vertex( tgtShape ));
- pOK = true;
- //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMesh->GetMeshDS())->GetID() << endl;
+ if ( srcNbVert == tgtNbVert || tgtPP.empty() )
+ pOK = true;
+ else
+ pOK = (( tgtP.Distance( tgtPP[0] ) > tol*tol ) &&
+ ( tgtPP.size() == 1 || tgtP.Distance( tgtPP[1] ) > tol*tol ));
+ //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMeshDS)->GetID() << endl;
}
else if ( tgtPP.size() > 0 )
{
- if ( SMESHDS_SubMesh* tgtSmds = tgtMesh->GetMeshDS()->MeshElements( tgtShape ))
+ if ( SMESHDS_SubMesh* tgtSmds = tgtMeshDS->MeshElements( tgtShape ))
{
double srcDist = srcPP[0].Distance( p );
double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape ));
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() )
+ bool tgtEdgesMeshed = false;
+ for ( TopExp_Explorer srcExp( srcFace, TopAbs_EDGE); srcExp.More(); srcExp.Next() )
{
- const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current(), /*isSrc=*/true );
+ const TopoDS_Shape& srcEdge = srcExp.Current();
+ const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge, /*isSrc=*/true );
+ tgtEdgesMeshed != tgtMesh->GetSubMesh( tgtEdge )->IsEmpty();
+
+ if ( srcMesh->GetSubMesh( srcEdge )->IsEmpty() ||
+ tgtMesh->GetSubMesh( tgtEdge )->IsEmpty() )
+ continue;
map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
- if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(),
- TopoDS::Edge( srcEdge.Current() ),
- /*ignoreMediumNodes = */true,
- srcNodes )
+ if (( ! SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS,
+ TopoDS::Edge( srcEdge ),
+ /*ignoreMediumNodes = */true,
+ srcNodes ))
||
- !SMESH_Algo::GetSortedNodesOnEdge( tgtMesh->GetMeshDS(),
- TopoDS::Edge( tgtEdge ),
- /*ignoreMediumNodes = */true,
- tgtNodes )
+ ( ! SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS,
+ TopoDS::Edge( tgtEdge ),
+ /*ignoreMediumNodes = */true,
+ tgtNodes ))
||
- srcNodes.size() != tgtNodes.size())
+ (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 )
+ )
return false;
- if ( !tgtEdge.IsPartner( srcEdge.Current() ))
+ if ( !tgtEdge.IsPartner( srcEdge ))
{
+ if ( tgtNodes.empty() )
+ return false;
// check that transformation is OK by three nodes
gp_Pnt p0S = SMESH_TNodeXYZ( (srcNodes.begin()) ->second);
gp_Pnt p1S = SMESH_TNodeXYZ( (srcNodes.rbegin()) ->second);
return false;
}
}
+ if ( !tgtNodes.empty() )
+ {
+ 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 ));
+ }
+ }
+ // check nodes on VERTEXes for a case of not meshes EDGEs
+ for ( TopExp_Explorer srcExp( srcFace, TopAbs_VERTEX); srcExp.More(); srcExp.Next() )
+ {
+ const TopoDS_Shape& srcV = srcExp.Current();
+ const TopoDS_Shape& tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
+ const SMDS_MeshNode* srcN = SMESH_Algo::VertexNode( TopoDS::Vertex( srcV ), srcMeshDS );
+ const SMDS_MeshNode* tgtN = SMESH_Algo::VertexNode( TopoDS::Vertex( tgtV ), srcMeshDS );
+ if ( !srcN )
+ continue;
+ if ( !tgtN || tgtV.ShapeType() != TopAbs_VERTEX )
+ 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 ));
+ if ( !tgtV.IsPartner( srcV ))
+ {
+ // check that transformation is OK by three nodes
+ gp_Pnt p0S = SMESH_TNodeXYZ( srcN );
+ gp_Pnt p0T = SMESH_TNodeXYZ( tgtN );
+ if ( p0T.SquareDistance( p0S.Transformed( trsf )) > tol )
+ {
+ return false;
+ }
+ }
+ src2tgtNodes.insert( make_pair( srcN, tgtN ));
}
+
// Make new faces
// prepare the helper to adding quadratic elements if necessary
SMESH_MesherHelper helper( *tgtMesh );
helper.SetSubShape( tgtFace );
helper.IsQuadraticSubMesh( tgtFace );
- helper.SetElementsOnShape( true );
+
+ SMESHDS_SubMesh* srcSubDS = srcMeshDS->MeshElements( srcFace );
+ if ( !tgtEdgesMeshed && srcSubDS->NbElements() )
+ helper.SetIsQuadratic( srcSubDS->GetElements()->next()->IsQuadratic() );
SMESH_MesherHelper srcHelper( *srcMesh );
srcHelper.SetSubShape( srcFace );
const SMDS_MeshNode* nullNode = 0;
// indices of nodes to create properly oriented faces
+ bool isReverse = ( trsf.Form() != gp_Identity );
int tri1 = 1, tri2 = 2, quad1 = 1, quad3 = 3;
- if ( trsf.Form() != gp_Identity )
+ if ( isReverse )
std::swap( tri1, tri2 ), std::swap( quad1, quad3 );
- SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace );
SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements();
vector< const SMDS_MeshNode* > tgtNodes;
while ( elemIt->more() ) // loop on all mesh faces on srcFace
const SMDS_MeshElement* elem = elemIt->next();
const int nbN = elem->NbCornerNodes();
tgtNodes.resize( nbN );
+ helper.SetElementsOnShape( false );
for ( int i = 0; i < nbN; ++i ) // loop on nodes of the source element
{
const SMDS_MeshNode* srcNode = elem->GetNode(i);
if ( srcN_tgtN->second == nullNode )
{
// create a new node
- gp_Pnt tgtP = gp_Pnt(srcNode->X(),srcNode->Y(),srcNode->Z()).Transformed( trsf );
+ gp_Pnt tgtP = gp_Pnt( SMESH_TNodeXYZ( srcNode )).Transformed( trsf );
SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
srcN_tgtN->second = n;
-
- gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode,
- elem->GetNode( helper.WrapIndex(i+1,nbN)));
- n->SetPosition( new SMDS_FacePosition( srcUV.X(), srcUV.Y() ));
+ switch ( srcNode->GetPosition()->GetTypeOfPosition() )
+ {
+ case SMDS_TOP_FACE:
+ {
+ gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode );
+ tgtMeshDS->SetNodeOnFace( n, helper.GetSubShapeID(), srcUV.X(), srcUV.Y() );
+ break;
+ }
+ case SMDS_TOP_EDGE:
+ {
+ const TopoDS_Shape & srcE = srcMeshDS->IndexToShape( srcNode->getshapeId() );
+ const TopoDS_Shape & tgtE = shape2ShapeMap( srcE, /*isSrc=*/true );
+ double srcU = srcHelper.GetNodeU( TopoDS::Edge( srcE ), srcNode );
+ tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtE ), srcU );
+ break;
+ }
+ case SMDS_TOP_VERTEX:
+ {
+ const TopoDS_Shape & srcV = srcMeshDS->IndexToShape( srcNode->getshapeId() );
+ const TopoDS_Shape & tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
+ tgtMeshDS->SetNodeOnVertex( n, TopoDS::Vertex( tgtV ));
+ break;
+ }
+ default:;
+ }
}
tgtNodes[i] = srcN_tgtN->second;
}
// create a new face
+ helper.SetElementsOnShape( true );
switch ( nbN )
{
case 3: helper.AddFace(tgtNodes[0], tgtNodes[tri1], tgtNodes[tri2]); break;
case 4: helper.AddFace(tgtNodes[0], tgtNodes[quad1], tgtNodes[2], tgtNodes[quad3]); break;
+ default:
+ if ( isReverse ) std::reverse( tgtNodes.begin(), tgtNodes.end() );
+ helper.AddPolygonalFace( tgtNodes );
}
}
+
+ // check node positions
+
+ if ( !tgtFace.IsPartner( srcFace ) )
+ {
+ int nbOkPos = 0;
+ const double tol2d = 1e-12;
+ srcN_tgtN = src2tgtNodes.begin();
+ for ( ; srcN_tgtN != src2tgtNodes.end(); ++srcN_tgtN )
+ {
+ const SMDS_MeshNode* n = srcN_tgtN->second;
+ switch ( n->GetPosition()->GetTypeOfPosition() )
+ {
+ case SMDS_TOP_FACE:
+ {
+ gp_XY uv = helper.GetNodeUV( tgtFace, n ), uvBis = uv;
+ if (( helper.CheckNodeUV( tgtFace, n, uv, tol )) &&
+ (( uv - uvBis ).SquareModulus() < tol2d ) &&
+ ( ++nbOkPos > 10 ))
+ return true;
+ else
+ nbOkPos = 0;
+ break;
+ }
+ case SMDS_TOP_EDGE:
+ {
+ const TopoDS_Edge & tgtE = TopoDS::Edge( tgtMeshDS->IndexToShape( n->getshapeId() ));
+ double u = helper.GetNodeU( tgtE, n ), uBis = u;
+ if (( !helper.CheckNodeU( tgtE, n, u, tol )) ||
+ (( u - uBis ) < tol2d ))
+ nbOkPos = 0;
+ break;
+ }
+ default:;
+ }
+ }
+ }
+
return true;
} // bool projectPartner()
+ //================================================================================
+ /*!
+ * \brief Check if two consecutive EDGEs are connected in 2D
+ * \param [in] E1 - a well oriented non-seam EDGE
+ * \param [in] E2 - a possibly well oriented seam EDGE
+ * \param [in] F - a FACE
+ * \return bool - result
+ */
+ //================================================================================
+
+ bool are2dConnected( const TopoDS_Edge & E1,
+ const TopoDS_Edge & E2,
+ const TopoDS_Face & F )
+ {
+ double f,l;
+ Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( E1, F, f, l );
+ gp_Pnt2d uvLast1 = c1->Value( E1.Orientation() == TopAbs_REVERSED ? f : l );
+
+ Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( E2, F, f, l );
+ gp_Pnt2d uvFirst2 = c2->Value( f );
+ gp_Pnt2d uvLast2 = c2->Value( l );
+ double tol2 = 1e-5 * uvLast2.SquareDistance( uvFirst2 );
+
+ return (( uvLast1.SquareDistance( uvFirst2 ) < tol2 ) ||
+ ( uvLast1.SquareDistance( uvLast2 ) < tol2 ));
+ }
+
//================================================================================
/*!
* \brief Preform projection in case if the faces are similar in 2D space
// make corresponding sequence of tgt EDGEs
TSideVector tgtWires( srcWires.size() );
- for ( unsigned iW = 0; iW < srcWires.size(); ++iW )
+ for ( size_t iW = 0; iW < srcWires.size(); ++iW )
{
list< TopoDS_Edge > tgtEdges;
StdMeshers_FaceSidePtr srcWire = srcWires[iW];
TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
{
- tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true)));
+ TopoDS_Edge E = TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true));
// reverse a seam edge encountered for the second time
- const int oldExtent = edgeMap.Extent();
- edgeMap.Add( tgtEdges.back() );
- if ( oldExtent == edgeMap.Extent() )
- tgtEdges.back().Reverse();
+ const int index = edgeMap.Add( E );
+ if ( index < edgeMap.Extent() ) // E is a seam
+ {
+ // check which of edges to reverse, E or one already being in tgtEdges
+ if ( are2dConnected( tgtEdges.back(), E, tgtFace ))
+ {
+ list< TopoDS_Edge >::iterator eIt = tgtEdges.begin();
+ std::advance( eIt, index-1 );
+ eIt->Reverse();
+ }
+ else
+ {
+ E.Reverse();
+ }
+ }
+ tgtEdges.push_back( E );
}
tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
/*theIsForward = */ true,
// Make sub-shapes association
// ---------------------------
- TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
+ TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
TAssocTool::TShapeShapeMap shape2ShapeMap;
{
if ( srcShape.ShapeType() == TopAbs_FACE )
{
- int nbE1 = TAssocTool::Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true );
- int nbE2 = TAssocTool::Count( srcShape, TopAbs_EDGE, /*ignoreSame=*/true );
+ int nbE1 = SMESH_MesherHelper::Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true );
+ int nbE2 = SMESH_MesherHelper::Count( srcShape, TopAbs_EDGE, /*ignoreSame=*/true );
if ( nbE1 != nbE2 )
return error(COMPERR_BAD_SHAPE,
SMESH_Comment("Different number of edges in source and target faces: ")
SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace );
SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace );
+ string srcMeshError;
if ( tgtMesh == srcMesh ) {
- if ( !TAssocTool::MakeComputed( srcSubMesh ) || !srcSubMesh->IsMeshComputed() )
- return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
+ if ( !TAssocTool::MakeComputed( srcSubMesh ))
+ srcMeshError = TAssocTool::SourceNotComputedError( srcSubMesh, this );
}
else {
if ( !srcSubMesh->IsMeshComputed() )
- return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
+ srcMeshError = TAssocTool::SourceNotComputedError();
}
+ if ( !srcMeshError.empty() )
+ return error(COMPERR_BAD_INPUT_MESH, srcMeshError );
// ===========
// Projection
done = projectBy2DSimilarity( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap, is1DComputed);
}
+ SMESH_MesherHelper helper( theMesh );
+ helper.SetSubShape( tgtFace );
+
if ( !done )
{
// --------------------
// 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();
const bool toProjectNodes =
( nbFaceNodes > 0 && ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN ));
- // Load pattern from the source face
- SMESH_Pattern mapper;
- 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");
-
- // Find the first target vertex corresponding to first vertex of the <mapper>
+ // Find the corresponding source and target vertex
// and <theReverse> flag needed to call mapper.Apply()
- TopoDS_Vertex srcV1 = TopoDS::Vertex( mapper.GetSubShape( 1 ));
- if ( srcV1.IsNull() )
- RETURN_BAD_RESULT("Mesh is not bound to the face");
- if ( !shape2ShapeMap.IsBound( srcV1, /*isSrc=*/true ))
- RETURN_BAD_RESULT("Not associated vertices, srcV1 " << srcV1.TShape().operator->() );
- TopoDS_Vertex tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1, /*isSrc=*/true ));
-
- if ( !SMESH_MesherHelper::IsSubShape( srcV1, srcFace ))
- RETURN_BAD_RESULT("Wrong srcV1 " << srcV1.TShape().operator->());
- if ( !SMESH_MesherHelper::IsSubShape( tgtV1, tgtFace ))
- RETURN_BAD_RESULT("Wrong tgtV1 " << tgtV1.TShape().operator->());
-
- // try to find out orientation by order of edges
+ TopoDS_Vertex srcV1, tgtV1;
bool reverse = false;
+
+ if ( _sourceHypo->HasVertexAssociation() ) {
+ srcV1 = _sourceHypo->GetSourceVertex(1);
+ tgtV1 = _sourceHypo->GetTargetVertex(1);
+ } else {
+ srcV1 = TopoDS::Vertex( TopExp_Explorer( srcFace, TopAbs_VERTEX ).Current() );
+ tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1, /*isSrc=*/true ));
+ }
list< TopoDS_Edge > tgtEdges, srcEdges;
list< int > nbEdgesInWires;
- SMESH_Block::GetOrderedEdges( tgtFace, tgtV1, tgtEdges, nbEdgesInWires);
- SMESH_Block::GetOrderedEdges( srcFace, srcV1, srcEdges, nbEdgesInWires);
- if ( nbEdgesInWires.front() > 1 ) // possible to find out
+ SMESH_Block::GetOrderedEdges( tgtFace, tgtEdges, nbEdgesInWires, tgtV1 );
+ SMESH_Block::GetOrderedEdges( srcFace, srcEdges, nbEdgesInWires, srcV1 );
+
+ if ( nbEdgesInWires.front() > 1 ) // possible to find out orientation
{
TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 );
reverse = ( ! srcE1.IsSame( srcE1bis ));
+ if ( reverse &&
+ _sourceHypo->HasVertexAssociation() &&
+ nbEdgesInWires.front() > 2 &&
+ helper.IsRealSeam( tgtEdges.front() ))
+ {
+ // projection to a face with seam EDGE; pb is that GetOrderedEdges()
+ // always puts a seam EDGE first (if possible) and as a result
+ // we can't use only theReverse flag to correctly associate source
+ // and target faces in the mapper. Thus we select srcV1 so that
+ // GetOrderedEdges() to return EDGEs in a needed order
+ list< TopoDS_Edge >::iterator edge = srcEdges.begin();
+ for ( ; edge != srcEdges.end(); ++edge ) {
+ if ( srcE1bis.IsSame( *edge )) {
+ srcV1 = helper.IthVertex( 0, *edge );
+ break;
+ }
+ }
+ }
}
else if ( nbEdgesInWires.front() == 1 )
{
RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()");
}
+ // Load pattern from the source face
+ SMESH_Pattern mapper;
+ mapper.Load( srcMesh, srcFace, toProjectNodes, srcV1 );
+ if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+ return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
+
// --------------------
// Perform 2D mapping
// --------------------
// Make groups of nodes to merge
- // loop on edge and vertex submeshes of a target face
+ // loop on EDGE and VERTEX sub-meshes of a target FACE
smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,/*complexShapeFirst=*/false);
while ( smIt->more() )
{
//if ( !is1DComputed && sm->GetSubShape().ShapeType() == TopAbs_EDGE )
//break;
+ if ( helper.IsDegenShape( sm->GetId() ) ) // to merge all nodes on degenerated
+ {
+ if ( sm->GetSubShape().ShapeType() == TopAbs_EDGE )
+ {
+ groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
+ SMESH_subMeshIteratorPtr smDegenIt
+ = sm->getDependsOnIterator(/*includeSelf=*/true,/*complexShapeFirst=*/false);
+ while ( smDegenIt->more() )
+ if (( smDS = smDegenIt->next()->GetSubMeshDS() ))
+ {
+ SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+ while ( nIt->more() )
+ groupsOfNodes.back().push_back( nIt->next() );
+ }
+ }
+ continue; // do not treat sm of degen VERTEX
+ }
+
// Sort new and old nodes of a submesh separately
bool isSeam = helper.IsRealSeam( sm->GetId() );
map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
set< const SMDS_MeshNode* > seamNodes;
- // mapper puts on a seam edge nodes from 2 edges
+ // mapper changed, no more "mapper puts on a seam edge nodes from 2 edges"
if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
- RETURN_BAD_RESULT("getBoundaryNodes() failed");
+ ;//RETURN_BAD_RESULT("getBoundaryNodes() failed");
SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
while ( nIt->more() )
u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
newEnd = u2nodesMaps[ OLD_NODES ].end();
for ( ; u_oldNode != newEnd; ++u_oldNode )
- _badInputElements.push_back( u_oldNode->second );
+ SMESH_Algo::addBadInputElement( u_oldNode->second );
return error( COMPERR_BAD_INPUT_MESH,
SMESH_Comment( "Existing mesh mismatches the projected 2D mesh on " )
<< ( sm->GetSubShape().ShapeType() == TopAbs_EDGE ? "edge" : "vertex" )
<< " #" << sm->GetId() );
}
if ( isSeam && !mergeSeamToNew ) {
- //RETURN_BAD_RESULT
- MESSAGE("Different nb of old and seam nodes " <<
- u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size());
+ const TopoDS_Shape& seam = sm->GetSubShape();
+ if ( u2nodesMaps[ NEW_NODES ].size() > 0 &&
+ u2nodesOnSeam.size() > 0 &&
+ seam.ShapeType() == TopAbs_EDGE )
+ {
+ int nbE1 = SMESH_MesherHelper::Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true );
+ int nbE2 = SMESH_MesherHelper::Count( srcFace, TopAbs_EDGE, /*ignoreSame=*/true );
+ if ( nbE1 != nbE2 ) // 2 EDGEs are mapped to a seam EDGE
+ {
+ // find the 2 EDGEs of srcFace
+ TopTools_DataMapIteratorOfDataMapOfShapeShape src2tgtIt( shape2ShapeMap._map2to1 );
+ for ( ; src2tgtIt.More(); src2tgtIt.Next() )
+ if ( seam.IsSame( src2tgtIt.Value() ))
+ SMESH_Algo::addBadInputElements
+ ( srcMesh->GetMeshDS()->MeshElements( src2tgtIt.Key() ));
+ return error( COMPERR_BAD_INPUT_MESH,
+ "Different number of nodes on two edges projected to a seam edge" );
+ }
+ }
}
+
// Make groups of nodes to merge
+
u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
u_newNode = u2nodesMaps[ NEW_NODES ].begin();
newEnd = u2nodesMaps[ NEW_NODES ].end();
groupsOfNodes.back().push_back( u_newNode->second );
groupsOfNodes.back().push_back( u_newOnSeam->second );
}
- }
+
+ } // loop on EDGE and VERTEX submeshes of a target FACE
// Merge
int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
editor.MergeNodes( groupsOfNodes );
int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
- if ( nbFaceBeforeMerge != nbFaceAtferMerge )
+ if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() )
return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
// ----------------------------------------------------------------
while ( faceIt->more() )
tgtFaces.insert( tgtFaces.end(), faceIt->next() );
- editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces);
+ editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false);
}
cleaner.Release(); // not to remove mesh
}
}
// Fix orientation
- if ( SMESH_Algo::IsReversedSubMesh( face, meshDS ))
+ if ( helper.IsReversedSubMesh( face ))
{
SMESH_MeshEditor editor( tgtMesh );
SMDS_ElemIteratorPtr eIt = meshDS->MeshElements( face )->GetElements();