Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

developer:sdksamples:draftanglecontour [2015/09/14] (current)
Line 1: Line 1:
 +====== Draft Angle Contouring ======
 +====== C++ ======
 +> **Summary:​** //​Demonstrates how to create contour curves based on draft angle using the Rhino SDK.//
 +
 +=====Question=====
 +We find Rhino'​s draft angle analysis very useful. But, it would be great it it could create contour curves at specific angles. For example:
 +
 +{{:​legacy:​en:​SdkDraftAngleContour.jpg}}
 +
 +Notice the red curve on the right-hand image. This is what we would like to automate. Is there an SDK function that will help us to this?
 +
 +=====Answer=====
 +There is not an SDK function that will help you do this. But, it is possible to write your own tool.
 +
 +Draft angle analysis works by calculating the angles between mesh vertex normals and the unit normal (in most cases this is the world z-axis). It is possible to perform this calculation from a plug-in command. From these angles, it is possible to determine whether or not a contour line would pass through a mesh vertex or if it would cross between two mesh vertices.
 +
 +The follow sample code demonstrates this process:
 +
 +===== C++ =====
 +<code c++>
 +
 +CRhinoCommand::​result CCommandTest::​RunCommand( const CRhinoCommandContext&​ context )
 +{
 +  // Pick a mesh object
 +  CRhinoGetObject go;
 +  go.SetCommandPrompt( L"​Select mesh for draft angle contour"​ );
 +  go.SetGeometryFilter( CRhinoGetObject::​mesh_object );
 +  go.GetObjects( 1, 1 );
 +  if( go.CommandResult() != success )
 +    return go.CommandResult();​
 +
 +  const ON_Mesh* pMesh = go.Object(0).Mesh();​
 +  if( 0 == pMesh )
 +    return failure;
 +
 +  // Copy mesh so we can tweak it if necessary
 +  ON_Mesh mesh( *pMesh );
 +
 +  // To make our life easy, convert all quads to triangles.
 +  mesh.ConvertQuadsToTriangles();​
 +
 +  // For draft angle analysis, mesh must have vertex normals.
 +  if( !mesh.HasVertexNormals() )
 +  {
 +    if( !mesh.ComputeVertexNormals() )
 +      return failure;
 +  }
 +
 +  // Specify a draft angle
 +  CRhinoGetNumber gn;
 +  gn.SetCommandPrompt( L"​Draft angle" );
 +  gn.SetDefaultNumber( m_angle );
 +  gn.SetLowerLimit( 0.0, TRUE );
 +  gn.SetUpperLimit( 90.0, TRUE );
 +  gn.GetNumber();​
 +  if( gn.CommandResult() != success )
 +    return gn.CommandResult();​
 +
 +  m_angle = gn.Number();​ // degrees
 +
 +  //////////////////////////////////////////////////////////////​
 +
 +  double A = m_angle * ( ON_PI / 180.0 ); // alpha
 +  ON_3dVector D = ON_zaxis; // unit normal
 +  int fvcnt = 3; // triangles
 +
 +  // Process each mesh face
 +  int fi, i, j;
 +  for( fi = 0; fi < mesh.m_F.Count();​ fi++ )
 +  {
 +    const ON_MeshFace&​ f = mesh.m_F[fi];​
 +
 +    // For each face vertex, calculate the draft angle
 +    double d[3], a[3];
 +    for( i = fvcnt - 1; i >= 0; i-- )
 +    {
 +      ON_3dVector N = mesh.m_N[f.vi[i]];​
 +      d[i] = RHINO_CLAMP( N * D, -1.0, 1.0 );
 +      a[i] = acos(d[i]) - A;
 +    }
 +
 +    // Determine if any of the angles meet our criteria.
 +    // If so, calculate a point on an edge at that angle.
 +    int P_count = 0;
 +    ON_3dPoint P[3];
 +
 +    for( i = 0; i < fvcnt; i++ )
 +    {
 +      j = (i + 1) % fvcnt;
 +
 +      // If zero, then draft angle point passes through vertex
 +      if( a[i] == 0 )
 +        P[P_count++] = mesh.m_V[f.vi[i]];​
 +
 +      // See if draft angle point crosses the edge between two vertices
 +      else if( a[i] * a[j] < 0.0 )
 +      {
 +        double t = a[i] / (a[i] - a[j]);
 +        P[P_count++] = ((1 - t) * mesh.m_V[f.vi[i]]) + (t * mesh.m_V[f.vi[j]]);​
 +      }
 +    }
 +
 +    // If we have calculated enough points, create some geometry
 +    if( P_count == 2 )
 +      context.m_doc.AddCurveObject( ON_Line(P[0],​ P[1]) );
 +    else if( P_count == 3 )
 +    {
 +      context.m_doc.AddCurveObject( ON_Line(P[0],​ P[1]) );
 +      context.m_doc.AddCurveObject( ON_Line(P[1],​ P[2]) );
 +      context.m_doc.AddCurveObject( ON_Line(P[2],​ P[0]) );
 +    }
 +  }
 +
 +  context.m_doc.Redraw();​
 +
 +  return success;
 +}
 +
 +</​code>​
 +===== VB.NET =====
 +<code vb>
 +
 +Public Overrides Function RunCommand(ByVal context As RMA.Rhino.IRhinoCommandContext) As RMA.Rhino.IRhinoCommand.result
 +
 +  ' Pick a mesh object
 +  Dim go As New MRhinoGetObject
 +  go.SetCommandPrompt("​Select mesh for draft angle contour"​)
 +  go.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.mesh_object)
 +  go.GetObjects(1,​ 1)
 +  If (go.CommandResult() <> IRhinoCommand.result.success) Then
 +    Return go.CommandResult()
 +  End If
 +
 +  Dim pMesh As IOnMesh = go.Object(0).Mesh()
 +  If (pMesh Is Nothing) Then
 +    Return IRhinoCommand.result.failure
 +  End If
 +
 +  ' Copy mesh so we can tweak it if necessary
 +  Dim mesh As New OnMesh(pMesh)
 +
 +  ' To make our life easy, convert all quads to triangles.
 +  mesh.ConvertQuadsToTriangles()
 +
 +  ' For draft angle analysis, mesh must have vertex normals.
 +  If (mesh.HasVertexNormals() = False) Then
 +    If (mesh.ComputeVertexNormals() = False) Then
 +      Return IRhinoCommand.result.failure
 +    End If
 +  End If
 +
 +  ' Specify a draft angle
 +  Dim gn As New MRhinoGetNumber()
 +  gn.SetCommandPrompt("​Draft angle"​)
 +  gn.SetLowerLimit(0.0,​ True)
 +  gn.SetUpperLimit(90.0,​ True)
 +  gn.GetNumber()
 +  If (gn.CommandResult() <> IRhinoCommand.result.success) Then
 +    Return gn.CommandResult()
 +  End If
 +
 +  Dim angle As Double = gn.Number() '​degrees
 +
 +  ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''​
 +
 +  Dim A As Double = angle * (OnUtil.On_PI / 180.0) ' alpha
 +  Dim D As New On3dVector(OnUtil.On_zaxis) ' unit normal
 +  Dim fvcnt As Integer = 3 ' triangles
 +
 +  ' Process each mesh face
 +  Dim fi As Integer = 0
 +  For fi = 0 To mesh.m_F.Count() - 1
 +    Dim f As OnMeshFace = mesh.m_F(fi)
 +
 +    ' For each face vertex, calculate the draft angle
 +    Dim dd(2) As Double
 +    Dim aa(2) As Double
 +    Dim i As Integer = 0
 +    Dim j As Integer = 0
 +
 +    For i = fvcnt - 1 To 0 Step -1
 +      Dim N As On3fVector = mesh.m_N(f.vi(i))
 +      dd(i) = N * D
 +      If (dd(i) < -1.0) Then dd(i) = -1.0
 +      If (dd(i) > 1.0) Then dd(i) = 1.0
 +      aa(i) = Math.Acos(dd(i)) - A
 +    Next
 +
 +    ' Determine if any of the angles meet our criteria.
 +    ' If so, calculate a point on an edge at that angle.
 +    Dim P_count As Integer = 0
 +    Dim P(2) As On3dPoint
 +
 +    For i = 0 To fvcnt - 1
 +      j = (i + 1) Mod fvcnt
 +      If (aa(i) = 0) Then
 +        Dim tmp As On3fPoint = mesh.m_V(f.vi(i))
 +        P(P_count) = New On3dPoint(tmp.x,​ tmp.y, tmp.z)
 +        P_count = P_count + 1
 +      ElseIf (aa(i) * aa(j) < 0.0) Then
 +        Dim t As Double = aa(i) / (aa(i) - aa(j))
 +        Dim tmpi As New On3fPoint(mesh.m_V(f.vi(i)) * (1 - System.Convert.ToSingle(t)))
 +        Dim tmpj As New On3fPoint(mesh.m_V(f.vi(j)) * System.Convert.ToSingle(t))
 +        Dim tmp As New On3fPoint(tmpi + tmpj)
 +        P(P_count) = New On3dPoint(tmp.x,​ tmp.y, tmp.z)
 +        P_count = P_count + 1
 +      End If
 +    Next
 +
 +    If (P_count = 2) Then
 +      context.m_doc.AddCurveObject(New OnLine(P(0),​ P(1)))
 +    ElseIf (P_count = 3) Then
 +      context.m_doc.AddCurveObject(New OnLine(P(0),​ P(1)))
 +      context.m_doc.AddCurveObject(New OnLine(P(1),​ P(2)))
 +      context.m_doc.AddCurveObject(New OnLine(P(2),​ P(0)))
 +    End If
 +
 +  Next
 +
 +  Return IRhinoCommand.result.success
 +
 +End Function
 +</​code>​
 +
 +
 +{{tag>​Developer cplusplus}}
  
developer/sdksamples/draftanglecontour.txt ยท Last modified: 2015/09/14 (external edit)