Merge lp:~inkscape.dev/inkscape/bend_and_pattern_along_path_width_modified_by_knot into lp:~inkscape.dev/inkscape/trunk

Proposed by Jabiertxof
Status: Merged
Merged at revision: 14515
Proposed branch: lp:~inkscape.dev/inkscape/bend_and_pattern_along_path_width_modified_by_knot
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 357 lines (+198/-10)
4 files modified
src/live_effects/lpe-bendpath.cpp (+76/-2)
src/live_effects/lpe-bendpath.h (+15/-4)
src/live_effects/lpe-patternalongpath.cpp (+90/-2)
src/live_effects/lpe-patternalongpath.h (+17/-2)
To merge this branch: bzr merge lp:~inkscape.dev/inkscape/bend_and_pattern_along_path_width_modified_by_knot
Reviewer Review Type Date Requested Status
su_v (community) ui Approve
Jabiertxof Needs Resubmitting
Review via email: mp+266659@code.launchpad.net
To post a comment you must log in.
14274. By Jabiertxof <email address hidden>

Fix bug on apply effect from pen/pencil toolbar

14275. By Jabiertxof <email address hidden>

update to trunk

14276. By Jabiertxof <email address hidden>

update to trunk

14277. By Jabiertxof <email address hidden>

fix a bug appliening from patheffect list the LPE

Revision history for this message
su_v (suv-lp) wrote :

Testing r14277 (on OS X):

a) Pattern along path LPE: a path with such an LPE applied cannot be moved without unexpected deformation/changes of the LPE width parameter.

Steps to reproduce:
1) launch branch (new default prefs, new default document)
2) switch to the bezier (pen) tool
3) select shape 'Ellipse'
4) draw a simple (straight) line
5) switch to the select tool
6) grab the path and drag it to a new location

--> the width parameter of the path effect changes unexpectedly.

Steps to reproduce:
1) launch branch (new default prefs, new default document)
2) switch to the bezier (pen) tool
3) select shape 'Ellipse'
4) draw a simple (straight) line
5) switch to the node tool
6) select all nodes of the original path (Ctrl+A)
7) grab one of selected nodes and drag the path to a new location

--> AFAIU the width parameter is not (or incorrectly) adjusted, and the path gets badly mangled or disappears completely. If snapping is enabled while dragging the selected nodes, inkscape produces these console messages:
** (inkscape:69451): WARNING **: encountered non finite point when evaluating snapping callback
Dragging the path by its nodes also fails if snapping is disabled globally.

b) The new width parameter added to the Bend LPE is not modified when dragging the path with the select tool, and doesn't act as erratically when node-editing the bend path (Ctrl+A, drag the bend path by grabbing one of the selected nodes): what is somewhat surprising though in initial tests is that the width parameter does not stay fixed relative to the bend path (it does not seem to be fixed relative to the original position either?) when dragging the bend path by its nodes.

review: Needs Fixing
14278. By Jabiertxof <email address hidden>

Full refactor of the LPE now too much simple code

14279. By Jabiertxof <email address hidden>

update to trunk

14280. By Jabiertxof <email address hidden>

update to trunk

14281. By Jabiertxof <email address hidden>

update to trunk

Revision history for this message
Jabiertxof (jabiertxof) wrote :

Total rewrite the code, now without this bugs and with the code much more simplest.

review: Needs Resubmitting
14282. By Jabiertxof <email address hidden>

minor changes

Revision history for this message
su_v (suv-lp) wrote :

Both earlier reported issues are fixed with the updated branch (tested with r14282 on OS X 10.7.5).

review: Approve (ui)
14283. By jabiertxof<email address hidden>

update to trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/live_effects/lpe-bendpath.cpp'
2--- src/live_effects/lpe-bendpath.cpp 2014-09-29 02:01:20 +0000
3+++ src/live_effects/lpe-bendpath.cpp 2015-12-08 11:07:10 +0000
4@@ -20,7 +20,13 @@
5 #include <2geom/d2.h>
6 #include <2geom/piecewise.h>
7
8+#include "knot-holder-entity.h"
9+#include "knotholder.h"
10+
11+#include <glibmm/i18n.h>
12+
13 #include <algorithm>
14+
15 using std::vector;
16
17
18@@ -48,10 +54,21 @@
19 namespace Inkscape {
20 namespace LivePathEffect {
21
22+Geom::PathVector bp_helper_path;
23+namespace BeP {
24+class KnotHolderEntityWidthBendPath : public LPEKnotHolderEntity {
25+ public:
26+ KnotHolderEntityWidthBendPath(LPEBendPath * effect) : LPEKnotHolderEntity(effect) {}
27+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
28+ virtual Geom::Point knot_get() const;
29+ };
30+} // BeP
31+
32 LPEBendPath::LPEBendPath(LivePathEffectObject *lpeobject) :
33 Effect(lpeobject),
34 bend_path(_("Bend path:"), _("Path along which to bend the original path"), "bendpath", &wr, this, "M0,0 L1,0"),
35- prop_scale(_("_Width:"), _("Width of the path"), "prop_scale", &wr, this, 1),
36+ original_height(0.0),
37+ prop_scale(_("_Width:"), _("Width of the path"), "prop_scale", &wr, this, 1.0),
38 scale_y_rel(_("W_idth in units of length"), _("Scale the width of the path in units of its length"), "scale_y_rel", &wr, this, false),
39 vertical_pattern(_("_Original path is vertical"), _("Rotates the original 90 degrees, before bending it along the bend path"), "vertical", &wr, this, false)
40 {
41@@ -63,6 +80,7 @@
42 prop_scale.param_set_digits(3);
43 prop_scale.param_set_increments(0.01, 0.10);
44
45+ _provides_knotholder_entities = true;
46 concatenate_before_pwd2 = true;
47 }
48
49@@ -76,7 +94,9 @@
50 {
51 // get the item bounding box
52 original_bbox(lpeitem);
53+ original_height = boundingbox_Y.max() - boundingbox_Y.min();
54 SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
55+
56 item->apply_to_clippath(item);
57 item->apply_to_mask(item);
58 }
59@@ -148,7 +168,61 @@
60 bend_path.set_new_value( path.toPwSb(), true );
61 }
62
63-
64+void
65+LPEBendPath::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
66+{
67+ hp_vec.push_back(bp_helper_path);
68+}
69+
70+void
71+LPEBendPath::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
72+{
73+ KnotHolderEntity *e = new BeP::KnotHolderEntityWidthBendPath(this);
74+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _("Change the width"), SP_KNOT_SHAPE_CIRCLE);
75+ knotholder->add(e);
76+}
77+
78+namespace BeP {
79+
80+void
81+KnotHolderEntityWidthBendPath::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state)
82+{
83+ LPEBendPath *lpe = dynamic_cast<LPEBendPath *> (_effect);
84+
85+ Geom::Point const s = snap_knot_position(p, state);
86+ Geom::Path path_in = lpe->bend_path.get_pathvector().pathAt(Geom::PathVectorTime(0, 0, 0.0));
87+ Geom::Point ptA = path_in.pointAt(Geom::PathTime(0, 0.0));
88+ lpe->prop_scale.param_set_value(Geom::distance(s , ptA)/(lpe->original_height/2.0));
89+
90+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
91+}
92+
93+Geom::Point
94+KnotHolderEntityWidthBendPath::knot_get() const
95+{
96+ LPEBendPath *lpe = dynamic_cast<LPEBendPath *> (_effect);
97+
98+ Geom::Path path_in = lpe->bend_path.get_pathvector().pathAt(Geom::PathVectorTime(0, 0, 0.0));
99+ Geom::Point ptA = path_in.pointAt(Geom::PathTime(0, 0.0));
100+ Geom::Point B = path_in.pointAt(Geom::PathTime(1, 0.0));
101+ Geom::Curve const *first_curve = &path_in.curveAt(Geom::PathTime(0, 0.0));
102+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*first_curve);
103+ Geom::Ray ray(ptA, B);
104+ if (cubic) {
105+ ray.setPoints(ptA,(*cubic)[1]);
106+ }
107+ Geom::Angle first_curve_angle = ray.transformed(Geom::Rotate(Geom::deg_to_rad(90))).angle();
108+ Geom::Point result_point = Geom::Point::polar(first_curve_angle, (lpe->original_height * lpe->prop_scale)/2.0) + ptA;
109+
110+ bp_helper_path.clear();
111+ Geom::Path hp(result_point);
112+ hp.appendNew<Geom::LineSegment>(ptA);
113+ bp_helper_path.push_back(hp);
114+ hp.clear();
115+
116+ return result_point;
117+}
118+} // namespace BeP
119 } // namespace LivePathEffect
120 } /* namespace Inkscape */
121
122
123=== modified file 'src/live_effects/lpe-bendpath.h'
124--- src/live_effects/lpe-bendpath.h 2015-08-05 19:25:52 +0000
125+++ src/live_effects/lpe-bendpath.h 2015-12-08 11:07:10 +0000
126@@ -27,6 +27,10 @@
127 namespace Inkscape {
128 namespace LivePathEffect {
129
130+namespace BeP {
131+class KnotHolderEntityWidthBendPath;
132+}
133+
134 //for Bend path on group : we need information concerning the group Bounding box
135 class LPEBendPath : public Effect, GroupBBoxEffect {
136 public:
137@@ -39,12 +43,19 @@
138
139 virtual void resetDefaults(SPItem const* item);
140
141- PathParam bend_path;
142+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
143+
144+ virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item);
145+
146+ PathParam bend_path;
147+
148+ friend class BeP::KnotHolderEntityWidthBendPath;
149+protected:
150+ double original_height;
151+ ScalarParam prop_scale;
152 private:
153- ScalarParam prop_scale;
154 BoolParam scale_y_rel;
155- BoolParam vertical_pattern;
156-
157+ BoolParam vertical_pattern;
158 Geom::Piecewise<Geom::D2<Geom::SBasis> > uskeleton;
159 Geom::Piecewise<Geom::D2<Geom::SBasis> > n;
160
161
162=== modified file 'src/live_effects/lpe-patternalongpath.cpp'
163--- src/live_effects/lpe-patternalongpath.cpp 2014-03-27 01:33:44 +0000
164+++ src/live_effects/lpe-patternalongpath.cpp 2015-12-08 11:07:10 +0000
165@@ -18,6 +18,9 @@
166 #include <2geom/d2.h>
167 #include <2geom/piecewise.h>
168
169+#include "knot-holder-entity.h"
170+#include "knotholder.h"
171+
172 #include <algorithm>
173 using std::vector;
174
175@@ -45,6 +48,16 @@
176
177 namespace Inkscape {
178 namespace LivePathEffect {
179+Geom::PathVector pap_helper_path;
180+
181+namespace WPAP {
182+ class KnotHolderEntityWidthPatternAlongPath : public LPEKnotHolderEntity {
183+ public:
184+ KnotHolderEntityWidthPatternAlongPath(LPEPatternAlongPath * effect) : LPEKnotHolderEntity(effect) {}
185+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
186+ virtual Geom::Point knot_get() const;
187+ };
188+} // WPAP
189
190 static const Util::EnumData<PAPCopyType> PAPCopyTypeData[PAPCT_END] = {
191 {PAPCT_SINGLE, N_("Single"), "single"},
192@@ -57,9 +70,10 @@
193 LPEPatternAlongPath::LPEPatternAlongPath(LivePathEffectObject *lpeobject) :
194 Effect(lpeobject),
195 pattern(_("Pattern source:"), _("Path to put along the skeleton path"), "pattern", &wr, this, "M0,0 L1,0"),
196+ original_height(0),
197+ prop_scale(_("_Width:"), _("Width of the pattern"), "prop_scale", &wr, this, 1.0),
198 copytype(_("Pattern copies:"), _("How many pattern copies to place along the skeleton path"),
199 "copytype", PAPCopyTypeConverter, &wr, this, PAPCT_SINGLE_STRETCHED),
200- prop_scale(_("_Width:"), _("Width of the pattern"), "prop_scale", &wr, this, 1),
201 scale_y_rel(_("Wid_th in units of length"),
202 _("Scale the width of the pattern in units of its length"),
203 "scale_y_rel", &wr, this, false),
204@@ -87,9 +101,11 @@
205 registerParameter( dynamic_cast<Parameter *>(&prop_units) );
206 registerParameter( dynamic_cast<Parameter *>(&vertical_pattern) );
207 registerParameter( dynamic_cast<Parameter *>(&fuse_tolerance) );
208-
209 prop_scale.param_set_digits(3);
210 prop_scale.param_set_increments(0.01, 0.10);
211+
212+ _provides_knotholder_entities = true;
213+
214 }
215
216 LPEPatternAlongPath::~LPEPatternAlongPath()
217@@ -97,6 +113,16 @@
218
219 }
220
221+void
222+LPEPatternAlongPath::doBeforeEffect (SPLPEItem const* lpeitem)
223+{
224+ // get the pattern bounding box
225+ Geom::OptRect bbox = pattern.get_pathvector().boundsFast();
226+ if (bbox) {
227+ original_height = (*bbox)[Geom::Y].max() - (*bbox)[Geom::Y].min();
228+ }
229+}
230+
231 Geom::Piecewise<Geom::D2<Geom::SBasis> >
232 LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
233 {
234@@ -238,6 +264,68 @@
235 }
236 }
237
238+void
239+LPEPatternAlongPath::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
240+{
241+ hp_vec.push_back(pap_helper_path);
242+}
243+
244+
245+void
246+LPEPatternAlongPath::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
247+{
248+ KnotHolderEntity *e = new WPAP::KnotHolderEntityWidthPatternAlongPath(this);
249+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _("Change the width"), SP_KNOT_SHAPE_CIRCLE);
250+ knotholder->add(e);
251+}
252+
253+namespace WPAP {
254+
255+void
256+KnotHolderEntityWidthPatternAlongPath::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state)
257+{
258+ LPEPatternAlongPath *lpe = dynamic_cast<LPEPatternAlongPath *> (_effect);
259+
260+ Geom::Point const s = snap_knot_position(p, state);
261+ SPShape const *sp_shape = dynamic_cast<SPShape const *>(SP_LPE_ITEM(item));
262+ if (sp_shape) {
263+ Geom::Path const *path_in = sp_shape->getCurveBeforeLPE()->first_path();
264+ Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0));
265+ lpe->prop_scale.param_set_value(Geom::distance(s , ptA)/(lpe->original_height/2.0));
266+ }
267+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
268+}
269+
270+Geom::Point
271+KnotHolderEntityWidthPatternAlongPath::knot_get() const
272+{
273+ LPEPatternAlongPath *lpe = dynamic_cast<LPEPatternAlongPath *> (_effect);
274+
275+ SPShape const *sp_shape = dynamic_cast<SPShape const *>(SP_LPE_ITEM(item));
276+ if (sp_shape) {
277+ Geom::Path const *path_in = sp_shape->getCurveBeforeLPE()->first_path();
278+ Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0));
279+ Geom::Point B = path_in->pointAt(Geom::PathTime(1, 0.0));
280+ Geom::Curve const *first_curve = &path_in->curveAt(Geom::PathTime(0, 0.0));
281+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*first_curve);
282+ Geom::Ray ray(ptA, B);
283+ if (cubic) {
284+ ray.setPoints((*cubic)[1], ptA);
285+ }
286+ Geom::Angle first_curve_angle = ray.transformed(Geom::Rotate(Geom::deg_to_rad(90))).angle();
287+ Geom::Point result_point = Geom::Point::polar(first_curve_angle, (lpe->original_height * lpe->prop_scale)/2.0) + ptA;
288+
289+ pap_helper_path.clear();
290+ Geom::Path hp(result_point);
291+ hp.appendNew<Geom::LineSegment>(ptA);
292+ pap_helper_path.push_back(hp);
293+ hp.clear();
294+
295+ return result_point;
296+ }
297+ return Geom::Point();
298+}
299+} // namespace WPAP
300 } // namespace LivePathEffect
301 } /* namespace Inkscape */
302
303
304=== modified file 'src/live_effects/lpe-patternalongpath.h'
305--- src/live_effects/lpe-patternalongpath.h 2012-02-12 13:43:17 +0000
306+++ src/live_effects/lpe-patternalongpath.h 2015-12-08 11:07:10 +0000
307@@ -13,10 +13,15 @@
308 #include "live_effects/effect.h"
309 #include "live_effects/parameter/path.h"
310 #include "live_effects/parameter/bool.h"
311+#include "live_effects/parameter/point.h"
312
313 namespace Inkscape {
314 namespace LivePathEffect {
315
316+namespace WPAP {
317+class KnotHolderEntityWidthPatternAlongPath;
318+}
319+
320 enum PAPCopyType {
321 PAPCT_SINGLE = 0,
322 PAPCT_SINGLE_STRETCHED,
323@@ -30,14 +35,25 @@
324 LPEPatternAlongPath(LivePathEffectObject *lpeobject);
325 virtual ~LPEPatternAlongPath();
326
327+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
328+
329 virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
330
331 virtual void transform_multiply(Geom::Affine const& postmul, bool set);
332
333+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
334+
335+ virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item);
336+
337 PathParam pattern;
338+
339+ friend class WPAP::KnotHolderEntityWidthPatternAlongPath;
340+protected:
341+ double original_height;
342+ ScalarParam prop_scale;
343+
344 private:
345 EnumParam<PAPCopyType> copytype;
346- ScalarParam prop_scale;
347 BoolParam scale_y_rel;
348 ScalarParam spacing;
349 ScalarParam normal_offset;
350@@ -45,7 +61,6 @@
351 BoolParam prop_units;
352 BoolParam vertical_pattern;
353 ScalarParam fuse_tolerance;
354-
355 void on_pattern_pasted();
356
357 LPEPatternAlongPath(const LPEPatternAlongPath&);