//----------------------------------------------------------------------------
void Mgc::ApproximateEllipseByArcs (Real fA, Real fB, int iNumArcs,
    Vector2*& rakPoint, Vector2*& rakCenter, Real*& rafRadius)
{
    // allocate arrays
    assert( iNumArcs >= 2 );
    if ( iNumArcs < 2 )
    {
        rakPoint = NULL;
        rakCenter = NULL;
        rafRadius = NULL;
        return;
    }

    rakPoint = new Vector2[iNumArcs+1];
    rakCenter = new Vector2[iNumArcs];
    rafRadius = new Real[iNumArcs];

    // intermediate ellipse quantities
    Real fA2 = fA*fA, fB2 = fB*fB, fAB = fA*fB, fInvB2mA2 = 1.0f/(fB2-fA2);

    // End points of ellipse in first quadrant.  Points are generated in
    // counterclockwise order.
    rakPoint[0] = Vector2(fA,0.0f);
    rakPoint[iNumArcs] = Vector2(0.0f,fB);

    // curvature at end points, store curvature for computing arcs
    Real fK0 = fA/fB2;
    Real fK1 = fB/fA2;

    // select ellipse points based on curvature properties
    Real fInvNumArcs = 1.0f/iNumArcs;
    int i;
    for (i = 1; i < iNumArcs; i++)
    {
        // curvature at new point is weighted average of curvature at ends
        Real fW1 = i*fInvNumArcs, fW0 = 1.0f - fW1;
        Real fK = fW0*fK0 + fW1*fK1;

        // compute point having this curvature
        Real fTmp = Math::Pow(fAB/fK,0.6666667f);
        rakPoint[i].x = fA*Math::Sqrt(Math::FAbs((fTmp-fA2)*fInvB2mA2));
        rakPoint[i].y = fB*Math::Sqrt(Math::FAbs((fTmp-fB2)*fInvB2mA2));
    }

    // compute arc at (a,0)
    Circle2 kCircle;
    Circumscribe(Vector2(rakPoint[1].x,-rakPoint[1].y),rakPoint[0],
        rakPoint[1],kCircle);
    rakCenter[0] = kCircle.Center();
    rafRadius[0] = kCircle.Radius();

    // compute arc at (0,b)
    int iLast = iNumArcs-1;
    Circumscribe(Vector2(-rakPoint[iLast].x,rakPoint[iLast].y),
        rakPoint[iNumArcs],rakPoint[iLast],kCircle);
    rakCenter[iLast] = kCircle.Center();
    rafRadius[iLast] = kCircle.Radius();

    // compute arcs at intermediate points between (a,0) and (0,b)
    int iM, iP;
    for (iM = 0, i = 1, iP = 2; i < iLast; iM++, i++, iP++)
    {
        Circumscribe(rakPoint[iM],rakPoint[i],rakPoint[iP],kCircle);
        rakCenter[i] = kCircle.Center();
        rafRadius[i] = kCircle.Radius();
    }
}
Пример #2
0
void ApproximateEllipseByArcs (Real a, Real b, int numArcs,
    Vector2<Real>*& points, Vector2<Real>*& centers, Real*& radii)
{
    // Allocate arrays.
    assertion(numArcs >= 2, "Must specify at least two arcs\n");
    if (numArcs < 2)
    {
        points = 0;
        centers = 0;
        radii = 0;
        return;
    }

    points = new1<Vector2<Real> >(numArcs + 1);
    centers = new1<Vector2<Real> >(numArcs);
    radii = new1<Real>(numArcs);

    // Intermediate ellipse quantities.
    Real a2 = a*a, b2 = b*b, ab = a*b;
    Real invB2mA2 = ((Real)1)/(b2 - a2);

    // End points of ellipse in first quadrant.  Points are generated in
    // counterclockwise order.
    points[0] = Vector2<Real>(a, (Real)0);
    points[numArcs] = Vector2<Real>((Real)0, b);

    // Curvature at end points, store curvature for computing arcs.
    Real curv0 = a/b2;
    Real curv1 = b/a2;

    // Select ellipse points based on curvature properties.
    Real invNumArcs = ((Real)1)/numArcs;
    int i;
    for (i = 1; i < numArcs; ++i)
    {
        // Curvature at new point is weighted average of curvature at ends.
        Real weight1 = i*invNumArcs;
        Real weight0 = (Real)1 - weight1;
        Real curv = weight0*curv0 + weight1*curv1;

        // Compute point having this curvature.
        Real tmp = Math<Real>::Pow(ab/curv, (Real)2/(Real)3);
        points[i][0] = a*Math<Real>::Sqrt(
            Math<Real>::FAbs((tmp - a2)*invB2mA2));
        points[i][1] = b*Math<Real>::Sqrt(
            Math<Real>::FAbs((tmp - b2)*invB2mA2));
    }

    // Compute arc at (a,0).
    Circle2<Real> circle;
    Circumscribe<Real>(Vector2<Real>(points[1][0], -points[1][1]),
        points[0], points[1], circle);
    centers[0] = circle.Center;
    radii[0] = circle.Radius;

    // Compute arc at (0,b).
    int last = numArcs - 1;
    Circumscribe(Vector2<Real>(-points[last][0], points[last][1]),
        points[numArcs], points[last], circle);
    centers[last] = circle.Center;
    radii[last] = circle.Radius;

    // Compute arcs at intermediate points between (a,0) and (0,b).
    int iM, iP;
    for (iM = 0, i = 1, iP = 2; i < last; ++iM, ++i, ++iP)
    {
        Circumscribe<Real>(points[iM], points[i], points[iP], circle);
        centers[i] = circle.Center;
        radii[i] = circle.Radius;
    }
}