産業用ロボットで使用する DXF パーサーを作成しています。ロボットは線と円弧でしか移動できないため、楕円エンティティを一連の 2 つの円弧に分解する必要がありました (円弧機能のKeeperに感謝します)。変換は完全に機能しますが、キャンバス上で円弧をパスとして描画しようとすると、一部がずれます。
これらの円弧は実際にはコタンジェントであることを知っています。そうしないと、輪郭のグループ化アルゴリズムによって別々のパスが作成されるため、これは間違いなく表示上の問題です (開始点と終了点も手動で確認し、これを確認しました)。また、同じ方法を使用して一連のバイアークをエクスポートしましたが、SolidWorks から手動でエクスポートしたところ、同じ問題が発生しました。
これはフォームの出力のイメージです。バイアークがずれている場所を丸で囲みました。
参照用の楕円変換コードは次のとおりです。楕円のセグメント2n
時間をサンプリングするだけです。ここn
で、必要な弧の数です。次に、Keeperの 3 点円弧機能を使用して、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
これは、Arc オブジェクトをグラフィックに変換するコードです (始点、終点、中心点、および半径として格納されます)。
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
この問題の解決策はありますか、それとも固有の表示の問題ですか?