+ * \brief Return normal to a FACE at a node
+ * \param [in] n - node
+ * \param [in] face - FACE
+ * \param [in] helper - helper
+ * \param [out] isOK - true or false
+ * \param [in] shiftInside - to find normal at a position shifted inside the face
+ * \return gp_XYZ - normal
+ */
+//================================================================================
+
+gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
+ const TopoDS_Face& face,
+ SMESH_MesherHelper& helper,
+ bool& isOK,
+ bool shiftInside)
+{
+ gp_XY uv;
+ if ( shiftInside )
+ {
+ // get a shifted position
+ gp_Pnt p = SMESH_TNodeXYZ( node );
+ gp_XYZ shift( 0,0,0 );
+ TopoDS_Shape S = helper.GetSubShapeByNode( node, helper.GetMeshDS() );
+ switch ( S.ShapeType() ) {
+ case TopAbs_VERTEX:
+ {
+ shift = getFaceDir( face, TopoDS::Vertex( S ), node, helper, isOK );
+ break;
+ }
+ case TopAbs_EDGE:
+ {
+ shift = getFaceDir( face, TopoDS::Edge( S ), node, helper, isOK );
+ break;
+ }
+ default:
+ isOK = false;
+ }
+ if ( isOK )
+ shift.Normalize();
+ p.Translate( shift * 1e-5 );
+
+ TopLoc_Location loc;
+ GeomAPI_ProjectPointOnSurf& projector = helper.GetProjector( face, loc, 1e-7 );
+
+ if ( !loc.IsIdentity() ) p.Transform( loc.Transformation().Inverted() );
+
+ projector.Perform( p );
+ if ( !projector.IsDone() || projector.NbPoints() < 1 )
+ {
+ isOK = false;
+ return p.XYZ();
+ }
+ Quantity_Parameter U,V;
+ projector.LowerDistanceParameters(U,V);
+ uv.SetCoord( U,V );
+ }
+ else
+ {
+ uv = helper.GetNodeUV( face, node, 0, &isOK );
+ }
+
+ gp_Dir normal;
+ isOK = false;
+
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
+ if ( GeomLib::NormEstim( surface, uv, 1e-10, normal ) < 3 )
+ {
+ normal;
+ isOK = true;
+ }
+ else // hard singularity
+ {
+ const TGeomID faceID = helper.GetMeshDS()->ShapeToIndex( face );
+
+ SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() )
+ {
+ const SMDS_MeshElement* f = fIt->next();
+ if ( f->getshapeId() == faceID )
+ {
+ isOK = SMESH_MeshAlgos::FaceNormal( f, (gp_XYZ&) normal.XYZ(), /*normalized=*/true );
+ if ( isOK )
+ {
+ if ( helper.IsReversedSubMesh( face ))
+ normal.Reverse();
+ break;
+ }
+ }
+ }
+ }
+ return normal.XYZ();
+}
+
+//================================================================================
+/*!
+ * \brief Return a normal at a node weighted with angles taken by FACEs