McNeel Wiki
Determining the Normal Direction of a Brep Face
edit · print · help · all topics
Main Pages

AccuRender

Bongo

Brazil r/s

Developer

Flamingo

Penguin

Rhino Blogs

Rhino

Rhino Labs

Search

Languages

Česky

Deutsch

English

Español

Français

Italiano

Polish

日本語

한국어

中文(繁體)

 
.
DeveloperC++, .NET

Overview

To determine the normal direction of a surface, you can use one of the following functions:

  ON_Surface::NormalAt
  ON_Surface::EvNormal

To determine the normal direction of a face which is part of a brep, you can also use the above functions, as an ON_BrepFace object is derived from ON_Surface. But, you will also need to take into account the orientation of the brep face. If the orientation of the brep face is opposite of the underlying, natural surface orientation, then you will need to reverse the direction of the calculated normal vector.

It should also be noted that most surface in Rhino are really breps with a single face.

The following sample code demonstrates how to interactively determine the normal direction of a selected surface or brep face.

C++

  CRhinoCommand::result CCommandNormal::RunCommand( const CRhinoCommandContext& context )
  {
    // Select a surface
    CRhinoGetObject go;
    go.SetCommandPrompt( L"Select surface" );
    go.SetGeometryFilter( CRhinoGetObject::surface_object );
    go.GetObjects( 1, 1 );
    if( go.CommandResult() != success )
      return go.CommandResult();


    // Get the selected face
    const CRhinoObjRef& ref = go.Object(0);
    const ON_BrepFace* face = ref.Face();
    if( 0 == face )
      return failure;


    // Pick a point on the surface. Constrain
    // picking to the face.
    CRhinoGetPoint gp;
    gp.SetCommandPrompt( L"Select point on surface" );
    gp.Constrain( *face );
    gp.GetPoint();
    if( gp.CommandResult() != success )
      return gp.CommandResult();


    ON_3dPoint pt = gp.Point();


    // Get the parameters of the point on the
    // surface that is closest to pt
    double u, v;
    if( face->GetClosestPoint(pt, &u, &v) )
    {
      ON_3dPoint pt;
      ON_3dVector du, dv, dir;
      if( face->EvNormal(u, v, pt, du, dv, dir) )
      {
        // if the face orientation is opposite of 
        // the natural surface orientation, then
        // reverse the direction of the vector.
        if( face->m_bRev )
          dir.Reverse();


        RhinoApp().Print( 
          L"Surface normal at uv(%.2f,%.2f) = (%.2f,%.2f,%.2f)\n", 
          u, 
          v,
          dir.x, 
          dir.y, 
          dir.z 
          );
      }
    }


    return success;
  }

C# (Rhino 4)

  public override IRhinoCommand.result RunCommand(IRhinoCommandContext context)
  {
    // Select a surface
    MRhinoGetObject go = new MRhinoGetObject();
    go.SetCommandPrompt( "Select surface" );
    go.SetGeometryFilter( IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object );
    go.GetObjects( 1, 1 );
    if( go.CommandResult() != IRhinoCommand.result.success )
      return go.CommandResult();


    // Get the selected face
    IRhinoObjRef objref = go.Object(0);
    IOnBrepFace face = objref.Face();
    if( face == null )
      return IRhinoCommand.result.failure;


    // Pick a point on the surface. Constrain
    // picking to the face.
    MRhinoGetPoint gp = new MRhinoGetPoint();
    gp.SetCommandPrompt( "Select point on surface" );
    gp.Constrain( face );
    gp.GetPoint();
    if( gp.CommandResult() != IRhinoCommand.result.success )
      return gp.CommandResult();


    On3dPoint pt = gp.Point();


    // Get the parameters of the point on the
    // surface that is closest to pt
    double u=0.0, v=0.0;
    if( face.GetClosestPoint(pt, ref u, ref v) )
    {
      On3dVector du = new On3dVector();
      On3dVector dv = new On3dVector();
      On3dVector dir = new On3dVector();
      if( face.EvNormal( u, v, ref pt, ref du, ref dv, ref dir ) )
      {
        // if the face orientation is opposite of 
        // the natural surface orientation, then
        // reverse the direction of the vector.
        if( face.m_bRev )
          dir.Reverse();
        object[] args = {u,v,dir.x,dir.y,dir.z};
        string msg = string.Format("Surface normal at uv({0:f},{1:f}) = ({2:f},{3:f},{4:f})\n", args);
        RhUtil.RhinoApp().Print( msg );
      }
    }


    return IRhinoCommand.result.success;
  }

VB.NET (Rhino 4)

  Public Overrides Function RunCommand(ByVal context As RMA.Rhino.IRhinoCommandContext) _
    As RMA.Rhino.IRhinoCommand.result
    ' Select a surface
    Dim go As New MRhinoGetObject()
    go.SetCommandPrompt("Select surface")
    go.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object)
    go.GetObjects(1, 1)
    If (go.CommandResult() <> IRhinoCommand.result.success) Then
      Return go.CommandResult()
    End If


    ' Get the selected face
    Dim objref As IRhinoObjRef = go.Object(0)
    Dim face As IOnBrepFace = objref.Face()
    If (face Is Nothing) Then Return IRhinoCommand.result.failure


    ' Pick a point on the surface. Constrain
    ' picking to the face.
    Dim gp As New MRhinoGetPoint()
    gp.SetCommandPrompt("Select point on surface")
    gp.Constrain(face)
    gp.GetPoint()
    If (gp.CommandResult() <> IRhinoCommand.result.success) Then
      Return gp.CommandResult()
    End If


    Dim pt As On3dPoint = gp.Point()


    ' Get the parameters of the point on the
    ' surface that is closest to pt
    Dim u As Double = 0.0, v As Double = 0.0
    If (face.GetClosestPoint(pt, u, v)) Then
      Dim du As New On3dVector()
      Dim dv As New On3dVector()
      Dim dir As New On3dVector()
      If (face.EvNormal(u, v, pt, du, dv, dir)) Then
        ' if the face orientation is opposite of 
        ' the natural surface orientation, then
        ' reverse the direction of the vector.
        If (face.m_bRev) Then dir.Reverse()
        Dim args() As Object = {u, v, dir.x, dir.y, dir.z}
        Dim msg As String
        msg = String.Format("Surface normal at uv({0:f},{1:f}) = ({2:f},{3:f},{4:f})", args)
        RhUtil.RhinoApp().Print(msg + vbCrLf)
      End If
    End If


    Return IRhinoCommand.result.success
  End Function
rename · changes · history · subscriptions · lost and found · references · file upload