+ //================================================================================
+ /*!
+ * \brief Preform projection in case if tgtFace.IsPartner( srcFace ) and in case
+ * if projection by transformation is possible
+ * \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)
+ {
+ const double tol = 1e-6;
+
+ gp_Trsf trsf; // transformation to get location of target nodes from source ones
+ if ( tgtFace.IsPartner( srcFace ))
+ {
+ gp_Trsf srcTrsf = srcFace.Location();
+ gp_Trsf tgtTrsf = tgtFace.Location();
+ trsf = srcTrsf.Inverted() * tgtTrsf;
+ }
+ else
+ {
+ // Try to find the transformation
+
+ // 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 );
+ SMESH_subMeshIteratorPtr smIt = srcSM->getDependsOnIterator(/*includeSelf=*/false,false);
+ srcSM = smIt->next(); // sm of a vertex
+ while ( smIt->more() && srcPP.size() < 3 )
+ {
+ srcSM = smIt->next();
+ SMESHDS_SubMesh* srcSmds = srcSM->GetSubMeshDS();
+ if ( !srcSmds ) continue;
+ SMDS_NodeIteratorPtr nIt = srcSmds->GetNodes();
+ while ( nIt->more() )
+ {
+ SMESH_MeshEditor::TNodeXYZ p ( nIt->next());
+ bool pOK = false;
+ switch ( srcPP.size() )
+ {
+ case 0: pOK = true; break;
+
+ case 1: pOK = ( srcPP[0].SquareDistance( p ) > tol ); break;
+
+ case 2:
+ {
+ gp_Vec p0p1( srcPP[0], srcPP[1] ), p0p( srcPP[0], p );
+ pOK = !p0p1.IsParallel( p0p, tol );
+ break;
+ }
+ }
+ if ( !pOK )
+ continue;
+
+ // find corresponding point on target shape
+ pOK = false;
+ gp_Pnt tgtP;
+ const TopoDS_Shape& tgtShape = shape2ShapeMap( srcSM->GetSubShape() );
+ 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;
+ }
+ else if ( tgtPP.size() > 0 )
+ {
+ if ( SMESHDS_SubMesh* tgtSmds = tgtMesh->GetMeshDS()->MeshElements( tgtShape ))
+ {
+ double srcDist = srcPP[0].Distance( p );
+ double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape ));
+ SMDS_NodeIteratorPtr nItT = tgtSmds->GetNodes();
+ while ( nItT->more() && !pOK )
+ {
+ const SMDS_MeshNode* n = nItT->next();
+ tgtP = SMESH_MeshEditor::TNodeXYZ( n );
+ pOK = ( fabs( srcDist - tgtPP[0].Distance( tgtP )) < 2*eTol );
+ //cout << "E - nS " << p._node->GetID() << " - nT " << n->GetID()<< " OK - " << pOK<< " " << fabs( srcDist - tgtPP[0].Distance( tgtP ))<< " tol " << eTol<< endl;
+ }
+ }
+ }
+ if ( !pOK )
+ continue;
+
+ srcPP.push_back( p );
+ tgtPP.push_back( tgtP );
+ }
+ }
+ if ( srcPP.size() != 3 )
+ return false;
+
+ // make transformation
+ gp_Trsf fromTgtCS, toSrcCS; // from/to global CS
+ gp_Ax2 srcCS( srcPP[0], gp_Vec( srcPP[0], srcPP[1] ), gp_Vec( srcPP[0], srcPP[2]));
+ gp_Ax2 tgtCS( tgtPP[0], gp_Vec( tgtPP[0], tgtPP[1] ), gp_Vec( tgtPP[0], tgtPP[2]));
+ toSrcCS .SetTransformation( gp_Ax3( srcCS ));
+ fromTgtCS.SetTransformation( gp_Ax3( tgtCS ));
+ fromTgtCS.Invert();
+
+ trsf = fromTgtCS * toSrcCS;
+ }
+
+ // 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() );
+
+ 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;
+
+ if ( !tgtEdge.IsPartner( srcEdge.Current() ))
+ {
+ // check that transormation is OK by three nodes
+ gp_Pnt p0S = SMESH_MeshEditor::TNodeXYZ( (srcNodes.begin()) ->second);
+ gp_Pnt p1S = SMESH_MeshEditor::TNodeXYZ( (srcNodes.rbegin()) ->second);
+ gp_Pnt p2S = SMESH_MeshEditor::TNodeXYZ( (++srcNodes.begin())->second);
+
+ gp_Pnt p0T = SMESH_MeshEditor::TNodeXYZ( (tgtNodes.begin()) ->second);
+ gp_Pnt p1T = SMESH_MeshEditor::TNodeXYZ( (tgtNodes.rbegin()) ->second);
+ gp_Pnt p2T = SMESH_MeshEditor::TNodeXYZ( (++tgtNodes.begin())->second);
+
+ // transform source points, they must coinside with target ones
+ if ( p0T.SquareDistance( p0S.Transformed( trsf )) > tol ||
+ p1T.SquareDistance( p1S.Transformed( trsf )) > tol ||
+ p2T.SquareDistance( p2S.Transformed( trsf )) > tol )
+ {
+ //cout << "KO trsf, 3 dist: "
+ //<< p0T.SquareDistance( p0S.Transformed( trsf ))<< ", "
+ //<< p1T.SquareDistance( p1S.Transformed( trsf ))<< ", "
+ //<< p2T.SquareDistance( p2S.Transformed( trsf ))<< ", "<<endl;
+ 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
+
+ // 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;
+ }
+