Question

I am creating a DXF parser for use by an industrial robot. The robot can only move in lines and arcs, so I've had to decompose ellipse entities into a series of biarcs (thanks to Keeper for the arc function). The conversion works perfectly, but when I try to draw the arcs as a path on the canvas, some are misaligned.

I know that these arcs are really cotangent as otherwise my contour grouping algorithm would have made them separate paths, so it's definitely a display issue (I've also checked the Startpoints and Endpoints manually and have confirmed this). I've also exported a series of biarcs using the same method but by hand out of SolidWorks and have encountered the same problem.

Here is an image of the output on the form, I've circled where the biarcs are misaligned:

enter image description here

Here is the ellipse conversion code for reference, it simply samples the ellipse segment 2n times, where n is the number of arcs wanted. Then using the 3 point arc function by Keeper it draws arcs for every set of 3 points.

Public Function Ellipse2DToArcs(ByVal CenterPoint As XYZPoint, ByVal MajorRadius As Double, ByVal MinorRadius As Double, ByVal StartAngle As Double, ByVal EndAngle As Double, ByVal OffsetAngle As Double)

 Dim PointList As New List(Of XYZPoint)
 Dim ArcList As New List(Of ShapeClasses.ArcClass)

 For i = StartAngle To EndAngle Step (EndAngle - StartAngle) / (My.Settings.EllipseApprox * 2)
   PointList.Add(New XYZPoint With {.X = CenterPoint.X + MajorRadius * Math.Cos(i) * Math.Cos(OffsetAngle) - MinorRadius * Math.Sin(i) * Math.Sin(OffsetAngle), .Y = CenterPoint.Y + MajorRadius * Math.Cos(i) * Math.Sin(OffsetAngle) + MinorRadius * Math.Sin(i) * Math.Cos(OffsetAngle)})
 Next

 For i As UInteger = 1 To PointList.Count - 2 Step 2
   Dim D As Double = 2 * (PointList(i - 1).X - PointList(i + 1).X) * (PointList(i + 1).Y - PointList(i).Y) + 2 * (PointList(i).X - PointList(i + 1).X) * (PointList(i - 1).Y - PointList(i + 1).Y)
   Dim M1 As Double = ((PointList(i - 1).X ^ 2) - (PointList(i + 1).X ^ 2) + (PointList(i - 1).Y ^ 2) - (PointList(i + 1).Y ^ 2))
   Dim M2 As Double = ((PointList(i + 1).X ^ 2) - (PointList(i).X ^ 2) + (PointList(i + 1).Y ^ 2) - (PointList(i).Y ^ 2))
   Dim NX As Double = M1 * (PointList(i + 1).Y - PointList(i).Y) + M2 * (PointList(i + 1).Y - PointList(i - 1).Y)
   Dim NY As Double = M1 * (PointList(i).X - PointList(i + 1).X) + M2 * (PointList(i - 1).X - PointList(i + 1).X)
   Dim CX As Double = NX / D
   Dim CY As Double = NY / D

   ArcList.Add(New ShapeClasses.ArcClass With {.Radius = Math.Sqrt((CX - PointList(i + 1).X) ^ 2 + (CY - PointList(i + 1).Y) ^ 2), .CenterPoint = New XYZPoint With {.X = CX, .Y = CY}, .StartPoint = PointList(i - 1), .EndPoint = PointList(i + 1)})

 Next
 Return ArcList.ToArray
End Function

This is the code that converts the Arc Object to a graphic (it's stored as a startpoint, endpoint, centerpoint and radius):

Public Function Arc2DToDraw(ByVal Arc As ShapeClasses.ArcClass)

  'calculate start angle
  Dim StartAngle As Single = Math.Atan2(Arc.StartPoint.Y - Arc.CenterPoint.Y, Arc.StartPoint.X - Arc.CenterPoint.X) * (180 / Math.PI)

  'calculate end angle
  Dim EndAngle As Single = Math.Atan2(Arc.EndPoint.Y - Arc.CenterPoint.Y, Arc.EndPoint.X - Arc.CenterPoint.X) * (180 / Math.PI)

  If StartAngle = EndAngle Then 'is a circle

    '359.99 is a kludge to prevent a chord forming between 0 and 270 (why I have no idea)
    Return {New System.Drawing.Rectangle(Arc.CenterPoint.X - Arc.Radius, Arc.CenterPoint.Y - Arc.Radius, Arc.Radius * 2, Arc.Radius * 2), StartAngle, CSng(359.99)} 
  Else

    Return {New System.Drawing.Rectangle(Arc.CenterPoint.X - Arc.Radius, Arc.CenterPoint.Y - Arc.Radius, Arc.Radius * 2, Arc.Radius * 2), StartAngle, -(StartAngle - EndAngle)}

  End If
End Function

Is there a solution to this problem, or is it an inherent display issue?

Was it helpful?

Solution

SOLVED:

The issue was that I was using the integer based Rectangle rather than float based RectangleF which was invoking a narrowing conversion when drawing the arc.

New System.Drawing.Rectangle(Arc.CenterPoint.X - Arc.Radius, Arc.CenterPoint.Y - Arc.Radius, Arc.Radius * 2, Arc.Radius * 2)

Should be changed to:

New System.Drawing.RectangleF(Arc.CenterPoint.X - Arc.Radius, Arc.CenterPoint.Y - Arc.Radius, Arc.Radius * 2, Arc.Radius * 2) 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top