summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2011-03-18 23:34:21 +0000
committerJohan Engelen <goejendaagh@zonnet.nl>2011-03-18 23:34:21 +0000
commit4d22a9f26c863dcb99bf1a6f72c3b4a2d33eeb64 (patch)
treed765712050e3a22a92d7235fd205c55b7ec04919 /src
parentD-Bus. Merging branch lp:~joakim-verona/inkscape/dbus-fixes (Bug #666986, Bug... (diff)
downloadinkscape-4d22a9f26c863dcb99bf1a6f72c3b4a2d33eeb64.tar.gz
inkscape-4d22a9f26c863dcb99bf1a6f72c3b4a2d33eeb64.zip
add spiro interpolator to powerstroke
(bzr r10115)
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/lpe-powerstroke.cpp165
-rw-r--r--src/live_effects/lpe-powerstroke.h2
2 files changed, 161 insertions, 6 deletions
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 5dc170e84..3556be61f 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -21,18 +21,31 @@
#include <2geom/transforms.h>
#include <2geom/bezier-utils.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 Piecewise<D2<SBasis> > interpolateToPwD2Sb(std::vector<Point> points) = 0;
- virtual Path interpolateToPath(std::vector<Point> points) = 0;
+ virtual Geom::Path interpolateToPath(std::vector<Point> points) = 0;
private:
Interpolator(const Interpolator&);
@@ -120,16 +133,153 @@ private:
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 {
+static const Util::EnumData<unsigned> InterpolatorTypeData[] = {
+ {Geom::Interpolate::INTERP_LINEAR , N_("Linear"), "Linear"},
+ {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"},
+ {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"},
+ {Geom::Interpolate::INTERP_SPIRO , N_("SpiroInterpolator"), "SpiroInterpolator"}
+};
+static const Util::EnumDataConverter<unsigned> InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData));
+
LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this),
- sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve."), "sort_points", &wr, this, true)
+ sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve."), "sort_points", &wr, this, true),
+ interpolator_type(_("Interpolator type"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path."), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN)
{
show_orig_path = true;
@@ -137,6 +287,7 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&offset_points) );
registerParameter( dynamic_cast<Parameter *>(&sort_points) );
+ registerParameter( dynamic_cast<Parameter *>(&interpolator_type) );
}
LPEPowerStroke::~LPEPowerStroke()
@@ -195,9 +346,11 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const &
}
// create stroke path where points (x,y) := (t, offset)
- Geom::Interpolate::CubicBezierJohan interpolator;
- Path strokepath = interpolator.interpolateToPath(ts);
- Path mirroredpath = strokepath.reverse() * Geom::Scale(1,-1);
+ //Geom::Interpolate::CubicBezierJohan interpolator;
+ Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value()));
+ Geom::Path strokepath = interpolator->interpolateToPath(ts);
+ Geom::Path mirroredpath = strokepath.reverse() * Geom::Scale(1,-1);
+ delete interpolator;
strokepath.append(mirroredpath, Geom::Path::STITCH_DISCONTINUOUS);
strokepath.close();
@@ -222,7 +375,7 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const &
ts.push_back( first_point + Point(pwd2_in.domain().extent() ,0) );
// create stroke path where points (x,y) := (t, offset)
Geom::Interpolate::CubicBezierJohan interpolator;
- Path strokepath = interpolator.interpolateToPath(ts);
+ Geom::Path strokepath = interpolator.interpolateToPath(ts);
// output 2 separate paths
D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(strokepath.toPwSb());
diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h
index 667c94f53..7a1f3829a 100644
--- a/src/live_effects/lpe-powerstroke.h
+++ b/src/live_effects/lpe-powerstroke.h
@@ -15,6 +15,7 @@
#include "live_effects/effect.h"
#include "live_effects/parameter/bool.h"
#include "live_effects/parameter/powerstrokepointarray.h"
+#include "live_effects/parameter/enum.h"
namespace Inkscape {
namespace LivePathEffect {
@@ -31,6 +32,7 @@ public:
private:
PowerStrokePointArrayParam offset_points;
BoolParam sort_points;
+ EnumParam<unsigned> interpolator_type;
LPEPowerStroke(const LPEPowerStroke&);
LPEPowerStroke& operator=(const LPEPowerStroke&);