用径向线画一个圆圈

时间:2014-06-06 18:15:25

标签: vb6 drawing rounding user-experience

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

我使用此算法渲染许多线条控件,使其如下所示:

enter image description here

结果很奇怪:

enter image description here

我认为这是由于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

产生这个:

enter image description here

这更接近我的预期......遗憾的是,我仍然不知道如何实现抗锯齿,但这样做会有所帮助。 (目前,至少):))

3 个答案:

答案 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