summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2011-11-08 20:56:10 +0000
committerJohan Engelen <goejendaagh@zonnet.nl>2011-11-08 20:56:10 +0000
commitb1e076e2e3199b4242231f567e1d8dd2af56d214 (patch)
tree6c1126ce0b26cc3794c075bb79dc2b999bb35498 /src
parentGerman translation update (diff)
downloadinkscape-b1e076e2e3199b4242231f567e1d8dd2af56d214.tar.gz
inkscape-b1e076e2e3199b4242231f567e1d8dd2af56d214.zip
split interpolator code from main powerstroke code
(bzr r10732)
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/CMakeLists.txt1
-rw-r--r--src/live_effects/Makefile_insert1
-rw-r--r--src/live_effects/lpe-powerstroke-interpolators.h276
-rw-r--r--src/live_effects/lpe-powerstroke.cpp244
4 files changed, 279 insertions, 243 deletions
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index 01cd7f25f..94112a52e 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -84,6 +84,7 @@ set(live_effects_SRC
lpe-perp_bisector.h
lpe-perspective_path.h
lpe-powerstroke.h
+ lpe-powerstroke-interpolators.h
lpe-recursiveskeleton.h
lpe-rough-hatches.h
lpe-ruler.h
diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert
index aacabc2db..692503201 100644
--- a/src/live_effects/Makefile_insert
+++ b/src/live_effects/Makefile_insert
@@ -69,6 +69,7 @@ ink_common_sources += \
live_effects/lpe-copy_rotate.h \
live_effects/lpe-powerstroke.cpp \
live_effects/lpe-powerstroke.h \
+ live_effects/lpe-powerstroke-interpolators.h \
live_effects/lpe-offset.cpp \
live_effects/lpe-offset.h \
live_effects/lpe-ruler.cpp \
diff --git a/src/live_effects/lpe-powerstroke-interpolators.h b/src/live_effects/lpe-powerstroke-interpolators.h
new file mode 100644
index 000000000..88bc13ff2
--- /dev/null
+++ b/src/live_effects/lpe-powerstroke-interpolators.h
@@ -0,0 +1,276 @@
+/** @file
+ * Interpolators for lists of points.
+ */
+/* Authors:
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Copyright (C) 2010-2011 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_LPE_POWERSTROKE_INTERPOLATORS_H
+#define INKSCAPE_LPE_POWERSTROKE_INTERPOLATORS_H
+
+#include <2geom/path.h>
+#include <2geom/bezier-utils.h>
+#include <2geom/sbasis-to-bezier.h>
+
+#include "live_effects/bezctx.h"
+#include "live_effects/bezctx_intf.h"
+#include "live_effects/spiro.h"
+
+
+/// @TODO Move this to 2geom?
+namespace Geom {
+namespace Interpolate {
+
+enum InterpolatorType {
+ INTERP_LINEAR,
+ INTERP_CUBICBEZIER,
+ INTERP_CUBICBEZIER_JOHAN,
+ INTERP_SPIRO
+};
+
+class Interpolator {
+public:
+ Interpolator() {};
+ virtual ~Interpolator() {};
+
+ static Interpolator* create(InterpolatorType type);
+
+ virtual Geom::Path interpolateToPath(std::vector<Point> const &points) const = 0;
+
+private:
+ Interpolator(const Interpolator&);
+ Interpolator& operator=(const Interpolator&);
+};
+
+class Linear : public Interpolator {
+public:
+ Linear() {};
+ virtual ~Linear() {};
+
+ virtual Path interpolateToPath(std::vector<Point> const &points) const {
+ Path path;
+ path.start( points.at(0) );
+ for (unsigned int i = 1 ; i < points.size(); ++i) {
+ path.appendNew<Geom::LineSegment>(points.at(i));
+ }
+ return path;
+ };
+
+private:
+ Linear(const Linear&);
+ Linear& operator=(const Linear&);
+};
+
+// this class is terrible
+class CubicBezierFit : public Interpolator {
+public:
+ CubicBezierFit() {};
+ virtual ~CubicBezierFit() {};
+
+ virtual Path interpolateToPath(std::vector<Point> const &points) const {
+ unsigned int n_points = points.size();
+ // worst case gives us 2 segment per point
+ int max_segs = 8*n_points;
+ Geom::Point * b = g_new(Geom::Point, max_segs);
+ Geom::Point * points_array = g_new(Geom::Point, 4*n_points);
+ for (unsigned i = 0; i < n_points; ++i) {
+ points_array[i] = points.at(i);
+ }
+
+ double tolerance_sq = 0; // this value is just a random guess
+
+ int const n_segs = Geom::bezier_fit_cubic_r(b, points_array, n_points,
+ tolerance_sq, max_segs);
+
+ Geom::Path fit;
+ if ( n_segs > 0)
+ {
+ fit.start(b[0]);
+ for (int c = 0; c < n_segs; c++) {
+ fit.appendNew<Geom::CubicBezier>(b[4*c+1], b[4*c+2], b[4*c+3]);
+ }
+ }
+ g_free(b);
+ g_free(points_array);
+ return fit;
+ };
+
+private:
+ CubicBezierFit(const CubicBezierFit&);
+ CubicBezierFit& operator=(const CubicBezierFit&);
+};
+
+/// @todo invent name for this class
+class CubicBezierJohan : public Interpolator {
+public:
+ CubicBezierJohan(double beta = 0.2) {
+ _beta = beta;
+ };
+ virtual ~CubicBezierJohan() {};
+
+ virtual Path interpolateToPath(std::vector<Point> const &points) const {
+ Path fit;
+ fit.start(points.at(0));
+ for (unsigned int i = 1; i < points.size(); ++i) {
+ Point p0 = points.at(i-1);
+ Point p1 = points.at(i);
+ Point dx = Point(p1[X] - p0[X], 0);
+ fit.appendNew<CubicBezier>(p0+_beta*dx, p1-_beta*dx, p1);
+ }
+ return fit;
+ };
+
+ double _beta;
+
+private:
+ CubicBezierJohan(const CubicBezierJohan&);
+ CubicBezierJohan& operator=(const CubicBezierJohan&);
+};
+
+
+#define SPIRO_SHOW_INFINITE_COORDINATE_CALLS
+class SpiroInterpolator : public Interpolator {
+public:
+ SpiroInterpolator() {};
+ virtual ~SpiroInterpolator() {};
+
+ virtual Path interpolateToPath(std::vector<Point> const &points) const {
+ Path fit;
+
+ Coord scale_y = 100.;
+
+ guint len = points.size();
+ bezctx *bc = new_bezctx_ink(&fit);
+ spiro_cp *controlpoints = g_new (spiro_cp, len);
+ for (unsigned int i = 0; i < len; ++i) {
+ controlpoints[i].x = points[i][X];
+ controlpoints[i].y = points[i][Y] / scale_y;
+ controlpoints[i].ty = 'c';
+ }
+ controlpoints[0].ty = '{';
+ controlpoints[1].ty = 'v';
+ controlpoints[len-2].ty = 'v';
+ controlpoints[len-1].ty = '}';
+
+ spiro_seg *s = run_spiro(controlpoints, len);
+ spiro_to_bpath(s, len, bc);
+ free(s);
+ free(bc);
+
+ fit *= Scale(1,scale_y);
+ return fit;
+ };
+
+private:
+ typedef struct {
+ bezctx base;
+ Path *path;
+ int is_open;
+ } bezctx_ink;
+
+ static void bezctx_ink_moveto(bezctx *bc, double x, double y, int /*is_open*/)
+ {
+ bezctx_ink *bi = (bezctx_ink *) bc;
+ if ( IS_FINITE(x) && IS_FINITE(y) ) {
+ bi->path->start(Point(x, y));
+ }
+ #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
+ else {
+ g_message("spiro moveto not finite");
+ }
+ #endif
+ }
+
+ static void bezctx_ink_lineto(bezctx *bc, double x, double y)
+ {
+ bezctx_ink *bi = (bezctx_ink *) bc;
+ if ( IS_FINITE(x) && IS_FINITE(y) ) {
+ bi->path->appendNew<LineSegment>( Point(x, y) );
+ }
+ #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
+ else {
+ g_message("spiro lineto not finite");
+ }
+ #endif
+ }
+
+ static void bezctx_ink_quadto(bezctx *bc, double xm, double ym, double x3, double y3)
+ {
+ bezctx_ink *bi = (bezctx_ink *) bc;
+
+ if ( IS_FINITE(xm) && IS_FINITE(ym) && IS_FINITE(x3) && IS_FINITE(y3) ) {
+ bi->path->appendNew<QuadraticBezier>(Point(xm, ym), Point(x3, y3));
+ }
+ #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
+ else {
+ g_message("spiro quadto not finite");
+ }
+ #endif
+ }
+
+ static void bezctx_ink_curveto(bezctx *bc, double x1, double y1, double x2, double y2,
+ double x3, double y3)
+ {
+ bezctx_ink *bi = (bezctx_ink *) bc;
+ if ( IS_FINITE(x1) && IS_FINITE(y1) && IS_FINITE(x2) && IS_FINITE(y2) ) {
+ bi->path->appendNew<CubicBezier>(Point(x1, y1), Point(x2, y2), Point(x3, y3));
+ }
+ #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
+ else {
+ g_message("spiro curveto not finite");
+ }
+ #endif
+ }
+
+ bezctx *
+ new_bezctx_ink(Geom::Path *path) const {
+ bezctx_ink *result = g_new(bezctx_ink, 1);
+ result->base.moveto = bezctx_ink_moveto;
+ result->base.lineto = bezctx_ink_lineto;
+ result->base.quadto = bezctx_ink_quadto;
+ result->base.curveto = bezctx_ink_curveto;
+ result->base.mark_knot = NULL;
+ result->path = path;
+ return &result->base;
+ }
+
+ SpiroInterpolator(const SpiroInterpolator&);
+ SpiroInterpolator& operator=(const SpiroInterpolator&);
+};
+
+
+Interpolator*
+Interpolator::create(InterpolatorType type) {
+ switch (type) {
+ case INTERP_LINEAR:
+ return new Geom::Interpolate::Linear();
+ case INTERP_CUBICBEZIER:
+ return new Geom::Interpolate::CubicBezierFit();
+ case INTERP_CUBICBEZIER_JOHAN:
+ return new Geom::Interpolate::CubicBezierJohan();
+ case INTERP_SPIRO:
+ return new Geom::Interpolate::SpiroInterpolator();
+ default:
+ return new Geom::Interpolate::Linear();
+ }
+}
+
+} //namespace Interpolate
+} //namespace Geom
+
+#endif
+
+/*
+ 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 :
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 56248907c..1cf8ff764 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -11,6 +11,7 @@
*/
#include "live_effects/lpe-powerstroke.h"
+#include "live_effects/lpe-powerstroke-interpolators.h"
#include "sp-shape.h"
#include "display/curve.h"
@@ -24,249 +25,6 @@
#include <2geom/sbasis-to-bezier.h>
#include <2geom/svg-path.h>
-// for the spiro interpolator:
-#include "live_effects/bezctx.h"
-#include "live_effects/bezctx_intf.h"
-#include "live_effects/spiro.h"
-
-
-/// @TODO Move this to 2geom
-namespace Geom {
-namespace Interpolate {
-
-enum InterpolatorType {
- INTERP_LINEAR,
- INTERP_CUBICBEZIER,
- INTERP_CUBICBEZIER_JOHAN,
- INTERP_SPIRO
-};
-
-class Interpolator {
-public:
- Interpolator() {};
- virtual ~Interpolator() {};
-
- static Interpolator* create(InterpolatorType type);
-
-// virtual Piecewise<D2<SBasis> > interpolateToPwD2Sb(std::vector<Point> points) = 0;
- virtual Geom::Path interpolateToPath(std::vector<Point> points) = 0;
-
-private:
- Interpolator(const Interpolator&);
- Interpolator& operator=(const Interpolator&);
-};
-
-class Linear : public Interpolator {
-public:
- Linear() {};
- virtual ~Linear() {};
-
- virtual Path interpolateToPath(std::vector<Point> points) {
- Path path;
- path.start( points.at(0) );
- for (unsigned int i = 1 ; i < points.size(); ++i) {
- path.appendNew<Geom::LineSegment>(points.at(i));
- }
- return path;
- };
-
-private:
- Linear(const Linear&);
- Linear& operator=(const Linear&);
-};
-
-// this class is terrible
-class CubicBezierFit : public Interpolator {
-public:
- CubicBezierFit() {};
- virtual ~CubicBezierFit() {};
-
- virtual Path interpolateToPath(std::vector<Point> points) {
- unsigned int n_points = points.size();
- // worst case gives us 2 segment per point
- int max_segs = 8*n_points;
- Geom::Point * b = g_new(Geom::Point, max_segs);
- Geom::Point * points_array = g_new(Geom::Point, 4*n_points);
- for (unsigned i = 0; i < n_points; ++i) {
- points_array[i] = points.at(i);
- }
-
- double tolerance_sq = 0; // this value is just a random guess
-
- int const n_segs = Geom::bezier_fit_cubic_r(b, points_array, n_points,
- tolerance_sq, max_segs);
-
- Geom::Path fit;
- if ( n_segs > 0)
- {
- fit.start(b[0]);
- for (int c = 0; c < n_segs; c++) {
- fit.appendNew<Geom::CubicBezier>(b[4*c+1], b[4*c+2], b[4*c+3]);
- }
- }
- g_free(b);
- g_free(points_array);
- return fit;
- };
-
-private:
- CubicBezierFit(const CubicBezierFit&);
- CubicBezierFit& operator=(const CubicBezierFit&);
-};
-
-/// @todo invent name for this class
-class CubicBezierJohan : public Interpolator {
-public:
- CubicBezierJohan() {};
- virtual ~CubicBezierJohan() {};
-
- virtual Path interpolateToPath(std::vector<Point> points) {
- Path fit;
- fit.start(points.at(0));
- for (unsigned int i = 1; i < points.size(); ++i) {
- Point p0 = points.at(i-1);
- Point p1 = points.at(i);
- Point dx = Point(p1[X] - p0[X], 0);
- fit.appendNew<CubicBezier>(p0+0.2*dx, p1-0.2*dx, p1);
- }
- return fit;
- };
-
-private:
- CubicBezierJohan(const CubicBezierJohan&);
- CubicBezierJohan& operator=(const CubicBezierJohan&);
-};
-
-
-#define SPIRO_SHOW_INFINITE_COORDINATE_CALLS
-class SpiroInterpolator : public Interpolator {
-public:
- SpiroInterpolator() {};
- virtual ~SpiroInterpolator() {};
-
- virtual Path interpolateToPath(std::vector<Point> points) {
- Path fit;
-
- Coord scale_y = 100.;
-
- guint len = points.size();
- bezctx *bc = new_bezctx_ink(&fit);
- spiro_cp *controlpoints = g_new (spiro_cp, len);
- for (unsigned int i = 0; i < len; ++i) {
- controlpoints[i].x = points[i][X];
- controlpoints[i].y = points[i][Y] / scale_y;
- controlpoints[i].ty = 'c';
- }
- controlpoints[0].ty = '{';
- controlpoints[1].ty = 'v';
- controlpoints[len-2].ty = 'v';
- controlpoints[len-1].ty = '}';
-
- spiro_seg *s = run_spiro(controlpoints, len);
- spiro_to_bpath(s, len, bc);
- free(s);
- free(bc);
-
- fit *= Scale(1,scale_y);
- return fit;
- };
-
-private:
- typedef struct {
- bezctx base;
- Path *path;
- int is_open;
- } bezctx_ink;
-
- static void bezctx_ink_moveto(bezctx *bc, double x, double y, int /*is_open*/)
- {
- bezctx_ink *bi = (bezctx_ink *) bc;
- if ( IS_FINITE(x) && IS_FINITE(y) ) {
- bi->path->start(Point(x, y));
- }
- #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
- else {
- g_message("spiro moveto not finite");
- }
- #endif
- }
-
- static void bezctx_ink_lineto(bezctx *bc, double x, double y)
- {
- bezctx_ink *bi = (bezctx_ink *) bc;
- if ( IS_FINITE(x) && IS_FINITE(y) ) {
- bi->path->appendNew<LineSegment>( Point(x, y) );
- }
- #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
- else {
- g_message("spiro lineto not finite");
- }
- #endif
- }
-
- static void bezctx_ink_quadto(bezctx *bc, double xm, double ym, double x3, double y3)
- {
- bezctx_ink *bi = (bezctx_ink *) bc;
-
- if ( IS_FINITE(xm) && IS_FINITE(ym) && IS_FINITE(x3) && IS_FINITE(y3) ) {
- bi->path->appendNew<QuadraticBezier>(Point(xm, ym), Point(x3, y3));
- }
- #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
- else {
- g_message("spiro quadto not finite");
- }
- #endif
- }
-
- static void bezctx_ink_curveto(bezctx *bc, double x1, double y1, double x2, double y2,
- double x3, double y3)
- {
- bezctx_ink *bi = (bezctx_ink *) bc;
- if ( IS_FINITE(x1) && IS_FINITE(y1) && IS_FINITE(x2) && IS_FINITE(y2) ) {
- bi->path->appendNew<CubicBezier>(Point(x1, y1), Point(x2, y2), Point(x3, y3));
- }
- #ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
- else {
- g_message("spiro curveto not finite");
- }
- #endif
- }
-
- bezctx *
- new_bezctx_ink(Geom::Path *path) {
- bezctx_ink *result = g_new(bezctx_ink, 1);
- result->base.moveto = bezctx_ink_moveto;
- result->base.lineto = bezctx_ink_lineto;
- result->base.quadto = bezctx_ink_quadto;
- result->base.curveto = bezctx_ink_curveto;
- result->base.mark_knot = NULL;
- result->path = path;
- return &result->base;
- }
-
- SpiroInterpolator(const SpiroInterpolator&);
- SpiroInterpolator& operator=(const SpiroInterpolator&);
-};
-
-
-Interpolator*
-Interpolator::create(InterpolatorType type) {
- switch (type) {
- case INTERP_LINEAR:
- return new Geom::Interpolate::Linear();
- case INTERP_CUBICBEZIER:
- return new Geom::Interpolate::CubicBezierFit();
- case INTERP_CUBICBEZIER_JOHAN:
- return new Geom::Interpolate::CubicBezierJohan();
- case INTERP_SPIRO:
- return new Geom::Interpolate::SpiroInterpolator();
- default:
- return new Geom::Interpolate::Linear();
- }
-}
-
-} //namespace Interpolate
-} //namespace Geom
namespace Inkscape {
namespace LivePathEffect {