for i = 0 to 23
'' ...
'' create 'line' control
'' ...
line.x1 = (inner_radius*cos(15 * i)) + centerx
line.y1 = (inner_radius*sin(15 * i)) + centery
line.x2 = (outer_radius*cos(15 * i)) + centerx
line.y2 = (outer_radius*sin(15 * i)) + centery
next
我使用此算法渲染许多线条控件,使其如下所示:
结果很奇怪:
我认为这是由于cos()和sin()函数的舍入而发生的,所以我的问题是,是否有一些算法可以应用于修复舍入?或者有更好的方法来渲染这样的控件吗?
修改
Hrqls指出的问题是我使用的是度数而不是弧度...这是我最终使用的函数:
Sub ProgressAnim(ByVal centerx, _
ByVal centery, _
ByVal outer_radius, _
ByVal inner_radius, _
ByVal step_count, _
ByVal line_width)
Dim pi
Dim degstep
Dim scan
Dim newcontrol As Line
Dim controlid
pi = 4 * Atn(1)
degstep = pi / (step_count / 2)
For scan = 0 To step_count - 1
controlid = "line" & (scan + 1)
Set newcontrol = Me.Controls.Add("vb.line", controlid)
newcontrol.X1 = centerx + (inner_radius * Cos(degstep * scan))
newcontrol.Y1 = centery + (inner_radius * Sin(degstep * scan))
newcontrol.X2 = centerx + (outer_radius * Cos(degstep * scan))
newcontrol.Y2 = centery + (outer_radius * Sin(degstep * scan))
newcontrol.BorderStyle = 1
newcontrol.BorderWidth = line_width
newcontrol.Visible = True
Next
End Sub
像这样调用
ProgressAnim 150, 250, 16, 9, 18, 1
产生这个:
这更接近我的预期......遗憾的是,我仍然不知道如何实现抗锯齿,但这样做会有所帮助。 (目前,至少):))
答案 0 :(得分:0)
将for i = 0 to 23
更改为for i = 0 to 21
和(15 * i)
与(0.3 * i)
使用timer1:
在form1中尝试该代码Dim c As Integer, centerx As Integer, centery As Integer, inner_radius As Integer, outer_radius As Integer
Dim x1 As Single, y1 As Single, x2 As Single, y2 As Single
Private Sub Form_Load()
c = 0
centerx = Form1.Width / 2
centery = Form1.Height / 2
inner_radius = 1200
outer_radius = 1
Timer1.Interval = 200
End Sub
Private Sub Timer1_Timer()
x1 = (inner_radius * Cos(0.3 * c)) + centerx
y1 = (inner_radius * Sin(0.3 * c)) + centery
x2 = (outer_radius * Cos(0.3 * c)) + centerx
y2 = (outer_radius * Sin(0.3 * c)) + centery
Line (x1, y1)-(x2, y2), RGB(0, 0, 0)
c = c + 1
If c = 21 Then Timer1.Enabled = False
End Sub
检查此示例中的数字以查看绘图行为。
答案 1 :(得分:0)
你的问题是你以度为单位计算角度,而VB使用弧度作为角度
查看以下项目:
Option Explicit
Private Sub Form_Click()
DrawWheel
End Sub
Private Sub DrawWheel()
Dim intI As Integer
Dim sngRadius As Single
Dim sngRadiusY As Single
Dim sngCenterX As Single, sngCenterY As Single
Dim sngX1 As Single, sngY1 As Single
Dim sngX2 As Single, sngY2 As Single
Dim sngStep As Single
Dim sngAngle As Single
Dim sngCos As Single, sngSin As Single
'calculate form sizes
sngRadius = (ScaleWidth - 240) / 2
sngRadiusY = (ScaleHeight - 240) / 2
sngCenterX = 120 + sngRadius
sngCenterY = 120 + sngRadiusY
If sngRadiusY < sngRadius Then sngRadius = sngRadiusY
'draw circle
Circle (sngCenterX, sngCenterY), sngRadius
'calculate step between lines
sngStep = Atn(1) / 3
'draw lines
For intI = 0 To 23
'calculate angle for each line
sngAngle = sngStep * intI
'calculate coordinates for each line
sngCos = Cos(sngAngle)
sngSin = Sin(sngAngle)
sngX1 = sngCenterX + sngCos * sngRadius / 10
sngY1 = sngCenterY + sngSin * sngRadius / 10
sngX2 = sngCenterX + sngCos * sngRadius
sngY2 = sngCenterY + sngSin * sngRadius
'draw each lines
Line (sngX1, sngY1)-(sngX2, sngY2)
'print sequence number
Print CStr(intI)
Next intI
End Sub
单击表单以绘制滚轮
Atn(1)是PI / 4 ...对于24行,你需要将2 * PI除以24 ..因此你需要将PI除以12 ...这使你将Atn(1)除以3 < / p>
答案 2 :(得分:0)
我会确保通过使用2PI的适当分数来保持最高的准确度。
摆弄常数直到你得到你想要的东西:
Option Explicit
Private Sub Form_Load()
Timer.Interval = 50
End Sub
Private Sub Timer_Timer()
DrawRadialLines
End Sub
Private Sub DrawRadialLines()
Const ksngPI As Single = 3.14159!
Const ksngCircle As Single = 2! * ksngPI
Const ksngInnerRadius As Single = 130!
Const ksngOuterRadius As Single = 260!
Const ksngCenterX As Single = 1200!
Const ksngCenterY As Single = 1200!
Const klSegmentCount As Long = 12
Const klLineWidth As Long = 3
Static s_lActiveSegment As Integer ' The "selected" segment.
Dim lSegment As Long
Dim sngRadians As Single
Dim sngX1 As Single
Dim sngY1 As Single
Dim sngX2 As Single
Dim sngY2 As Single
Dim cLineColour As OLE_COLOR
Me.DrawWidth = klLineWidth
' Overdraw previous graphic.
Me.Line (ksngCenterX - ksngOuterRadius - Screen.TwipsPerPixelX * 2, ksngCenterY - ksngOuterRadius - Screen.TwipsPerPixelY * 2)-(ksngCenterX + ksngOuterRadius + Screen.TwipsPerPixelX * 2, ksngCenterY + ksngOuterRadius + Screen.TwipsPerPixelY * 2), Me.BackColor, BF
For lSegment = 0 To klSegmentCount - 1
'
' Work out the coordinates for the line to be draw from the outside circle to the inside circle.
'
sngRadians = (ksngCircle * CSng(lSegment)) / klSegmentCount
sngX1 = (ksngOuterRadius * Cos(sngRadians)) + ksngCenterX
sngY1 = (ksngOuterRadius * Sin(sngRadians)) + ksngCenterY
sngX2 = (ksngInnerRadius * Cos(sngRadians)) + ksngCenterX
sngY2 = (ksngInnerRadius * Sin(sngRadians)) + ksngCenterY
' Work out how many segments away from the "current segment" we are.
' The current segment should be the darkest, and the further away from this segment we are, the lighter the colour should be.
Select Case Abs(Abs(s_lActiveSegment - lSegment) - klSegmentCount \ 2)
Case 0!
cLineColour = RGB(0, 0, 255)
Case 1!
cLineColour = RGB(63, 63, 255)
Case 2!
cLineColour = RGB(117, 117, 255)
Case Else
cLineColour = RGB(181, 181, 255)
End Select
Me.Line (sngX1, sngY1)-(sngX2, sngY2), cLineColour
Next lSegment
' Move the current segment on by one.
s_lActiveSegment = (s_lActiveSegment + 1) Mod klSegmentCount
End Sub