标题:求助:Circle 方法画出来的圆,其圆弧上的坐标点怎么计算?
只看楼主
William1949
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:109
专家分:0
注 册:2009-3-17
结帖率:70%
已结贴  问题点数:100 回复次数:11 
求助:Circle 方法画出来的圆,其圆弧上的坐标点怎么计算?
用 Circle 画一个半圆,颜色为黑色。
Picture1.Circle (90, 100), 80, vbBlack, 0, 3.14


然后,计算圆弧上的每个坐标点,再用:
Picture1.PSet (X1, Y1), vbRed
设置该点的像素颜色为红色。

理论上,图像上应该不会显示出黑色的圆弧(都被红色覆盖了),要是计算精确的话,红色也不会画在其它地方,只能画在原黑色轨迹上。

请问,我应该如何精确计算,使坐标点完全重合原先的黑色圆弧,(数学水平太差了,三角函数把我搞蒙了)

程序代码:
Private Sub Command1_Click()
'错误的计算过程
    Dim iColor      As Long, P          As Long, X1         As Long, Y1     As Long, Radius        As Long
    Dim CentrX      As Long, CentrY     As Long
    Dim Pi          As Double, Si       As Double, Co       As Double
    Dim Radian      As Double, Angle    As Double, ArcLen   As Double, Angle2 As Double
    
    Pi = 3.1415926
    With Picture1
        .Cls
        .BackColor = vbWhite
        .ScaleMode = vbPixels
    End With
    Radius = 80
    Angle = 180
    
    CentrX = 90
    CentrY = 100
    Picture1.Circle (CentrX, CentrY), Radius, vbBlack, 0, 3.14
    
    ArcLen = Angle * Pi * Radius / 180
    Angle2 = (180 * 1) / (Pi * Radius)
    ArcLen = Angle * Pi * Radius / 180
    For P = 0 To Int(ArcLen)
        Radian = (P * Angle2) * (Pi / 180)
        Si = Sin(Radian)
        Co = Cos(Radian)
        X1 = CentrX - Radius * Co
        Y1 = CentrY - Radius * Si
        If Picture1.Point(X1, Y1) = vbBlack Then iColor = vbRed Else iColor = vbGreen
        Picture1.PSet (X1, Y1), iColor
    Next
End Sub





[此贴子已经被作者于2022-9-8 16:39编辑过]

搜索更多相关主题的帖子: 坐标 计算 Long Dim Double 
2022-09-08 16:37
yuma
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:银河系
等 级:贵宾
威 望:33
帖 子:1883
专家分:2904
注 册:2009-12-22
得分:20 
以下内容来自来MSDN手册,以下为原文复制粘帖:


画圆


Circle 方法可画出圆形和椭圆形的各种形状。另外,Circle 方法还可以画出圆弧(圆的一部分)和楔形饼块。使用变化的 Circle 方法,可画出多种曲线。

为了画圆,Visual Basic 需要给出该圆的圆心位置和它的半径。画一个理想圆的语法是:

[object.]Circle [Step](x, y), radius[, color]

方括号表明 object 和 Step 关键字是任选项。如果不指定 object,则认为指定的就是当前的窗体。x 参数和 y 参数是圆心的坐标,radius 参数是圆的半径。例如,下面语句将画出一个以 (1200,1000) 为圆心、750 为半径的圆:

Circle (1200, 1000), 750

这个语句产生的精确作用,还要依赖于窗体的大小和窗体的坐标系。如果不知道窗体的大小,也就不能知道这个圆是否可见。可使用绘图区的标尺属性,将该圆的圆心置于窗体的中心处:

Circle ((ScaleWidth + ScaleLeft) / 2, (ScaleHeight + _
   ScaleTop) / 2), ScaleWidth / 4

此时,关于 ScaleWidth 和 ScaleHeight 所有应知道的是,它们能帮助将图形定位于窗体的中心。

