summaryrefslogtreecommitdiffstats
path: root/src/2geom/elliptical-arc-from-sbasis.cpp
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2015-05-22 08:23:27 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2015-05-22 08:23:27 +0000
commit25fa09178b7d0d0befa708e93ea5316ef381caa0 (patch)
tree550b4d0d66d0d234b3f49e868cb747987dcc6bf8 /src/2geom/elliptical-arc-from-sbasis.cpp
parentMerge from trunk (diff)
downloadinkscape-25fa09178b7d0d0befa708e93ea5316ef381caa0.tar.gz
inkscape-25fa09178b7d0d0befa708e93ea5316ef381caa0.zip
Update to 2Geom revision 2396
(bzr r14059.2.16)
Diffstat (limited to '')
-rw-r--r--src/2geom/elliptical-arc-from-sbasis.cpp (renamed from src/2geom/svg-elliptical-arc.cpp)172
1 files changed, 121 insertions, 51 deletions
diff --git a/src/2geom/svg-elliptical-arc.cpp b/src/2geom/elliptical-arc-from-sbasis.cpp
index 3a5154d08..54f995fb6 100644
--- a/src/2geom/svg-elliptical-arc.cpp
+++ b/src/2geom/elliptical-arc-from-sbasis.cpp
@@ -1,6 +1,8 @@
-/*
- * SVG Elliptical Arc Class
+/** @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>
*
* This library is free software; you can redistribute it and/or
@@ -27,33 +29,120 @@
* the specific language governing rights and limitations.
*/
-
+#include <2geom/curve.h>
+#include <2geom/angle.h>
+#include <2geom/utils.h>
#include <2geom/bezier-curve.h>
-#include <2geom/ellipse.h>
-#include <2geom/numeric/fitting-model.h>
-#include <2geom/numeric/fitting-tool.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/sbasis-curve.h> // for non-native methods
#include <2geom/numeric/vector.h>
-#include <2geom/poly.h>
-#include <2geom/sbasis-geometric.h>
-#include <2geom/svg-elliptical-arc.h>
-
-#include <cfloat>
-#include <limits>
-#include <memory>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+#include <algorithm>
+namespace Geom {
-namespace Geom
+// forward declation
+namespace detail
{
+ struct ellipse_equation;
+}
-/**
- * @class SVGEllipticalArc
- * @brief SVG 1.1-compliant elliptical arc.
+/*
+ * make_elliptical_arc
*
- * This class is almost identical to the normal elliptical arc, but it differs slightly
- * in the handling of degenerate arcs to be compliant with SVG 1.1 implementation guidelines.
+ * 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.
*
- * @ingroup Curves
*/
+class make_elliptical_arc
+{
+ public:
+ typedef D2<SBasis> curve_type;
+
+ /*
+ * 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.
+ */
+ make_elliptical_arc( EllipticalArc& _ea,
+ curve_type const& _curve,
+ unsigned int _total_samples,
+ double _tolerance );
+
+ private:
+ bool bound_exceeded( unsigned int k, detail::ellipse_equation const & ee,
+ double e1x, double e1y, double e2 );
+
+ 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)
+ {
+ std::cerr
+ << "tolerance error" << std::endl
+ << "at point: " << k << std::endl
+ << "error value: "<< dist_err << std::endl
+ << "bound: " << dist_bound << std::endl
+ << "angle error: " << angle_err
+ << " (" << angle_tol << ")" << std::endl;
+ }
+
+ public:
+ /*
+ * perform the actual conversion
+ * return true if the conversion is successfull, false on the contrary
+ */
+ bool operator()()
+ {
+ // initialize the reference
+ const NL::Vector & coeff = fitter.result();
+ fit();
+ if ( !check_bound(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]) )
+ return false;
+ if ( !(make_elliptiarc()) ) return false;
+ return true;
+ }
+
+ private:
+ EllipticalArc& ea; // output elliptical arc
+ const curve_type & curve; // input curve
+ Piecewise<D2<SBasis> > dcurve; // derivative of the input curve
+ NL::LFMEllipse model; // model used for fitting
+ // perform the actual fitting task
+ NL::least_squeares_fitter<NL::LFMEllipse> fitter;
+ // 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
+ double tolerance, tol_at_extr, tol_at_center, angle_tol;
+ Point initial_point, final_point; // initial and final end-points
+ unsigned int N; // total samples
+ unsigned int last; // N-1
+ double partitions; // N-1
+ std::vector<Point> p; // sample points
+ double dist_err, dist_bound, angle_err;
+};
namespace detail
{
@@ -97,7 +186,7 @@ struct ellipse_equation
double A, B, C, D, E, F;
};
-}
+} // end namespace detail
make_elliptical_arc::
make_elliptical_arc( EllipticalArc& _ea,
@@ -110,8 +199,7 @@ make_elliptical_arc( EllipticalArc& _ea,
tolerance(_tolerance), tol_at_extr(tolerance/2),
tol_at_center(0.1), angle_tol(0.1),
initial_point(curve.at0()), final_point(curve.at1()),
- N(_total_samples), last(N-1), partitions(N-1), p(N),
- svg_compliant(true)
+ N(_total_samples), last(N-1), partitions(N-1), p(N)
{
}
@@ -216,33 +304,12 @@ bool make_elliptical_arc::make_elliptiarc()
Point inner_point = curve(0.5);
- if (svg_compliant_flag())
- {
-#ifdef CPP11
- std::unique_ptr<EllipticalArc> arc( e.arc(initial_point, inner_point, final_point, true) );
-#else
- std::auto_ptr<EllipticalArc> arc( e.arc(initial_point, inner_point, final_point, true) );
-#endif
- ea = *arc;
- }
- else
- {
- try
- {
#ifdef CPP11
- std::unique_ptr<EllipticalArc>
+ std::unique_ptr<EllipticalArc> arc( e.arc(initial_point, inner_point, final_point) );
#else
- std::auto_ptr<EllipticalArc>
+ std::auto_ptr<EllipticalArc> arc( e.arc(initial_point, inner_point, final_point) );
#endif
- eap( e.arc(initial_point, inner_point, final_point, false) );
- ea = *eap;
- }
- catch(RangeError const &exc)
- {
- return false;
- }
- }
-
+ ea = *arc;
if ( !are_near( e.center(),
ea.center(),
@@ -257,10 +324,14 @@ bool make_elliptical_arc::make_elliptiarc()
-} // end namespace Geom
-
-
+bool arc_from_sbasis(EllipticalArc &ea, D2<SBasis> const &in,
+ double tolerance, unsigned num_samples)
+{
+ make_elliptical_arc convert(ea, in, num_samples, tolerance);
+ return convert();
+}
+} // end namespace Geom
/*
Local Variables:
@@ -272,4 +343,3 @@ bool make_elliptical_arc::make_elliptiarc()
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
-