使用起始 X/Y 和起始扫描角度获取 ArcSegment 中的终点
有没有人有一个好的算法来计算ArcSegment
的终点?这不是圆弧,而是椭圆弧。
例如,我有以下初始值:
- 起始点 X = 0.251
- 起始点 Y = 0.928
- 宽度半径 = 0.436
- 高度半径 = 0.593
- 起始角度 = 169.51
- 扫描角度 = 123.78
我知道我的圆弧应该结束的位置就在 X 周围=0.92 和 Y=0.33(通过另一个程序),但我需要在 ArcSegment
中执行此操作并指定终点。我只需要知道如何计算终点,所以它看起来像这样:
<ArcSegment Size="0.436,0.593" Point="0.92,0.33" IsLargeArc="False" SweepDirection="Clockwise" />
有人知道计算这个的好方法吗? (我认为这是 WPF 或任何其他语言并不重要,因为数学应该是相同的)。
这是一张图片。除了终点(橙色点)之外,所有值都是已知的。
编辑: 我发现有一个名为 DrawArc
的例程.NET GDI+ 中的重载几乎可以满足我的需要(稍后将详细介绍“几乎”)。
为了简化查看,以下例程为例:
Public Sub MyDrawArc(e As PaintEventArgs)
Dim blackPen As New Pen(Color.Black, 2)
Dim x As Single = 0.0F
Dim y As Single = 0.0F
Dim width As Single = 100.0F
Dim height As Single = 200.0F
Dim startAngle As Single = 180.0F
Dim sweepAngle As Single = 135.0F
e.Graphics.DrawArc(blackPen, x, y, width, height, startAngle, sweepAngle)
Dim redPen As New Pen(Color.Red, 2)
e.Graphics.DrawLine(redPen, New Point(0, 55), New Point(95, 55))
End Sub
Private Sub ImageBox_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles ImageBox.Paint
MyDrawArc(e)
End Sub
该例程将终点直接放置在X=95,Y=55
处。对于圆形椭圆提到的其他例程将导致 X=85, Y=29
。如果有一种方法1)不必绘制任何东西并且2)让e.Graphics.DrawArc
返回终点坐标,这就是我需要的。
现在问题变得更加清晰了 - 有人知道 e.Graphics.DrawArc 是如何实现的吗?
Does anyone have a good algorithm for calculating the end point of ArcSegment
? This is not a circular arc - it's an elliptical one.
For example, I have these initial values:
- Start Point X = 0.251
- Start Point Y = 0.928
- Width Radius = 0.436
- Height Radius = 0.593
- Start Angle = 169.51
- Sweep Angle = 123.78
I know the location that my arc should end up at is right around X=0.92 and Y=0.33 (through another program), but I need to do this in an ArcSegment
with specifying the end point. I just need to know how to calculate the end point so it would look like this:
<ArcSegment Size="0.436,0.593" Point="0.92,0.33" IsLargeArc="False" SweepDirection="Clockwise" />
Does anyone know of a good way to calculate this? (I don't suppose it matters that this is WPF or any other language as the math should be the same).
Here is an image. All values are known in it, except for end point (the orange point).
EDIT:
I've found that there is a routine called DrawArc
with an overload in .NET GDI+ that pretty much does what I need (more on the "pretty much" in a sec).
To simplify viewing it, take the following as an example:
Public Sub MyDrawArc(e As PaintEventArgs)
Dim blackPen As New Pen(Color.Black, 2)
Dim x As Single = 0.0F
Dim y As Single = 0.0F
Dim width As Single = 100.0F
Dim height As Single = 200.0F
Dim startAngle As Single = 180.0F
Dim sweepAngle As Single = 135.0F
e.Graphics.DrawArc(blackPen, x, y, width, height, startAngle, sweepAngle)
Dim redPen As New Pen(Color.Red, 2)
e.Graphics.DrawLine(redPen, New Point(0, 55), New Point(95, 55))
End Sub
Private Sub ImageBox_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles ImageBox.Paint
MyDrawArc(e)
End Sub
This routine squarely puts the end point at X=95, Y=55
. Other routines mentioned for circular ellipses would result in X=85, Y=29
. If there was a way to 1) Not have to draw anything and 2) have e.Graphics.DrawArc
return the end-point coordinates, this is what I would need.
So now the question gains some clarity - does anyone know how e.Graphics.DrawArc
is implemented?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Graphics.DrawArc
调用 gdiplus.dll 中的本机函数GdipDrawArcI
。该函数调用同一 dll 中的 arc2polybezier 函数。它似乎使用贝塞尔曲线来近似椭圆弧。为了获得您正在寻找的完全相同的端点,我们必须对该函数进行逆向工程并弄清楚它到底是如何工作的。幸运的是, Wine 的好人有 已经为我们做到了。
这是 arc2polybezier 方法,大致从 C 翻译为 C# (请注意,因为这是从 Wine 翻译的,所以该代码已获得 LGPL< /a>):
使用此代码作为指导,结合一些数学知识,我编写了这个端点计算器类(不是 LGPL):
以下是一些示例。请注意,您给出的第一个示例是不正确的 - 对于这些初始值,
DrawArc()
的端点为 (0.58, 0.97),不是 (0.92, 0.33)。Graphics.DrawArc
calls the native functionGdipDrawArcI
in gdiplus.dll. This function calls thearc2polybezier
function in the same dll. It appears to use a bezier curve to approximate an elliptical arc. In order to get the exact same end-point you're looking for, we'd have to reverse-engineer that function and figure out exactly how it works.Fortunately, the good people at Wine have already done that for us.
Here is the arc2polybezier method, roughly translated from C to C# (note that because this was translated from Wine, this code is licensed under LGPL):
Using this code as a guide, along with a bit of math, I wrote this endpoint calculator class (not LGPL):
Here are some examples. Note that the first example you gave is incorrect - for those initial values,
DrawArc()
will have an endpoint of (0.58, 0.97), not (0.92, 0.33).所以,你的坐标是(xEnd,yEnd)。
So, your coordinate is (xEnd, yEnd).
“BlueRaja - Danny Pflughoeft”的答案是正确的,但是......它围绕半径点,必须使用 PointF 代替 Point:
我已经扩展了位类以便也有起点,以及每个方法的另一个签名:
the answer of "BlueRaja - Danny Pflughoeft" is correct but ... it rounds the radius point, a PointF has to be used instead a Point:
I've extended a bit the class in order to have starting points as well, and another signature per method:
这是有帮助吗:
ArcSegment 的数学
Is this of help:
The Mathematics of ArcSegment