详细信息 在本章前面“改变对象的坐标系统”中详细讨论了 ScaleWidth 和 ScaleHeight 属性。

注意 圆的半径通常是按照水平单位来指定的。如果坐标系使用的水平单位和垂直单位是相同的话(按照缺省规定,应当这样),可以不用考虑单位问题。但如果使用的是自定义标尺,则水平单位和垂直单位可能对应不同的长度。上例中,半径是用水平单位来指定的,可以保证圆的实际高度和实际宽度相等。

Blanker 应用程序创建了一些圆圈,作为多彩地毯演示程序的一部分。该演示程序围绕窗体中心画出一系列虚线圆。这些圆看起来正好象一个编织成的圆形地毯。CircleDemo 过程使用下列语句,在多彩地毯演示程序中画圆:

Sub CircleDemo ()
   Dim Radius
'将红色设置为随机数。
   R = 255 * Rnd
'将绿色设置为随机数。
   G = 255 * Rnd
'将蓝色设置为随机数。
   B = 255 * Rnd
'将 x 坐标设置在窗体中间。
   XPos = ScaleWidth / 2
'将 y 坐标设置在窗体中间。
   YPos = ScaleHeight / 2
   '将半径设置在窗体高度的 0 到 50% 之间。
   Radius = ((YPos * 0.9) + 1) * Rnd
   '用随机颜色画圆。
   Circle (XPos, YPos), Radius, RGB(R, G, B)
End Sub

多彩地毯演示程序的结果,显示在图 12.16 中。

图 12.16 Blanker 应用程序里的多彩地毯演示程序



画圆弧
为了用 Circle 方法画出圆弧,应以弧度为单位,给出定义弧线 start 和 end 的角度参数。画圆弧的语法是:

[object.]Circle [Step](x, y), radius, [color], start, end[, aspect]

如果 start 参数或 end 参数是负数的话,Visual Basic 将画一条连接圆心到负端点的线。例如,下面的过程将用消除切片方式画出一个饼。

Private Sub Form_Click ()
   Const PI = 3.14159265
   Circle (3500, 1500), 1000, , –PI / 2, –PI / 3
End Sub

注意 将度换算成弧度的公式是将度数乘以 Pi/180。

心生万象,万象皆程序!
本人计算机知识网:http://bbs.为防伸手党,本站已停止会员注册。
2022-09-08 16:47
独木星空
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:20 
回复 2楼 yuma
真能把问题从网上搜集出来,并粘贴到这里,也是对问题成熟化的表现。对于一个完全不理解问题的人来说,也是一个大难题(想从网上找到答案的人)。

素数问题的解决是我学习编程永恒的动力。
2022-09-08 22:05
yuma
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:银河系
等 级:贵宾
威 望:33
帖 子:1883
专家分:2904
注 册:2009-12-22
得分:0 
看我代码,怎么不存在你那种问题,红圆完美覆盖黑圆。

程序代码:
Private Sub Form_Load()
Me.Show
Circle (1200, 1000), 750, vbBlack
Circle (1200, 1000), 750, vbRed
End Sub


放大800倍也没有你那种问题。




[此贴子已经被作者于2022-9-8 22:54编辑过]


心生万象,万象皆程序!
本人计算机知识网:http://bbs.为防伸手党,本站已停止会员注册。
2022-09-08 22:07
William1949
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:109
专家分:0
注 册:2009-3-17
得分:0 
老弟 你可真行!

要是你这么回答,那我只能把标题改改了。
原标题是:“... ... 圆弧上的坐标点怎么计算?”
改成:“怎么用 2 个 Circle 画2个圆,并使2个圆完全重合?”


假设一下,vb 没有提供 Circle 方法,api也没有画圆的函数,那你该怎么画出一个圆?
只给你提供:中心点坐标 和 半径。
难道你不用计算?不用三角函数?,不用诸如 Sin、Cos ...之类的函数?

