1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
// Geometric Tools, LLC
// Copyright (c) 1998-2014
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
//
// File Version: 5.0.1 (2010/10/01)
#include "Wm5MathematicsPCH.h"
#include "Wm5ApprEllipseByArcs2.h"
#include "Wm5ContScribeCircle2.h"
namespace Wm5
{
//----------------------------------------------------------------------------
template <typename Real>
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;
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Explicit instantiation.
//----------------------------------------------------------------------------
template WM5_MATHEMATICS_ITEM
void ApproximateEllipseByArcs<float> (float, float, int,
Vector2<float>*&, Vector2<float>*&, float*&);
template WM5_MATHEMATICS_ITEM
void ApproximateEllipseByArcs<double> (double, double, int,
Vector2<double>*&, Vector2<double>*&, double*&);
//----------------------------------------------------------------------------
}
|