如何使用Visual Basic .NET绘制非常特定的环形扇区 [英] How to draw very specific annular sectors using 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屋!