+//================================================================================
+/*!
+ * \brief Return (unsorted) nodes of the i-th EDGE.
+ * Nodes moved to other geometry by MergeNodes() are also returned.
+ * \retval bool - is OK
+ */
+//================================================================================
+
+bool StdMeshers_FaceSide::GetEdgeNodes(size_t i,
+ vector<const SMDS_MeshNode*>& nodes,
+ bool inlude1stVertex,
+ bool inludeLastVertex) const
+{
+ if ( i >= myEdge.size() )
+ return false;
+
+ SMESH_Mesh* mesh = myProxyMesh->GetMesh();
+ SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
+ SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] );
+
+ if ( inlude1stVertex )
+ {
+ if ( const SMDS_MeshNode* n0 = VertexNode( i ))
+ nodes.push_back( n0 );
+ }
+
+ if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 ))
+ {
+ if ( mesh->HasModificationsToDiscard() ) // check nb of nodes on the EDGE sub-mesh
+ {
+ int iQuad = sm->NbElements() ? sm->GetElements()->next()->IsQuadratic() : 0;
+ int nbExpect = sm->NbElements() - 1 + iQuad * sm->NbElements();
+ if ( nbExpect != sm->NbNodes() ) // some nodes are moved from the EDGE by MergeNodes()
+ {
+ // add nodes of all segments
+ typedef set< const SMDS_MeshNode* > TNodeSet;
+ TNodeSet sharedNodes;
+ SMDS_ElemIteratorPtr segIt = sm->GetElements();
+ while ( segIt->more() )
+ {
+ const SMDS_MeshElement* seg = segIt->next();
+ if ( seg->GetType() != SMDSAbs_Edge )
+ continue;
+ for ( int i = 0; i < 3-myIgnoreMediumNodes; ++i )
+ {
+ const SMDS_MeshNode* n = seg->GetNode( i );
+ if ( i == 2 ) // medium node
+ {
+ nodes.push_back( n );
+ }
+ else
+ {
+ pair<TNodeSet::iterator, bool> it2new = sharedNodes.insert( n );
+ if ( !it2new.second ) // n encounters twice == it's on EDGE, not on VERTEX
+ {
+ nodes.push_back( n );
+ sharedNodes.erase( it2new.first );
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( nodes.size() < 2 ) // add nodes assigned to the EDGE
+ {
+ SMDS_NodeIteratorPtr nItr = sm->GetNodes();
+ while ( nItr->more() )
+ {
+ const SMDS_MeshNode* n = nItr->next();
+ if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( n, SMDSAbs_Edge ))
+ continue;
+ nodes.push_back( n );
+ }
+ }
+ } // if ( sm && sm->NbElements() > 0 )
+
+ if ( inludeLastVertex )
+ {
+ if ( const SMDS_MeshNode* n1 = VertexNode( i+1 ))
+ nodes.push_back( n1 );
+ }
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Return a node from the i-th VERTEX (count starts from zero)
+ * Nodes moved to other geometry by MergeNodes() are also returned.
+ * \param [in] i - the VERTEX index
+ * \param [out] isMoved - returns \c true if the found node is moved by MergeNodes()
+ * \return const SMDS_MeshNode* - the found node
+ */
+//================================================================================
+
+const SMDS_MeshNode* StdMeshers_FaceSide::VertexNode(std::size_t i, bool* isMoved) const
+{
+ TopoDS_Vertex V = ( i >= myEdge.size() ) ? LastVertex() : FirstVertex(i);
+
+ const SMDS_MeshNode* n = SMESH_Algo::VertexNode( V, myProxyMesh->GetMeshDS() );
+
+ if ( !n && !myEdge.empty() && myProxyMesh->GetMesh()->HasModificationsToDiscard() )
+ {
+ size_t iE = ( i < myEdge.size() ) ? i : myEdge.size()-1;
+ SMESHDS_SubMesh* sm = myProxyMesh->GetMeshDS()->MeshElements( myEdgeID[ iE ]);
+
+ n = SMESH_Algo::VertexNode( V, sm, myProxyMesh->GetMesh(), /*checkV=*/false );
+
+ if (( !n ) &&
+ (( i > 0 && (int) i < NbEdges() ) || IsClosed() ))
+ {
+ iE = SMESH_MesherHelper::WrapIndex( int(i)-1, NbEdges() );
+ sm = myProxyMesh->GetMeshDS()->MeshElements( myEdgeID[ iE ]);
+ n = SMESH_Algo::VertexNode( V, sm, myProxyMesh->GetMesh(), /*checkV=*/false );
+ }
+
+ if ( n && n->GetPosition()->GetDim() == 1 ) // check that n does not lie on an EDGE of myFace
+ {
+ TopoDS_Shape S = SMESH_MesherHelper::GetSubShapeByNode( n, myProxyMesh->GetMeshDS() );
+ if ( SMESH_MesherHelper::IsSubShape( S, myFace ))
+ n = 0; // VERTEX ignored by e.g. Composite Wire Discretization algo
+ }
+ if ( isMoved )
+ *isMoved = n;
+ }
+ return n;
+}
+