/** @file
* @brief Fitting elliptical arc to SBasis
*
* This file contains the implementation of the function arc_from_sbasis.
*//*
* Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
*
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*/
#include <algorithm>
namespace Geom {
// forward declation
namespace detail
{
struct ellipse_equation;
}
/*
* make_elliptical_arc
*
* convert a parametric polynomial curve given in symmetric power basis form
* into an EllipticalArc type; in order to be successfull the input curve
* has to look like an actual elliptical arc even if a certain tolerance
* is allowed through an ad-hoc parameter.
* The conversion is performed through an interpolation on a certain amount of
* sample points computed on the input curve;
* the interpolation computes the coefficients of the general implicit equation
* of an ellipse (A*X^2 + B*XY + C*Y^2 + D*X + E*Y + F = 0), then from the
* implicit equation we compute the parametric form.
*
*/
class make_elliptical_arc
{
public:
/*
* constructor
*
* it doesn't execute the conversion but set the input and output parameters
*
* _ea: the output EllipticalArc that will be generated;
* _curve: the input curve to be converted;
* _total_samples: the amount of sample points to be taken
* on the input curve for performing the conversion
* _tolerance: how much likelihood is required between the input curve
* and the generated elliptical arc; the smaller it is the
* the tolerance the higher it is the likelihood.
*/
curve_type const& _curve,
unsigned int _total_samples,
double _tolerance );
private:
bool check_bound(double A, double B, double C, double D, double E, double F);
void fit();
bool make_elliptiarc();
void print_bound_error(unsigned int k)
{
<< "angle error: " << angle_err
}
public:
/*
* perform the actual conversion
* return true if the conversion is successfull, false on the contrary
*/
bool operator()()
{
// initialize the reference
fit();
return false;
if ( !(make_elliptiarc()) ) return false;
return true;
}
private:
// perform the actual fitting task
// tolerance: the user-defined tolerance parameter;
// tol_at_extr: the tolerance at end-points automatically computed
// on the value of "tolerance", and usually more strict;
// tol_at_center: tolerance at the center of the ellipse
// angle_tol: tolerance for the angle btw the input curve tangent
// versor and the ellipse normal versor at the sample points
unsigned int N; // total samples
};
namespace detail
{
/*
* ellipse_equation
*
* this is an helper struct, it provides two routines:
* the first one evaluates the implicit form of an ellipse on a given point
* the second one computes the normal versor at a given point of an ellipse
* in implicit form
*/
struct ellipse_equation
{
ellipse_equation(double a, double b, double c, double d, double e, double f)
: A(a), B(b), C(c), D(d), E(e), F(f)
{
}
double operator()(double x, double y) const
{
// A * x * x + B * x * y + C * y * y + D * x + E * y + F;
return (A * x + B * y + D) * x + (C * y + E) * y + F;
}
double operator()(Point const& p) const
{
return (*this)(p[X], p[Y]);
}
{
return unit_vector(n);
}
{
return normal(p[X], p[Y]);
}
double A, B, C, D, E, F;
};
} // end namespace detail
curve_type const& _curve,
unsigned int _total_samples,
double _tolerance )
{
}
/*
* check that the coefficients computed by the fit method satisfy
* the tolerance parameters at the k-th sample point
*/
bool
{
// check that the angle btw the tangent versor to the input curve
// and the normal versor of the elliptical arc, both evaluate
// at the k-th sample point, are really othogonal
//angle_err *= angle_err;
}
/*
* check that the coefficients computed by the fit method satisfy
* the tolerance parameters at each sample point
*/
bool
check_bound(double A, double B, double C, double D, double E, double F)
{
// check error magnitude at the end-points
{
return false;
}
{
return false;
}
// e1x = derivative((ee(x,y), x) | x->tolerance, y->tolerance
// e1y = derivative((ee(x,y), y) | x->tolerance, y->tolerance
// e2 = ee(tolerance, tolerance) - F;
// std::cerr << "e1x = " << e1x << std::endl;
// std::cerr << "e1y = " << e1y << std::endl;
// std::cerr << "e2 = " << e2 << std::endl;
// check error magnitude at sample points
for ( unsigned int k = 1; k < last; ++k )
{
{
return false;
}
}
return true;
}
/*
* fit
*
* supply the samples to the fitter and compute
* the ellipse implicit equation coefficients
*/
{
for (unsigned int k = 0; k < N; ++k)
{
p[k] = curve( k / partitions );
}
}
{
Ellipse e;
try
{
}
catch(LogicalError const &exc)
{
return false;
}
#ifdef CPP11
#else
#endif
)
)
{
return false;
}
return true;
}
double tolerance, unsigned num_samples)
{
return convert();
}
} // end namespace Geom
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :