如何使用visual basic .NET绘制非常特定的环形扇区

时间:2014-09-08 10:35:03

标签: vb.net math

这里......我需要使用GraphicsPath在VisualBasic.NET中绘制几个环形扇区。

例如,我会输入环形扇区的外径和内径/半径以及起始和终止度/辐射度。然后,该函数必须返回GraphicsPath,该GraphicsPath可以简单地作为闭合形状添加到另一个GraphicsPath。这似乎很容易做到,但我需要它在环形扇区之间保持5个像素的间隙。

我将解释更多...例如,如果我输入0度作为起点而360度作为终点,它必须返回一个GraphicsPath,其环形扇区以X度开始(其中X为2.5像素)偏离0度)并以Y度结束(其中Y是从360度偏移的-2.5像素)。环形扇区的外曲线和内曲线都必须符合上述要求。它基本上必须好像我在输入的度数中通过圆的中心绘制两条相距5行的平行线,并使用这些线作为弧的起点和终点。对于输入的任何学位,这必须适用。

这篇文章:SVG donut slice as path element (annular sector)几乎解决了这个问题,但它从中心点(与Pie切片不同)向外绘制所有环形扇区,导致连续的外环在它们之间有更大和更大的间隙每次1度(加上SVG)。

我添加了一张图片,说明我想要更好地说些什么:https://onedrive.live.com/redir?resid=79292E5BC057FE03!112&authkey=!AMnkq0bjbsH4BwU&v=3&ithint=photo%2cjpg

valter解决了这个问题。在代码的答案中向下滚动到编辑2

此图片:(https://onedrive.live.com/redir?resid=79292E5BC057FE03!113&authkey=!AGxrnpf8MiiEX48&v=3&ithint=photo%2cjpg)显示了他的解决方案可以实现的目标。

以下代码用于创建用于在图像中绘制饼图和环形扇区的sweepA。在撰写本文时,不支持此负Dim p As GraphicsPath = New GraphicsPath() p.AddPie(160.0F, 160.0F, 280.0F, 280.0F, 300.0F, 90.0F) p.AddPath(DrawAnnular(New Point(300I, 300I), 100I, 70I, 300.0F, 90.0F, 5.0R), False) p.AddPath(DrawAnnular(New Point(300I, 300I), 100I, 70I, 30.0F, 80.0F, 5.0R), False) p.AddPath(DrawAnnular(New Point(300I, 300I), 135I, 105I, 300.0F, 90.0F, 5.0R), False) p.AddPath(DrawAnnular(New Point(300I, 300I), 135I, 105I, 30.0F, 80.0F, 5.0R), False) (扫描角度)。

{{1}}

由于

架式钻机

1 个答案:

答案 0 :(得分:0)

pntC 是中心。 outerR innerR 是半径。 startA endA 是角度。角度从 x轴顺时针

开始测量
Private Sub DrawAnnular(ByVal pntC As Point, ByVal outerR As Integer, ByVal innerR As Integer, ByVal startA As Integer, ByVal endA As Integer)
    Dim g As Graphics
    Dim mypen As New Pen(Color.FromKnownColor(KnownColor.Control), 1) 'the form back color
    Dim mybrush As New SolidBrush(Color.FromKnownColor(KnownColor.Control)) 'the form back color

    g = Me.CreateGraphics
    g.SmoothingMode = SmoothingMode.AntiAlias

    g.FillPie(Brushes.Black, pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR, startA, -startA + endA) 'Outer
    g.FillPie(mybrush, pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR, startA, -startA + endA) 'Inner

    g.DrawPie(mypen, pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR, startA, -startA + endA) 'Outer
    g.DrawPie(mypen, pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR, startA, -startA + endA) 'Inner

    g.Dispose()
End Sub

修改

这是一个如何找到带有间隙的GraphicPath的示例。

enter image description here

Dim pth As New GraphicsPath

pth.AddArc(outArc)

pth.AddLine(D, C)

pth.AddArc(innArc)

pth.AddLine(A, B)

并且有你的道路。让我们找到A,B(同样的逻辑适用于C,D):

ε1 : y = a * x + b
ε1': y = a * x + (b +- 2,5) we keep the minus in this example

a 已知(ε1与x轴的角度)和 b 可以计算(pntC属于ε1):

pntC.Υ = a * pntC.X + b

现在我们必须找到ε1'与外圈(B)和内圈(A)的拦截点:

Solve these equations for x, y (point B)

circle: (x - pntC.X) * (x - pntC.X) + (y - pntC.Y) * (y - pntC.Y) = outerR * outerR
ε1'   : y = a * x + (b - 2,5)

Solve these equations for x, y (point A)

circle: (x - pntC.X) * (x - pntC.X) + (y - pntC.Y) * (y - pntC.Y) = innerR * innerR
ε1'   : y = a * x + (b - 2,5)

现在我们需要验证 outArc,innArc 。 outArc(相同的逻辑适用于innerArc):

enter image description here

pth.AddArc(outArc): pth.AddArc(pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR, startA + φ, endA - startA - 2 * φ)

计算φ(OBB'三角形):

enter image description here

sinφ = OB'/OB => sinφ = 2,5 / outerR

最后一件事。因为 Form坐标真实坐标相反,所以在使用 pntC 进行计算之前,转换为真实坐标: p>

real: pntC.Yr = (Form client Height) - pntC.Y

当你计算A,B,C,D时,转换为 Form 的那些( r 意味着真实的):

A.Y = (Form client Height) - A.Yr
B.Y = (Form client Height) - B.Yr
C.Y = (Form client Height) - C.Yr
D.Y = (Form client Height) - D.Yr

编辑2

有差距:

Private Sub DrawAnnular(ByVal pntC As Point, ByVal outerR As Integer, ByVal innerR As Integer, ByVal startA As Single, ByVal sweepA As Single, ByVal gap As Double)
    Dim g As Graphics
    Dim pth As New GraphicsPath
    Dim fe, dbl As Double 'fe is "φ"

    gap = gap / 2.0R

    g = Me.CreateGraphics
    g.SmoothingMode = SmoothingMode.AntiAlias

    dbl = gap / CDbl(outerR)
    fe = Math.Asin(dbl) * 180.0R / Math.PI

    pth.AddArc(pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR, startA + CSng(fe), sweepA - CSng(2.0R * fe)) 'Outer

    dbl = gap / CDbl(innerR)
    fe= Math.Asin(dbl) * 180.0R / Math.PI

    pth.AddArc(pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR, startA + sweepA - CSng(fe), -(sweepA - CSng(2.0R * fe))) 'Inner

    g.FillPath(Brushes.Black, pth)

    pth.Dispose()
    g.Dispose()
End Sub

瓦尔特