2013-03-28 3 views
1

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

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

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

enter image description here

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

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 

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

+0

@LarsTech Спасибо за уборку. – Crazymoomin

ответ

0

РЕШИТЬ:

Вопрос заключается в том, что я использовал целое число на основе 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)