summaryrefslogtreecommitdiffstats
path: root/src/live_effects
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2011-11-05 23:46:09 +0000
committerJohan Engelen <goejendaagh@zonnet.nl>2011-11-05 23:46:09 +0000
commitd98a89be688002c6fb69775a324af6669203090a (patch)
tree4b80d3b468ef0edf4b4b06c3e789d7b9455a7314 /src/live_effects
parentfix LPE toggle icon (diff)
downloadinkscape-d98a89be688002c6fb69775a324af6669203090a.tar.gz
inkscape-d98a89be688002c6fb69775a324af6669203090a.zip
Powerstroke: adjust control points when adding or deleting knots, to try and keep the shape a bit the same...
(bzr r10728)
Diffstat (limited to 'src/live_effects')
-rw-r--r--src/live_effects/lpe-powerstroke.cpp11
-rw-r--r--src/live_effects/lpe-powerstroke.h3
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.cpp36
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.h5
4 files changed, 50 insertions, 5 deletions
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 74a594a4b..56248907c 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -301,7 +301,7 @@ enum LineCuspType {
static const Util::EnumData<unsigned> LineCuspTypeData[] = {
{LINECUSP_BEVEL , N_("Beveled"), "bevel"},
{LINECUSP_ROUND , N_("Rounded"), "round"},
- {LINECUSP_SHARP , N_("Sharp"), "sharp"}
+// not yet supported {LINECUSP_SHARP , N_("Sharp"), "sharp"}
};
static const Util::EnumDataConverter<unsigned> LineCuspTypeConverter(LineCuspTypeData, sizeof(LineCuspTypeData)/sizeof(*LineCuspTypeData));
@@ -343,6 +343,12 @@ LPEPowerStroke::doOnApply(SPLPEItem *lpeitem)
offset_points.param_set_and_write_new_value(points);
}
+void
+LPEPowerStroke::adjustForNewPath(std::vector<Geom::Path> const & path_in)
+{
+ offset_points.recalculate_controlpoints_for_new_pwd2(path_in[0].toPwSb());
+}
+
static bool compare_offsets (Geom::Point first, Geom::Point second)
{
return first[Geom::X] < second[Geom::X];
@@ -435,10 +441,9 @@ LPEPowerStroke::doEffect_path (std::vector<Geom::Path> const & path_in)
// for now, only regard first subpath and ignore the rest
Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = path_in[0].toPwSb();
- offset_points.set_pwd2(pwd2_in);
Piecewise<D2<SBasis> > der = unitVector(derivative(pwd2_in));
Piecewise<D2<SBasis> > n = rot90(der);
- offset_points.set_pwd2_normal(n);
+ offset_points.set_pwd2(pwd2_in, n);
std::vector<Geom::Point> ts = offset_points.data();
if (sort_points) {
diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h
index bcfbdadc0..6c005f792 100644
--- a/src/live_effects/lpe-powerstroke.h
+++ b/src/live_effects/lpe-powerstroke.h
@@ -29,6 +29,9 @@ public:
virtual void doOnApply(SPLPEItem *lpeitem);
+ // methods called by path-manipulator upon edits
+ void adjustForNewPath(std::vector<Geom::Path> const & path_in);
+
private:
PowerStrokePointArrayParam offset_points;
BoolParam sort_points;
diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp
index 5139f0e41..fccbad7e5 100644
--- a/src/live_effects/parameter/powerstrokepointarray.cpp
+++ b/src/live_effects/parameter/powerstrokepointarray.cpp
@@ -76,6 +76,42 @@ void PowerStrokePointArrayParam::param_transform_multiply(Geom::Affine const& /*
}
+/** call this method to recalculate the controlpoints such that they stay at the same location relative to the new path. Useful after adding/deleting nodes to the path.*/
+void
+PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
+{
+ if (!last_pwd2.empty()) {
+ if (last_pwd2.size() > pwd2_in.size()) {
+ // Path has become shorter: rescale offsets
+ double factor = (double)pwd2_in.size() / (double)last_pwd2.size();
+ for (unsigned int i = 0; i < _vector.size(); ++i) {
+ _vector[i][Geom::X] *= factor;
+ }
+ } else if (last_pwd2.size() < pwd2_in.size()) {
+ // Path has become longer: probably node added, maintain position of knots
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > normal = rot90(unitVector(derivative(pwd2_in)));
+ for (unsigned int i = 0; i < _vector.size(); ++i) {
+ Geom::Point pt = _vector[i];
+ Geom::Point position = last_pwd2.valueAt(pt[Geom::X]) + pt[Geom::Y] * last_pwd2_normal.valueAt(pt[Geom::X]);
+
+ double t = nearest_point(position, pwd2_in);
+ double offset = dot(position - pwd2_in.valueAt(t), normal.valueAt(t));
+ _vector[i] = Geom::Point(t, offset);
+ }
+ }
+
+ write_to_SVG();
+ }
+}
+
+void
+PowerStrokePointArrayParam::set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_normal_in)
+{
+ last_pwd2 = pwd2_in;
+ last_pwd2_normal = pwd2_normal_in;
+}
+
+
void
PowerStrokePointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
{
diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h
index d984a7de5..550866384 100644
--- a/src/live_effects/parameter/powerstrokepointarray.h
+++ b/src/live_effects/parameter/powerstrokepointarray.h
@@ -43,11 +43,12 @@ public:
virtual bool providesKnotHolderEntities() { return true; }
virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
- void set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) { last_pwd2 = pwd2_in; }
+ void set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_normal_in);
Geom::Piecewise<Geom::D2<Geom::SBasis> > const & get_pwd2() { return last_pwd2; }
- void set_pwd2_normal(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) { last_pwd2_normal = pwd2_in; }
Geom::Piecewise<Geom::D2<Geom::SBasis> > const & get_pwd2_normal() { return last_pwd2_normal; }
+ void recalculate_controlpoints_for_new_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+
friend class PowerStrokePointArrayParamKnotHolderEntity;
private: