如何使用Visual Basic .NET绘制非常特定的环形扇区 [英] How to draw very specific annular sectors using visual basic .NET

查看:100
本文介绍了如何使用Visual Basic .NET绘制非常特定的环形扇区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我将解释更多...例如,如果我输入0度作为起点,输入360度作为终点,则它必须返回一个GraphicsPath,其环形扇区以X度开始(其中X是偏离2.5像素0度)并以Y度结束(其中Y是从360度偏移的-2.5像素).环形扇形的外部和内部曲线都必须遵守上述规定.基本上,就好像我在圆心处以输入的角度画了两条平行线(距离像素5个像素),并将这些线用作圆弧的起点和终点.输入的任何学位都必须为真.

此帖子: SVG甜甜圈切片作为路径元素(环形扇区) 几乎可以解决该问题,但它会从中心点(与Pie切片不同)向外绘制所有环形扇区,从而导致连续的外圈之间的间隙越来越大(如果每次将它们分开1度)(加上它是用于SVG).

我包括一张图片,解释了我想说的更好: valter 解决了这个问题.在他的代码答案中向下滚动至 EDIT 2 .

此图片:(解决方案

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的示例.

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

现在我们必须找到带有外圆(B)和带有内圆(A)的ε1'的截点:

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):

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

计算φ(OBB'三角形):

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

最后一件事.因为 Form坐标实坐标相反(仅用于Y轴),所以在使用 pntC 进行计算之前,请转换为实坐标:

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

瓦尔特

Here goes... I need to draw several annular sectors in VisualBasic.NET using a GraphicsPath.

I would for instance enter the annular sector's outer and inner diameter/radius and a starting and ending degree/radiant. The function must then return a GraphicsPath that can simply be added to another GraphicsPath as a closed shape. This seems very easy to do, but I need it to keep a 5 pixel gap between the annular sectors.

I will explain more... If for instance I enter 0 degrees as starting point and 360 degrees as ending point it must return a GraphicsPath with an annular sector that starts at X degrees (where X is 2.5 pixels offset from 0 degrees) and ends at Y degrees (where Y is -2.5 pixels offset from 360 degrees). Both the outer and inner curves of the annular sector must adhere to the above. It basically must be as if I drew two parallel lines 5 pixels apart through the circle's center at the degrees entered and used the lines as starting and ending points for the arcs. This must hold true for any Degrees entered.

This post: SVG donut slice as path element (annular sector) Almost solves the problem, but it draws all annular sectors from the center point (not unlike Pie slices) outwards causing consecutive outer rings to have bigger and bigger gaps in between if you split them with 1 Degree each time (plus it is for SVG).

I include an image explaining what I am trying to say better: https://onedrive.live.com/redir?resid=79292E5BC057FE03!112&authkey=!AMnkq0bjbsH4BwU&v=3&ithint=photo%2cjpg

This question was solved by valter. Scroll down to EDIT 2 in his answer for the code.

This image: (https://onedrive.live.com/redir?resid=79292E5BC057FE03!113&authkey=!AGxrnpf8MiiEX48&v=3&ithint=photo%2cjpg) shows what can be achieved with his solution.

The following code was used to create the GraphicsPath used to draw the pie and annular sectors in the image. At the time of writing this negative sweepA (sweep angle) was not supported.

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)

Thanks

drifter

解决方案

pntC is the center. outerR and innerR are the radius. startA and endA are the angles. The angles are measured from x axis and clockwise

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

EDIT

This is an example of how to find the GraphicPath with the gap.

Dim pth As New GraphicsPath

pth.AddArc(outArc)

pth.AddLine(D, C)

pth.AddArc(innArc)

pth.AddLine(A, B)

and there is your path. Lets find A, B (the same logic applies to C, D):

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

a is known (the angle of ε1 with x axis) and b can be calculated (pntC belongs to ε1):

pntC.Υ = a * pntC.X + b

Now we have to find the intercept points of ε1' with outer circle(B) and with inner circle(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)

Now we need to valculate outArc, innArc. outArc (the same logic applies for innerArc):

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

Calculating φ (OBB' triangle):

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

One last thing. Because Form coordinates are opposite from real ones (only for Y axis), before using pntC for your calculation, convert to real one :

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

and when you calculate A, B, C, D, transform to Form ones (the r means real):

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

EDIT 2

With the gap:

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

valter

这篇关于如何使用Visual Basic .NET绘制非常特定的环形扇区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