+ //================================================================================
+ /*!
+ * \brief Move coincident nodes to make node params on EDGE unique
+ * \param [in] theHelper - the helper
+ * \param [in] thePointsOnE - nodes on two opposite river sides
+ * \param [in] theSinuFace - the sinuous FACE
+ * \param [out] theNodes2Merge - the map of nodes to merge
+ */
+ //================================================================================
+
+ void separateNodes( SMESH_MesherHelper& theHelper,
+ map< double, pair< NodePoint, NodePoint > > & thePointsOnE,
+ SinuousFace& theSinuFace )
+ {
+ if ( thePointsOnE.size() < 2 )
+ return;
+
+ SMESHDS_Mesh* meshDS = theHelper.GetMeshDS();
+ const vector<TopoDS_Edge>& theSinuEdges = theSinuFace._sinuEdges;
+
+ typedef map< double, pair< NodePoint, NodePoint > >::iterator TIterator;
+
+ for ( int iSide = 0; iSide < 2; ++iSide )
+ {
+ TIterator u2NP0, u2NP1, u2NP = thePointsOnE.begin();
+ while ( u2NP != thePointsOnE.end() )
+ {
+ while ( u2NP != thePointsOnE.end() &&
+ get( u2NP->second, iSide )._node )
+ ++u2NP; // skip NP with an existing node (VERTEXes must be meshed)
+ if ( u2NP == thePointsOnE.end() )
+ break;
+
+ // find a range of not meshed NP on one EDGE
+ u2NP0 = u2NP;
+ if ( !findVertexAndNode( get( u2NP0->second, iSide ), theSinuEdges ))
+ --u2NP0;
+ int iCurEdge = get( u2NP->second, iSide )._edgeInd;
+ int nbNP = 1;
+ while ( get( u2NP->second, iSide )._edgeInd == iCurEdge &&
+ get( u2NP->second, iSide )._node == 0 )
+ ++u2NP, ++nbNP;
+ u2NP1 = u2NP; // end of not meshed NP on iCurEdge
+
+ // fix parameters of extremity NP of the range
+ NodePoint* np0 = & get( u2NP0->second, iSide );
+ NodePoint* np1 = & get( u2NP1->second, iSide );
+ const TopoDS_Edge& edge = TopoDS::Edge( theSinuFace._sinuEdges[ iCurEdge ]);
+ if ( np0->_node && np0->_edgeInd != iCurEdge )
+ {
+ np0->_u = theHelper.GetNodeU( edge, np0->_node );
+ np0->_edgeInd = iCurEdge;
+ }
+ if ( np1->_node && np1->_edgeInd != iCurEdge )
+ {
+ np1->_u = theHelper.GetNodeU( edge, np1->_node );
+ np1->_edgeInd = iCurEdge;
+ }
+
+ // find coincident NPs
+ double f,l;
+ BRep_Tool::Range( edge, f,l );
+ double tol = 1e-2* (l-f) / nbNP;
+ TIterator u2NPEq = thePointsOnE.end();
+ u2NP = u2NP0;
+ for ( ++u2NP; u2NP0 != u2NP1; ++u2NP, ++u2NP0 )
+ {
+ np0 = & get( u2NP0->second, iSide );
+ np1 = & get( u2NP->second, iSide );
+ bool coincides = ( Abs( np0->_u - np1->_u ) < tol );
+ if ( coincides && u2NPEq == thePointsOnE.end() )
+ u2NPEq = u2NP0;
+
+ if (( u2NPEq != thePointsOnE.end() ) &&
+ ( u2NP == u2NP1 || !coincides ))
+ {
+ if ( !get( u2NPEq->second, iSide )._node )
+ --u2NPEq;
+ if ( coincides && !get( u2NP->second, iSide )._node && u2NP0 != u2NP1 )
+ ++u2NP;
+
+ // distribute nodes between u2NPEq and u2NP
+ size_t nbSeg = std::distance( u2NPEq, u2NP );
+ double du = 1. / nbSeg * ( get( u2NP->second, iSide )._u -
+ get( u2NPEq->second, iSide )._u );
+ double u = get( u2NPEq->second, iSide )._u + du;
+
+ const SMDS_MeshNode* closeNode =
+ get(( coincides ? u2NP : u2NPEq )->second, iSide )._node;
+ list< const SMDS_MeshNode* >& eqNodes = theSinuFace._nodesToMerge[ closeNode ];
+
+ for ( ++u2NPEq; u2NPEq != u2NP; ++u2NPEq, u += du )
+ {
+ np0 = & get( u2NPEq->second, iSide );
+ np0->_u = u;
+ gp_Pnt p = np0->Point( theSinuFace._sinuCurves );
+ np0->_node = meshDS->AddNode( p.X(), p.Y(), p.Z() );
+ meshDS->SetNodeOnEdge( np0->_node, theSinuEdges[ np0->_edgeInd ], np0->_u );
+ if ( !closeNode )
+ eqNodes = theSinuFace._nodesToMerge[ closeNode = np0->_node ];
+ else
+ eqNodes.push_back( np0->_node );
+ }
+ }
+ }
+ u2NP = u2NP1;
+ while ( get( u2NP->second, iSide )._edgeInd != iCurEdge )
+ --u2NP;
+ u2NP++;
+ }
+ }
+ }
+