+ //================================================================================
+ /*!
+ * \brief Sort nodes on a FACE
+ */
+ void Hexahedron::sortVertexNodes(vector<_Node*>& nodes, _Node* curNode, TGeomID faceID)
+ {
+ if ( nodes.size() > 20 ) return;
+
+ // get shapes under nodes
+ TGeomID nShapeIds[20], *nShapeIdsEnd = &nShapeIds[0] + nodes.size();
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ if ( !( nShapeIds[i] = nodes[i]->ShapeID() ))
+ return;
+
+ // get shapes of the FACE
+ const TopoDS_Face& face = TopoDS::Face( _grid->_shapes( faceID ));
+ list< TopoDS_Edge > edges;
+ list< int > nbEdges;
+ int nbW = SMESH_Block::GetOrderedEdges (face, edges, nbEdges);
+ if ( nbW > 1 ) {
+ // select a WIRE - remove EDGEs of irrelevant WIREs from edges
+ list< TopoDS_Edge >::iterator e = edges.begin(), eEnd = e;
+ list< int >::iterator nE = nbEdges.begin();
+ for ( ; nbW > 0; ++nE, --nbW )
+ {
+ std::advance( eEnd, *nE );
+ for ( ; e != eEnd; ++e )
+ for ( int i = 0; i < 2; ++i )
+ {
+ TGeomID id = i==0 ?
+ _grid->_shapes.FindIndex( *e ) :
+ _grid->_shapes.FindIndex( SMESH_MesherHelper::IthVertex( 0, *e ));
+ if (( id > 0 ) &&
+ ( std::find( &nShapeIds[0], nShapeIdsEnd, id ) != nShapeIdsEnd ))
+ {
+ edges.erase( eEnd, edges.end() ); // remove rest wires
+ e = eEnd = edges.end();
+ --e;
+ nbW = 0;
+ break;
+ }
+ }
+ if ( nbW > 0 )
+ edges.erase( edges.begin(), eEnd ); // remove a current irrelevant wire
+ }
+ }
+ // rotate edges to have the first one at least partially out of the hexa
+ list< TopoDS_Edge >::iterator e = edges.begin(), eMidOut = edges.end();
+ for ( ; e != edges.end(); ++e )
+ {
+ if ( !_grid->_shapes.FindIndex( *e ))
+ continue;
+ bool isOut = false;
+ gp_Pnt p;
+ double uvw[3], f,l;
+ for ( int i = 0; i < 2 && !isOut; ++i )
+ {
+ if ( i == 0 )
+ {
+ TopoDS_Vertex v = SMESH_MesherHelper::IthVertex( 0, *e );
+ p = BRep_Tool::Pnt( v );
+ }
+ else if ( eMidOut == edges.end() )
+ {
+ TopLoc_Location loc;
+ Handle(Geom_Curve) c = BRep_Tool::Curve( *e, loc, f, l);
+ if ( c.IsNull() ) break;
+ p = c->Value( 0.5 * ( f + l )).Transformed( loc );
+ }
+ else
+ {
+ continue;
+ }
+
+ _grid->ComputeUVW( p.XYZ(), uvw );
+ if ( isOutParam( uvw ))
+ {
+ if ( i == 0 )
+ isOut = true;
+ else
+ eMidOut = e;
+ }
+ }
+ if ( isOut )
+ break;
+ }
+ if ( e != edges.end() )
+ edges.splice( edges.end(), edges, edges.begin(), e );
+ else if ( eMidOut != edges.end() )
+ edges.splice( edges.end(), edges, edges.begin(), eMidOut );
+
+ // sort nodes accoring to the order of edges
+ _Node* orderNodes [20];
+ TGeomID orderShapeIDs[20];
+ int nbN = 0;
+ TGeomID id, *pID;
+ for ( e = edges.begin(); e != edges.end(); ++e )
+ {
+ if (( id = _grid->_shapes.FindIndex( SMESH_MesherHelper::IthVertex( 0, *e ))) &&
+ (( pID = std::find( &nShapeIds[0], nShapeIdsEnd, id )) != nShapeIdsEnd ))
+ {
+ orderShapeIDs[ nbN ] = id;
+ orderNodes [ nbN++ ] = nodes[ pID - &nShapeIds[0] ];
+ *pID = -1;
+ }
+ if (( id = _grid->_shapes.FindIndex( *e )) &&
+ (( pID = std::find( &nShapeIds[0], nShapeIdsEnd, id )) != nShapeIdsEnd ))
+ {
+ orderShapeIDs[ nbN ] = id;
+ orderNodes [ nbN++ ] = nodes[ pID - &nShapeIds[0] ];
+ *pID = -1;
+ }
+ }
+ if ( nbN != nodes.size() )
+ return;
+
+ bool reverse = ( orderNodes[0 ]->Point().SquareDistance( curNode->Point() ) >
+ orderNodes[nbN-1]->Point().SquareDistance( curNode->Point() ));
+
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ nodes[ i ] = orderNodes[ reverse ? nbN-1-i : i ];
+ }
+