有谁知道一些算法来计算使用多边形逼近圆所需的边数,如果给出了圆的半径、r 和多边形与圆度的最大偏离,D?我真的需要找到边数,因为我需要在 OpenGL 中绘制近似圆。
另外,我们得到了屏幕的分辨率,单位为 NDC 坐标,由 P 给出,求解 D = P/2,我们可以保证我们的圆在半个像素的精度范围内。
有谁知道一些算法来计算使用多边形逼近圆所需的边数,如果给出了圆的半径、r 和多边形与圆度的最大偏离,D?我真的需要找到边数,因为我需要在 OpenGL 中绘制近似圆。
另外,我们得到了屏幕的分辨率,单位为 NDC 坐标,由 P 给出,求解 D = P/2,我们可以保证我们的圆在半个像素的精度范围内。
您在这里描述的实际上是一个质量因素,它通常与误差估计密切相关。
我们处理这个问题的一种常见方法是计算圆周的一小部分的误差。最简单的方法是确定圆切片的弧长与连接圆周上相同两点的线段相比的差异。您可以使用更有效的措施,例如面积差异、半径等,但这种方法应该足够了。
想象一个八边形,外接一个完美的圆。在这种情况下,误差是八边形上两个相邻点之间的直线长度差,以及连接这两个点的圆的弧长。
弧长很容易计算:PI * r * theta
,r
您的半径在哪里,并且theta
是两点之间的角度(以弧度为单位),假设您从这些点中的每一个绘制线到圆/多边形的中心。对于有边的封闭多边形n
,角度只是(2*PI/n)
弧度。令该值对应的弧长n
等于A
,即A=2*PI*r/n
。
两点之间的线长很容易计算。只需将您的圆圈分成n
等腰三角形,然后将每个三角形分成两个直角三角形。你知道每个直角三角形的角是theta/2 = (2*PI/n)/2 = (PI/n)
,斜边是r
。所以,你得到你的方程sin(PI/n)=x/r
,其中x
是连接外接多边形上两个相邻点的线段长度的一半。让这个值是B
(即:B=2x
,所以B=2*r*sin(PI/n)
)。
现在,只需计算相对误差E = |A-B| / A
(即:|TrueValue-ApproxValue|/|TrueValue|
您可以使用上述方程式设置约束E
(即:它不能大于某个值,例如 1.05),以使其“看起来不错”。
因此,您可以编写一个函数来计算A
、B
和E
从上述方程,并遍历 的值n
,并在计算的值E
小于您的阈值时让它停止循环。
我有一个使用固定函数opengl画圆的算法,也许它会有所帮助?
当您说要“使用多边形近似圆”时,很难知道您的意思
您会在下面的算法中注意到,我没有计算绘制圆所需的线数,我只是在 0 .. 2Pi 之间迭代,每次将角度步进 0.1,用 glVertex2f 绘制一条线到该点圆圈,从上一点开始。
void Circle::Render()
{
glLoadIdentity();
glPushMatrix();
glBegin(GL_LINES);
glColor3f(_vColour._x, _vColour._y, _vColour._z);
glVertex3f(_State._position._x, _State._position._y, 0);
glVertex3f(
(_State._position._x + (sinf(_State._angle)*_rRadius)),
(_State._position._y + (cosf(_State._angle)*_rRadius)),
0
);
glEnd();
glTranslatef(_State._position._x, _State._position._y, 0);
glBegin(GL_LINE_LOOP);
glColor3f(_vColour._x, _vColour._y, _vColour._z);
for(float angle = 0.0f; angle < g_k2Pi; angle += 0.1f)
glVertex2f(sinf(angle)*_rRadius, cosf(angle)*_rRadius);
glEnd();
glPopMatrix();
}
我会说你需要根据半径和缩放两个变量来设置边数(如果你允许缩放)
一个圆或半径为 20 像素的圆在 32 到 56 条边上看起来不错,但如果您对 200 像素的无线电使用相同的边数,那么边数就不够了
numberOfSides = radius * 3
如果你允许放大和缩小,你需要做这样的事情
numberOfSides = radiusOfPaintedCircle * 3
当您放大 radiusOfPaintedCircle 将大于正在绘制的圆的“属性”