用给定数量的段近似圆

时间:2011-07-12 19:02:33

标签: c++ algorithm geometry

有没有更好的方法从半径和顶点数计算圆? 我的解决方案为每个顶点计算sincos。有必要吗?

void getCircle2D(Vector2 * perimeterPointsArray, int32 numOfPoints, Vector2 & center, flt32 radius)
{
    ASSERT(numOfPoints >= 3);
    flt32 pieceAngle = MathConst::TAU / numOfPoints;
    flt32 iterAngle = 0;
    for (int32 i = 0; i < numOfPoints; ++i)
    {
        perimeterPointsArray[i] = Vector2(radius * cos(iterAngle) + center.x, radius * sin(iterAngle) + center.y);
        iterAngle += pieceAngle;
    }
}

3 个答案:

答案 0 :(得分:1)

你不需要罪和cos:

Midpoint circle algorithm。这是像素图形,但应该很容易修改它来创建验证。当然,只有顶点数量与像素数量相当(比一个数量级更小)才有意义。

答案 1 :(得分:1)

您可以计算一半的点,然后在X中心周围镜像。

答案 2 :(得分:1)

您建议的方法应该是通常的方法。但也许您可以使用以下加法定理进行迭代计算(参见Wikipedia):

sin(a+b) = sin(a)*cos(b) + cos(a)*sin(b)
cos(a+b) = cos(a)*cos(b) - sin(a)*sin(b)

在你的情况下a是前一个角度(你刚刚计算出它的cos和sin)而b是恒定角度步(当然cos和sin也是常数)。所以这样的事情可以起作用:

void getCircle2D(Vector2 * perimeterPointsArray, int32 numOfPoints, Vector2 & center, flt32 radius)
{
    flt32 pieceAngle = MathConst::TAU / numOfPoints;
    flt32 sinb = sin(pieceAngle), cosb = cos(pieceAngle);
    flt32 sina = 0.0, cosa = 1.0;
    for (int32 i = 0; i < numOfPoints; ++i)
    {
        perimeterPointsArray[i] = Vector2(radius * cosa + center.x, radius * sina + center.y);
        flt32 tmp = sina * cosb + cosa * sinb;
        cosa = cosa * cosb - sina * sinb;
        sina = tmp;
    }
}

在这里你只需计算一个sin和一个cos(如果在编译时知道点数,甚至可以预先计算)。

@yi_H我不知道圆光栅化算法是否真的适合浮点圆近似,但也许在浮点上它可以推广到上面提到的迭代计算。