你2楼的内容 通篇 读下来,只是 Circle 方法 的用法而已。

我真正想要的计算出来的 X,Y 坐标。


*********************************************
为了验证计算过程是否正确,我想了一办法:
把计算出来的 X,Y 坐标对应的像素,改成红色,并使一个一个像素都连起来 形成一个圆,然后与 Circle 方法画出的圆(1楼最上面的图)进行比对。

要是全红,说明计算是正确的。

事实上,我画出来的有误差,(1楼的图2)
有的地方是黑色,说明我没有覆盖到,
有的地方是绿色,说明我画偏了,

说白了,就是把 Circle 方法画出的圆 当做参照物。
而你却给了两个 Circle (1200, 1000), 750

真想坐地上大哭一场
2022-09-09 10:37
William1949
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:109
专家分:0
注 册:2009-3-17
得分:0 
或者 我这么问:
依照你发的图:



我测量圆周上某一坐标点,X = 117,Y = 33

请问:为什么是117,33,而不是116,32,也不是118,34
117,33,是怎么计算出来的?
2022-09-09 11:00
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:20 
楼主是要自己用pset逐点画圆,有两种方法:
1,步进法:当年我们学单片机时写数控机床代码就用这种方法,该方法是使用圆的公式x^2+y^2=r^2,假设圆的周长是10,原点坐标0,0,首先可以确定圆上一个起始点坐标假设是在x轴正半轴上,那这点坐标就是(10,0),以这点为起始点,判断下一个点的位置,无非是(11,0)(10,1)(9,0)(10,-1)(11,1)(11,-1)(9,1)(9,-1),把这8个点坐标代入圆的方程,选择误差最小的那个坐标作为下一点坐标,由于在坐标轴上的起始点下一个点误差最小的有两个点,这里程序需要特殊处理下,还有个技巧是圆上各点都是针对坐标原点对称,可以只需要画出1/4的圆弧就可以得到整个圆。
2,转角法:这个方法适合画指定长度的圆弧,缺点是步进角度选择不合适,容易断点,步进角度过密,运行效率又偏低。该方法可理解为假想一个长度为r的棍子,一端定在坐标原点上进行0-360度转动,这时步进的就是角度,根据角度和半径可计算另一端坐标位置,公式是:x=r*cos(∠),y=r*sin(∠)(假定原点坐标为0,0),vb代码大致如下:
dim x0 as double,y0 as double,x as double,y as double,i as double
x0=100
y0=100  '原点坐标位置100,100
for i=0 to 360 step 0.001
  x=x0+r*cos(i*3.14/180)
  y=y0+r*sin(i*3.14/180)
  pset (x,y),vbred
next

能编个毛线衣吗?
2022-09-09 11:31
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4912
专家分:29900
注 册:2008-10-15
得分:20 
问题出在 Circle 画的圆与我们自己计算出来的坐标有偏差

我使用勾股定理画很小圆也出现这个问题,不圆,有毛刺。四舍五入的问题。
解决办法,
画圆,不要使用 Circle 命令,而使用 7楼的给出的代码自己画
也许自己画的不是正圆,但再到圆上描点是一合一的。

或者你使用的你自己计算画点的方式,先画一个圆。然后再用同样的算法描点。
---------------
我自己内存使用用的勾股定理是类似步进法,但我不比较坐标差值,直接四舍五入了,同时画四个象限
从X轴步进,Y轴就是 round(SQR(R*R-X*X),0)
for x=0 to r
Y=round(SQR(R*R-X*X),0)
pset (x,y),颜色
pset (x,-y),颜色
pset (-x,y),颜色
pset (-x,-y),颜色
next x




