这个问题进一步推进了先前的question。在那个问题中,valter为我提供了一个非常好的答案,它使用两行代码来执行所有数学运算。我希望他也想尝试一下这个问题。即使它看起来很相似,但我还是无法使用任何数学工作。
我现在需要绘制完全相同的环形扇区,接受该问题中的OuterRadius变为Rectangle。我包含这个image来解释我的意思。您会注意到表示插入函数的Rectangle的红线。该图像实际上是我现在尝试生成的代码的屏幕截图。当然,大多数都是错误的,但例如左上角的环形扇区是正确的。所有环形扇区应终止于矩形边缘,同时补偿间隙。转角案件可能需要3分。
我已经决定发布我到目前为止的代码,所以清教徒们必须闭上眼睛,因为它非常野蛮:
<Extension()> Friend Sub AddAnnularSector(
ByVal aGraphicsPath As GraphicsPath,
ByVal aCenterPoint As PointR,
ByVal aInnerRadius As Double,
ByVal aOuterRectangle As RectangleF,
ByVal aStartAngle As Double,
ByVal aSweepAngle As Double,
ByVal aStartGap As Double,
ByVal aEndGap As Double)
'Declare local variables...
Dim tInnerStartOffset As Double = (Math.Asin(aStartGap / aInnerRadius) * 180.0R) / Math.PI
Dim tInnerEndOffset As Double = (Math.Asin(aEndGap / aInnerRadius) * 180.0R) / Math.PI
Dim tTestAngle1 As Double = aStartAngle + aSweepAngle - tInnerEndOffset
If tTestAngle1 > 360.0R Then tTestAngle1 -= 360.0R
If tTestAngle1 > 270.0R Then tTestAngle1 = 360.0R - tTestAngle1
If tTestAngle1 > 180.0R Then tTestAngle1 -= 180.0R
If tTestAngle1 > 90.0R Then tTestAngle1 = 180.0R - tTestAngle1
Dim tOuterEndLength As Double = (Math.Min(aOuterRectangle.Width, aOuterRectangle.Height) / 2) / Math.Sin(tTestAngle1.ToRadians)
Dim tTestAngle2 As Double = aStartAngle + tInnerStartOffset
If tTestAngle2 > 360.0R Then tTestAngle2 -= 360.0R
If tTestAngle2 > 270.0R Then tTestAngle2 = 360.0R - tTestAngle2
If tTestAngle2 > 180.0R Then tTestAngle2 -= 180.0R
If tTestAngle2 > 90.0R Then tTestAngle2 = 180.0R - tTestAngle2
Dim tOuterStartLength As Double = (Math.Min(aOuterRectangle.Width, aOuterRectangle.Height) / 2) / Math.Sin(tTestAngle2.ToRadians)
'Add the annular sector to the figure...
aGraphicsPath.StartFigure()
aGraphicsPath.AddArc(CSng(aCenterPoint.X - aInnerRadius), CSng(aCenterPoint.Y - aInnerRadius), CSng(aInnerRadius * 2.0R), CSng(aInnerRadius * 2.0R), CSng(aStartAngle + tInnerStartOffset), CSng(aSweepAngle - (tInnerStartOffset + tInnerEndOffset)))
aGraphicsPath.AddLines(New PointF() {
New PointF(CSng((aCenterPoint.X) + (Math.Cos((aStartAngle + aSweepAngle - tInnerEndOffset).ToRadians) * tOuterEndLength)), CSng((aCenterPoint.Y) + (Math.Sin((aStartAngle + aSweepAngle - tInnerEndOffset).ToRadians) * tOuterEndLength))),
New PointF(CSng((aCenterPoint.X) + (Math.Cos((aStartAngle + tInnerStartOffset).ToRadians) * tOuterStartLength)), CSng((aCenterPoint.Y) + (Math.Sin((aStartAngle + tInnerStartOffset).ToRadians) * tOuterStartLength)))
})
aGraphicsPath.CloseFigure()
Return
End Sub
您将注意到上一个问题的OuterRadius如何更改为aOuterRectangle。内弧的绘制方式与先前绘制的外弧完全相同。
编辑1 :只需将代码切掉一点就可以使其更清晰。
编辑2 :这是一张实际需要的图片,与上面只显示当前结果的图片不同。
编辑3 :这image显示了我认为快速的数学解决方案。
由于
架式钻机
答案 0 :(得分:0)
对于 wdthRect = 250,hgtRect = 200,innerR = 65,startA = 280.0,angle = 30.0,gap = 10.0R
Private Sub DrawAnnular2(ByVal pntC As Point, ByVal wdthRect As Integer, ByVal hgtRect As Integer, ByVal innerR As Integer, ByVal startA As Single, ByVal angle As Single, ByVal gap As Double)
Dim g As Graphics
Dim pth As New GraphicsPath
Dim pthRct As New GraphicsPath
Dim pthCrclIn As New GraphicsPath
Dim pthCrclOut As New GraphicsPath
Dim fe, theta, dbl As Double
Dim outerR, wdth As Integer
Dim rect As Rectangle
wdth = Math.Min(wdthRect, hgtRect)
outerR = CInt(Math.Sqrt(2.0R * (CDbl(wdth) / 2.0R) * (CDbl(wdth) / 2.0R))) 'πυθαγόρειο θεώρημα
rect.X = CInt(CDbl(pntC.X) - CDbl(wdth) / 2.0R)
rect.Y = CInt(CDbl(pntC.Y) - CDbl(wdth) / 2.0R)
rect.Width = wdth
rect.Height = wdth
pthCrclOut.AddEllipse(pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR)
pthCrclIn.AddEllipse(rect)
pthRct.AddRectangle(rect)
'////// The same as annular 1 //////////////////////////////////////////////////
g = Me.CreateGraphics
g.SmoothingMode = SmoothingMode.AntiAlias
gap /= 2.0R
dbl = gap / CDbl(outerR)
theta = Math.Asin(dbl) * 180.0R / Math.PI
fe = theta
pth.AddArc(pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR, startA + CSng(fe), angle - CSng(2.0R * fe)) 'Outer
dbl = gap / CDbl(innerR)
theta = Math.Asin(dbl) * 180.0R / Math.PI
fe = theta
pth.AddArc(pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR, startA + angle - CSng(fe), -(angle - CSng(2.0R * fe))) 'Inner
'////////////////////////////////////////////////////////////
Dim Reg1 As New Region(pth)
Dim Reg2 As New Region(pthRct)
Reg2.Intersect(Reg1)
g.FillRegion(Brushes.Aqua, Reg2) 'This is the actual annular 2.
g.DrawPath(Pens.Green, pthCrclIn)
g.DrawPath(Pens.Green, pthCrclOut)
g.DrawPath(Pens.Red, pthRct)
Reg1.Dispose()
Reg2.Dispose()
pthRct.Dispose()
pthCrclOut.Dispose()
pthCrclIn.Dispose()
pth.Dispose()
g.Dispose()
End Sub
这行代码:
Reg2.Intersect(Reg1)
实际上是蓝色和红色之间的交叉
修改
Private Function DrawAnnular2(ByVal pntC As Point, ByVal wdthRect As Integer, ByVal hgtRect As Integer, ByVal innerR As Integer, ByVal startA As Single, ByVal angle As Single, ByVal gap As Double) As GraphicsPath
Dim g As Graphics
Dim pth As New GraphicsPath
Dim pthRct As New GraphicsPath
Dim pthFinal As New GraphicsPath
Dim fe, theta, dbl As Double
Dim outerR, wdth As Integer
Dim rect As Rectangle
Dim lst1 As New List(Of Integer)
Dim lst2 As New List(Of Integer)
Dim lst3 As New List(Of Integer)
Dim lst4 As New List(Of Integer)
Dim i As Integer
Dim lstBl(3) As Boolean
Dim position As Integer
lstBl(0) = False
lstBl(1) = False
lstBl(2) = False
lstBl(3) = False
wdth = Math.Min(wdthRect, hgtRect)
outerR = CInt(Math.Sqrt(2.0R * (CDbl(wdth) / 2.0R) * (CDbl(wdth) / 2.0R))) 'πυθαγόρειο θεώρημα
rect.X = CInt(CDbl(pntC.X) - CDbl(wdth) / 2.0R)
rect.Y = CInt(CDbl(pntC.Y) - CDbl(wdth) / 2.0R)
rect.Width = wdth
rect.Height = wdth
pthRct.AddRectangle(rect)
'////////////////////////////////////////////////////////
g = Me.CreateGraphics
g.SmoothingMode = SmoothingMode.AntiAlias
gap /= 2.0R
dbl = gap / CDbl(outerR)
theta = Math.Asin(dbl) * 180.0R / Math.PI
fe = theta
If CDbl(angle) - 2.0R * fe >= 360.0R Then
pthFinal.AddEllipse(pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR)
pthFinal.AddRectangle(rect)
g.FillPath(Brushes.Aqua, pthFinal)
g.DrawPath(Pens.Red, pthRct)
pthRct.Dispose()
pth.Dispose()
g.Dispose()
Return pthFinal
End If
pth.AddArc(pntC.X - outerR, pntC.Y - outerR, 2 * outerR, 2 * outerR, startA + CSng(fe), angle - CSng(2.0R * fe)) 'Outer
dbl = gap / CDbl(innerR)
theta = Math.Asin(dbl) * 180.0R / Math.PI
fe = theta
pth.AddArc(pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR, startA + angle - CSng(fe), -(angle - CSng(2.0R * fe))) 'Inner
'////////////////////////////////////////////////////////////
For i = rect.X To rect.X + wdth
If pth.IsVisible(i, rect.Y) Then
If lst1.Count <> 0 Then
If i <> lst1(lst1.Count - 1) + 1 Then
lstBl(0) = True
position = lst1.Count
End If
End If
lst1.Add(i)
End If
Next
For i = rect.Y To rect.Y + wdth
If pth.IsVisible(rect.X + wdth, i) Then
If lst2.Count <> 0 Then
If i <> lst2(lst2.Count - 1) + 1 Then
lstBl(1) = True
position = lst2.Count
End If
End If
lst2.Add(i)
End If
Next
For i = rect.X To rect.X + wdth
If pth.IsVisible(i, rect.Y + wdth) Then
If lst3.Count <> 0 Then
If i <> lst3(lst3.Count - 1) + 1 Then
lstBl(2) = True
position = lst3.Count
End If
End If
lst3.Add(i)
End If
Next
For i = rect.Y To rect.Y + wdth
If pth.IsVisible(rect.X, i) Then
If lst4.Count <> 0 Then
If i <> lst4(lst4.Count - 1) + 1 Then
lstBl(3) = True
position = lst4.Count
End If
End If
lst4.Add(i)
End If
Next
'If lstBl(0) = True Or lstBl(1) = True Or lstBl(2) = True Or lstBl(3) = True Then
'It is a rare case that i have to work on, when angle is too large
'MsgBox(lstBl(0).ToString + " " + lstBl(1).ToString + " " + lstBl(2).ToString + " " + lstBl(3).ToString + " ")
'Application.Exit()
'End If
'TextBox1.Text = lst1.Count.ToString + " " + lst2.Count.ToString + " " + lst3.Count.ToString + " " + " " + lst4.Count.ToString
pthFinal.AddArc(pntC.X - innerR, pntC.Y - innerR, 2 * innerR, 2 * innerR, startA + angle - CSng(fe), -(angle - CSng(2.0R * fe))) 'Inner
If CDbl(startA) + fe >= 225.0R And CDbl(startA) + fe <= 315.0R Then '1
If lst1.Count <> 0 Then
If lstBl(0) = True Then
pthFinal.AddLine(lst1(position), rect.Y, lst1(lst1.Count - 1), rect.Y)
Else
pthFinal.AddLine(lst1(0), rect.Y, lst1(lst1.Count - 1), rect.Y)
End If
End If
If lst2.Count <> 0 Then
pthFinal.AddLine(lst1(lst1.Count - 1), rect.Y, rect.X + wdth, lst2(lst2.Count - 1))
End If
If lst3.Count <> 0 Then
pthFinal.AddLine(rect.X + wdth, lst2(lst2.Count - 1), lst3(0), rect.Y + wdth)
End If
If lst4.Count <> 0 Then
pthFinal.AddLine(lst3(0), rect.Y + wdth, rect.X, lst4(0))
End If
If lstBl(0) = True Then
pthFinal.AddLine(rect.X, lst4(0), lst1(position - 1), rect.Y)
End If
ElseIf (CDbl(startA) + fe > 315.0R And CDbl(startA) + fe <= 360.0R) Or _
(CDbl(startA) + fe >= 0.0R And CDbl(startA) + fe <= 45.0R) Then '2
If lst2.Count <> 0 Then
If lstBl(1) = True Then
pthFinal.AddLine(rect.X + wdth, lst2(position), rect.X + wdth, lst2(lst2.Count - 1))
Else
pthFinal.AddLine(rect.X + wdth, lst2(0), rect.X + wdth, lst2(lst2.Count - 1))
End If
End If
If lst3.Count <> 0 Then
pthFinal.AddLine(rect.X + wdth, lst2(lst2.Count - 1), lst3(0), rect.Y + wdth)
End If
If lst4.Count <> 0 Then
pthFinal.AddLine(lst3(0), rect.Y + wdth, rect.X, lst4(0))
End If
If lst1.Count <> 0 Then
pthFinal.AddLine(rect.X, lst4(0), lst1(lst1.Count - 1), rect.Y)
End If
If lstBl(1) = True Then
pthFinal.AddLine(lst1(lst1.Count - 1), rect.Y, rect.X + wdth, lst2(position - 1))
End If
ElseIf CDbl(startA) + fe > 45.0R And CDbl(startA) + fe <= 135.0R Then '3
If lst3.Count <> 0 Then
If lstBl(2) = True Then
pthFinal.AddLine(lst3(position - 1), rect.Y + wdth, lst3(0), rect.Y + wdth)
Else
pthFinal.AddLine(lst3(lst3.Count - 1), rect.Y + wdth, lst3(0), rect.Y + wdth)
End If
End If
If lst4.Count <> 0 Then
pthFinal.AddLine(lst3(0), rect.Y + wdth, rect.X, lst3(0))
End If
If lst1.Count <> 0 Then
pthFinal.AddLine(rect.X, lst3(0), lst1(lst1.Count - 1), rect.Y)
End If
If lst2.Count <> 0 Then
pthFinal.AddLine(lst1(lst1.Count - 1), rect.Y, rect.X + wdth, lst2(lst2.Count - 1))
End If
If lstBl(2) = True Then
pthFinal.AddLine(rect.X + wdth, lst2(lst2.Count - 1), lst3(position), rect.Y + wdth)
End If
Else '4
If lst4.Count <> 0 Then
If lstBl(3) = True Then
pthFinal.AddLine(rect.X, lst4(position - 1), rect.X, lst4(0))
Else
pthFinal.AddLine(rect.X, lst4(lst4.Count - 1), rect.X, lst4(0))
End If
End If
If lst1.Count <> 0 Then
pthFinal.AddLine(rect.X, lst4(0), lst1(lst1.Count - 1), rect.Y)
End If
If lst2.Count <> 0 Then
pthFinal.AddLine(lst1(lst1.Count - 1), rect.Y, rect.X + wdth, lst2(lst2.Count - 1))
End If
If lst3.Count <> 0 Then
pthFinal.AddLine(rect.X + wdth, lst2(lst2.Count - 1), lst3(0), rect.Y + wdth)
End If
If lstBl(3) = True Then
pthFinal.AddLine(lst3(0), rect.Y + wdth, rect.X, lst4(position))
End If
End If
'g.FillPath(Brushes.Blue, pth)
g.FillPath(Brushes.Aqua, pthFinal)
g.DrawPath(Pens.Red, pthRct)
pthRct.Dispose()
pth.Dispose()
g.Dispose()
Return pthFinal
End Function
你的价值观: