Биарк-рендеринг

Я создаю парсер DXF для использования промышленным роботом. Робот может двигаться только по линиям и дугам, поэтому мне пришлось разложить объекты эллипса на серию двух дуг (спасибо Keeper для функции дуги). Преобразование работает отлично, но когда я пытаюсь нарисовать дуги в виде пути на холсте, некоторые из них смещаются.

Я знаю, что эти дуги действительно кокасательные, так как иначе мой алгоритм группировки контуров сделал бы их отдельными путями, так что это определенно проблема отображения (я также вручную проверил начальную и конечную точки и подтвердил это). Я также экспортировал серию biarcs, используя тот же метод, но вручную из SolidWorks, и столкнулся с той же проблемой.

Вот изображение вывода в форме, я обвел там, где биарки смещены:

введите здесь описание изображения

Вот код преобразования эллипса для справки, он просто отбирает сегмент эллипса 2n раз, где n — количество требуемых дуг. Затем с помощью Keeper функции трехточечной дуги он рисует дуги для каждого набор из 3 очков.

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

Это код, который преобразует объект дуги в графику (он хранится как начальная точка, конечная точка, центральная точка и радиус):

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

Есть ли решение этой проблемы, или это проблема дисплея?


person Crazymoomin    schedule 28.03.2013    source источник
comment
@LarsTech Спасибо за чистку.   -  person Crazymoomin    schedule 28.03.2013


Ответы (1)


РЕШЕНО:

Проблема заключалась в том, что я использовал Rectangle на основе целого числа, а не RectangleF на основе числа с плавающей запятой, что вызывало сужающее преобразование при рисовании дуги.

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

Следует изменить на:

New System.Drawing.RectangleF(Arc.CenterPoint.X - Arc.Radius, Arc.CenterPoint.Y - Arc.Radius, Arc.Radius * 2, Arc.Radius * 2) 
person Crazymoomin    schedule 03.04.2013