授人于鱼,不如授人于渔
早已停用QQ了
2022-09-09 18:13
William1949
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:109
专家分:0
注 册:2009-3-17
得分:0 
方法2:貌似 和我一楼用的方法差不多,有所区别的地方是:我是以 弧长 作为循环周期  For P = 0 To Int(ArcLen) ,然后以一个像素的大小来计算弧度。
而你的是以 角度作为循环周期 for i=0 to 360 step 0.001,步长 0.001,
我测试方法2 发现 步长 越密,与 Circle 圆的重合度越好。改成0.1 效果就变差了。
此方法可借鉴一下,诚谢。


方法1:感觉好像看懂了,我可以把那 8 个点 到 圆心的距离统计出来,与半径相等的那个点,应该是最理想的点。不过要是研究此方法,就得另起炉灶了。抽时间在深度学习。

感谢!感谢!




2022-09-09 18:45
William1949
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:109
专家分:0
注 册:2009-3-17
得分:0 
终于完工了。

程序代码:
Private Type POINTAPI
    X       As Long
    Y       As Long
End Type

Private Sub CircleGradient(ByVal X As Long, ByVal Y As Long, ByVal Radius As Long, ByVal InnerRadius As Long, ByVal Angle As Long, ByVal StartAngle As Long, ByVal ColorStart As Long, ByVal ColorEnd As Long)
    Dim iR      As Long, P          As Long, i          As Long
    Dim Pi      As Double, Radian   As Double
    Dim sP      As Single
    Dim Po      As POINTAPI, oldPo  As POINTAPI, RePo() As POINTAPI
    Dim iColor() As Long
    
    Pi = 3.1415926
    ReDim RePo((Radius * 2 * Pi) * 2 - 1) As POINTAPI
    For iR = Radius To InnerRadius Step -1
        i = 0
        oldPo.X = X
        oldPo.Y = Y
        For sP = StartAngle To (StartAngle + Angle) Step 0.05 '0.01
            Radian = sP * (Pi / 180)
            Po.X = X - iR * Cos(Radian)
            Po.Y = Y - iR * Sin(Radian)
            If Po.X <> oldPo.X Or Po.Y <> oldPo.Y Then
                RePo(i) = Po
                i = i + 1
                oldPo = Po
            End If
        Next
        Call GetGradientColors(ColorStart, ColorEnd, i, iColor())
        For P = 0 To i - 1
            With RePo(P)
                Picture1.PSet (.X, .Y), iColor(P)
            End With
        Next
    Next
    Erase iColor(), RePo()
End Sub

Private Sub GetGradientColors(ByVal Color1 As Long, ByVal Color2 As Long, ByVal Step As Long, ByRef gColor() As Long)
    Dim UB      As Long, P          As Long
    Dim iRed    As Byte, iGreen     As Byte, iBlue  As Byte
    Dim aRGB1() As Byte, aRGB2()    As Byte
    Dim Sc      As Single, ScB      As Single
    
    Call GetRGB(Color1, aRGB1())
    Call GetRGB(Color2, aRGB2())
    
    UB = Step - 1
    ReDim gColor(UB) As Long
    For P = 0 To UB
        Sc = P / UB
        ScB = 1 - Sc
        iRed = aRGB2(0) * Sc + ScB * aRGB1(0)
        iGreen = aRGB2(1) * Sc + ScB * aRGB1(1)
        iBlue = aRGB2(2) * Sc + ScB * aRGB1(2)
        gColor(P) = (iBlue * &H10000 + iGreen * &H100& + iRed)
    Next
    Erase aRGB1(), aRGB2()
End Sub

Private Sub GetRGB(ByVal Color As Long, ByRef RGB() As Byte)
    ReDim RGB(2) As Byte
    RGB(0) = Color And &HFF                  'Red
    RGB(1) = (Color And &HFF00&) / &H100&    'Green
    RGB(2) = (Color And &HFF0000) / &H10000  'Blue
End Sub


接下来,再画几条刻度线,再画一个指针。就算齐活了
2022-09-15 14:22



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-509977-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.153513 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved