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

Proposed by Jabiertxof
Status: Merged
Approved by: Jabiertxof
Approved revision: 13900
Merge reported by: Jabiertxof
Merged at revision: not available
Proposed branch: lp:~inkscape.dev/inkscape/transform_by_two_points
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 480 lines (+406/-0)
6 files modified
src/live_effects/CMakeLists.txt (+2/-0)
src/live_effects/Makefile_insert (+2/-0)
src/live_effects/effect-enum.h (+1/-0)
src/live_effects/effect.cpp (+5/-0)
src/live_effects/lpe-transform_2pts.cpp (+316/-0)
src/live_effects/lpe-transform_2pts.h (+80/-0)
To merge this branch: bzr merge lp:~inkscape.dev/inkscape/transform_by_two_points
Reviewer Review Type Date Requested Status
Inkscape Developers Pending
Review via email: mp+248306@code.launchpad.net

Description of the change

Add transform by two points LPE.

To post a comment you must log in.
13886. By Jabiertxof <email address hidden>

Fix some problems pointed by su_v

13887. By Jabiertxof <email address hidden>

fixing bugs on reset function

13888. By Jabiertxof <email address hidden>

fixed bugs pointed by su_v

13889. By Jabiertxof <email address hidden>

update to trunk

Revision history for this message
Jabiertxof (jabiertxof) wrote :
13890. By Jabiertxof <email address hidden>

update to trunk

13891. By Jabiertxof <email address hidden>

fix a bug pointed by su_v

13892. By Jabiertxof <email address hidden>

Fixed compiling problems and removed ACTIVE DESKTOP from LPE

13893. By Jabiertxof <email address hidden>

update to trunk

13894. By Jabiertxof <email address hidden>

Fix coding style issues in transform by two points LPE

13895. By Jabiertxof <email address hidden>

update to trunk

13896. By Jabiertxof <email address hidden>

update to trunk

13897. By Jabiertxof <email address hidden>

update to trunk

Revision history for this message
njh (njh-njhurst) wrote :

I think you should pester tweenk about the new api and make sure this is still in style. I recall him recommending not using the int part of floats as a curve position.

Revision history for this message
Jabiertxof (jabiertxof) wrote :

Thanks Nathan for the review. I ping to tweenk tonight or tomorrow.

Revision history for this message
Jabiertxof (jabiertxof) wrote :

I just update the branch whith your inputs and ask tweenk to confirm

13898. By Jabiertxof <email address hidden>

update to trunk

13899. By Jabiertxof <email address hidden>

Fixed bugs in branch review and updated to new api

13900. By Jabiertxof <email address hidden>

update to trunk

Revision history for this message
Jabiertxof (jabiertxof) wrote :

I merge the branch tomorrow if no one put objections. The diff cuestions Nathan tell are solved, and also I update the code to the new 2Geom API thanks to the info get I from tweenk.

13901. By Jabiertxof <email address hidden>

update to trunk

Revision history for this message
Jabiertxof (jabiertxof) wrote :

Thanks Nathan for the review, and tweenk for the help!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/live_effects/CMakeLists.txt'
2--- src/live_effects/CMakeLists.txt 2015-07-08 21:08:19 +0000
3+++ src/live_effects/CMakeLists.txt 2015-08-24 19:48:57 +0000
4@@ -6,6 +6,7 @@
5 lpe-bounding-box.cpp
6 lpe-bspline.cpp
7 lpe-circle_3pts.cpp
8+ lpe-transform_2pts.cpp
9 lpe-circle_with_radius.cpp
10 lpe-clone-original.cpp
11 lpe-constructgrid.cpp
12@@ -83,6 +84,7 @@
13 lpe-bounding-box.h
14 lpe-bspline.h
15 lpe-circle_3pts.h
16+ lpe-transform_2pts.h
17 lpe-circle_with_radius.h
18 lpe-clone-original.h
19 lpe-constructgrid.h
20
21=== modified file 'src/live_effects/Makefile_insert'
22--- src/live_effects/Makefile_insert 2015-04-27 23:39:29 +0000
23+++ src/live_effects/Makefile_insert 2015-08-24 19:48:57 +0000
24@@ -74,6 +74,8 @@
25 live_effects/lpe-mirror_symmetry.h \
26 live_effects/lpe-circle_3pts.cpp \
27 live_effects/lpe-circle_3pts.h \
28+ live_effects/lpe-transform_2pts.cpp \
29+ live_effects/lpe-transform_2pts.h \
30 live_effects/lpe-angle_bisector.cpp \
31 live_effects/lpe-angle_bisector.h \
32 live_effects/lpe-parallel.cpp \
33
34=== modified file 'src/live_effects/effect-enum.h'
35--- src/live_effects/effect-enum.h 2014-10-18 21:44:39 +0000
36+++ src/live_effects/effect-enum.h 2015-08-24 19:48:57 +0000
37@@ -38,6 +38,7 @@
38 TANGENT_TO_CURVE,
39 MIRROR_SYMMETRY,
40 CIRCLE_3PTS,
41+ TRANSFORM_2PTS,
42 ANGLE_BISECTOR,
43 PARALLEL,
44 COPY_ROTATE,
45
46=== modified file 'src/live_effects/effect.cpp'
47--- src/live_effects/effect.cpp 2015-05-22 07:02:44 +0000
48+++ src/live_effects/effect.cpp 2015-08-24 19:48:57 +0000
49@@ -57,6 +57,7 @@
50 #include "live_effects/lpe-sketch.h"
51 #include "live_effects/lpe-spiro.h"
52 #include "live_effects/lpe-tangent_to_curve.h"
53+#include "live_effects/lpe-transform_2pts.h"
54 #include "live_effects/lpe-taperstroke.h"
55 #include "live_effects/lpe-test-doEffect-stack.h"
56 #include "live_effects/lpe-text_label.h"
57@@ -150,6 +151,7 @@
58 {PERSPECTIVE_ENVELOPE, N_("Perspective/Envelope"), "perspective-envelope"},
59 {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"},
60 {INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"},
61+ {TRANSFORM_2PTS, N_("Transform by 2 points"), "transform_2pts"},
62 };
63 const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData));
64
65@@ -315,6 +317,9 @@
66 case SHOW_HANDLES:
67 neweffect = static_cast<Effect*> ( new LPEShowHandles(lpeobj) );
68 break;
69+ case TRANSFORM_2PTS:
70+ neweffect = static_cast<Effect*> ( new LPETransform2Pts(lpeobj) );
71+ break;
72 default:
73 g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
74 neweffect = NULL;
75
76=== added file 'src/live_effects/lpe-transform_2pts.cpp'
77--- src/live_effects/lpe-transform_2pts.cpp 1970-01-01 00:00:00 +0000
78+++ src/live_effects/lpe-transform_2pts.cpp 2015-08-24 19:48:57 +0000
79@@ -0,0 +1,316 @@
80+/** \file
81+ * LPE "Transform through 2 points" implementation
82+ */
83+
84+/*
85+ * Authors:
86+ * Jabier Arraiza Cenoz<jabier.arraiza@marker.es>
87+ *
88+ *
89+ * Released under GNU GPL, read the file 'COPYING' for more information
90+ */
91+
92+#include <gtkmm.h>
93+
94+#include "live_effects/lpe-transform_2pts.h"
95+#include "display/curve.h"
96+#include <2geom/transforms.h>
97+#include <2geom/pathvector.h>
98+#include "sp-path.h"
99+#include "ui/icon-names.h"
100+
101+#include <glibmm/i18n.h>
102+
103+namespace Inkscape {
104+namespace LivePathEffect {
105+
106+LPETransform2Pts::LPETransform2Pts(LivePathEffectObject *lpeobject) :
107+ Effect(lpeobject),
108+ from_original_width(_("From original width"), _("From original width"), "from_original_width", &wr, this, false,"", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
109+ start(_("Start"), _("Start point"), "start", &wr, this, "Start point"),
110+ end(_("End"), _("End point"), "end", &wr, this, "End point"),
111+ first_knot(_("First Knot"), _("First Knot"), "first_knot", &wr, this, 1),
112+ last_knot(_("Last Knot"), _("Last Knot"), "last_knot", &wr, this, 1),
113+ from_original_width_toggler(false),
114+ point_a(Geom::Point()),
115+ point_b(Geom::Point()),
116+ pathvector(),
117+ append_path(false)
118+{
119+ registerParameter(&start);
120+ registerParameter(&end);
121+ registerParameter(&first_knot);
122+ registerParameter(&last_knot);
123+ registerParameter(&from_original_width);
124+
125+ first_knot.param_make_integer(true);
126+ last_knot.param_make_integer(true);
127+}
128+
129+LPETransform2Pts::~LPETransform2Pts()
130+{
131+}
132+
133+void
134+LPETransform2Pts::doOnApply(SPLPEItem const* lpeitem)
135+{
136+ using namespace Geom;
137+ original_bbox(lpeitem);
138+
139+ point_a = Point(boundingbox_X.min(), boundingbox_Y.middle());
140+ point_b = Point(boundingbox_X.max(), boundingbox_Y.middle());
141+ SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem);
142+ SPPath *sp_path = dynamic_cast<SPPath *>(splpeitem);
143+ if (sp_path) {
144+ pathvector = sp_path->get_original_curve()->get_pathvector();
145+ }
146+ if(!pathvector.empty()) {
147+ point_a = pathvector.initialPoint();
148+ point_b = pathvector.finalPoint();
149+ size_t nnodes = nodeCount(pathvector);
150+ last_knot.param_set_value(nnodes);
151+ }
152+ start.param_update_default(point_a);
153+ start.param_set_default();
154+ end.param_update_default(point_b);
155+ end.param_set_default();
156+}
157+
158+void
159+LPETransform2Pts::doBeforeEffect (SPLPEItem const* lpeitem)
160+{
161+ using namespace Geom;
162+ original_bbox(lpeitem);
163+ point_a = Point(boundingbox_X.min(), boundingbox_Y.middle());
164+ point_b = Point(boundingbox_X.max(), boundingbox_Y.middle());
165+
166+ SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem);
167+ SPPath *sp_path = dynamic_cast<SPPath *>(splpeitem);
168+ if (sp_path) {
169+ pathvector = sp_path->get_original_curve()->get_pathvector();
170+ }
171+ if(from_original_width_toggler != from_original_width) {
172+ from_original_width_toggler = from_original_width;
173+ reset();
174+ }
175+ if(!pathvector.empty() && !from_original_width) {
176+ append_path = false;
177+ point_a = pointAtNodeIndex(pathvector,(size_t)first_knot-1);
178+ point_b = pointAtNodeIndex(pathvector,(size_t)last_knot-1);
179+ size_t nnodes = nodeCount(pathvector);
180+ first_knot.param_set_range(1, last_knot-1);
181+ last_knot.param_set_range(first_knot+1, nnodes);
182+ from_original_width.param_setValue(false);
183+ } else {
184+ first_knot.param_set_value(1);
185+ last_knot.param_set_value(2);
186+ first_knot.param_set_range(1,1);
187+ last_knot.param_set_range(2,2);
188+ from_original_width.param_setValue(true);
189+ append_path = false;
190+ }
191+ splpeitem->apply_to_clippath(splpeitem);
192+ splpeitem->apply_to_mask(splpeitem);
193+}
194+
195+void
196+LPETransform2Pts::updateIndex()
197+{
198+ SPLPEItem * splpeitem = const_cast<SPLPEItem *>(sp_lpe_item);
199+ SPPath *sp_path = dynamic_cast<SPPath *>(splpeitem);
200+ if (sp_path) {
201+ pathvector = sp_path->get_original_curve()->get_pathvector();
202+ }
203+ if(!pathvector.empty() && !from_original_width) {
204+ point_a = pointAtNodeIndex(pathvector,(size_t)first_knot-1);
205+ point_b = pointAtNodeIndex(pathvector,(size_t)last_knot-1);
206+ start.param_update_default(point_a);
207+ start.param_set_default();
208+ end.param_update_default(point_b);
209+ end.param_set_default();
210+ start.param_update_default(point_a);
211+ end.param_update_default(point_b);
212+ start.param_set_default();
213+ end.param_set_default();
214+ }
215+}
216+//todo migrate to PathVector class?
217+size_t
218+LPETransform2Pts::nodeCount(Geom::PathVector pathvector) const
219+{
220+ size_t n = 0;
221+ for (Geom::PathVector::iterator it = pathvector.begin(); it != pathvector.end(); ++it) {
222+ n += it->size_closed();
223+ }
224+ return n;
225+}
226+//todo migrate to PathVector class?
227+Geom::Point
228+LPETransform2Pts::pointAtNodeIndex(Geom::PathVector pathvector, size_t index) const
229+{
230+ size_t n = 0;
231+ for (Geom::PathVector::iterator pv_it = pathvector.begin(); pv_it != pathvector.end(); ++pv_it) {
232+ for (Geom::Path::iterator curve_it = pv_it->begin(); curve_it != pv_it->end_closed(); ++curve_it) {
233+ if(index == n){
234+ return curve_it->initialPoint();
235+ }
236+ n++;
237+ }
238+ }
239+ return Geom::Point();
240+}
241+//todo migrate to PathVector class? Not used
242+Geom::Path
243+LPETransform2Pts::pathAtNodeIndex(Geom::PathVector pathvector, size_t index) const
244+{
245+ size_t n = 0;
246+ for (Geom::PathVector::iterator pv_it = pathvector.begin(); pv_it != pathvector.end(); ++pv_it) {
247+ for (Geom::Path::iterator curve_it = pv_it->begin(); curve_it != pv_it->end_closed(); ++curve_it) {
248+ if(index == n){
249+ return *pv_it;
250+ }
251+ n++;
252+ }
253+ }
254+ return Geom::Path();
255+}
256+
257+
258+void
259+LPETransform2Pts::reset()
260+{
261+ point_a = Geom::Point(boundingbox_X.min(), boundingbox_Y.middle());
262+ point_b = Geom::Point(boundingbox_X.max(), boundingbox_Y.middle());
263+ if(!pathvector.empty() && !from_original_width) {
264+ size_t nnodes = nodeCount(pathvector);
265+ first_knot.param_set_range(1, last_knot-1);
266+ last_knot.param_set_range(first_knot+1, nnodes);
267+ first_knot.param_set_value(1);
268+ last_knot.param_set_value(nnodes);
269+ point_a = pathvector.initialPoint();
270+ point_b = pathvector.finalPoint();
271+ } else {
272+ first_knot.param_set_value(1);
273+ last_knot.param_set_value(2);
274+ }
275+ start.param_update_default(point_a);
276+ end.param_update_default(point_b);
277+ start.param_set_default();
278+ end.param_set_default();
279+}
280+
281+Gtk::Widget *LPETransform2Pts::newWidget()
282+{
283+ // use manage here, because after deletion of Effect object, others might
284+ // still be pointing to this widget.
285+ Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
286+
287+ vbox->set_border_width(5);
288+ vbox->set_homogeneous(false);
289+ vbox->set_spacing(6);
290+
291+ std::vector<Parameter *>::iterator it = param_vector.begin();
292+ Gtk::HBox * button = Gtk::manage(new Gtk::HBox(true,0));
293+ while (it != param_vector.end()) {
294+ if ((*it)->widget_is_visible) {
295+ Parameter *param = *it;
296+ Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
297+ Glib::ustring *tip = param->param_getTooltip();
298+ if (param->param_key == "first_knot" || param->param_key == "last_knot") {
299+ Inkscape::UI::Widget::Scalar *registered_widget = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
300+ registered_widget->signal_value_changed().connect(sigc::mem_fun(*this, &LPETransform2Pts::updateIndex));
301+ widg = registered_widget;
302+ if (widg) {
303+ Gtk::HBox *hbox_scalar = dynamic_cast<Gtk::HBox *>(widg);
304+ std::vector<Gtk::Widget *> child_list = hbox_scalar->get_children();
305+ Gtk::Entry *entry_widget = dynamic_cast<Gtk::Entry *>(child_list[1]);
306+ entry_widget->set_width_chars(3);
307+ vbox->pack_start(*widg, true, true, 2);
308+ if (tip) {
309+ widg->set_tooltip_text(*tip);
310+ } else {
311+ widg->set_tooltip_text("");
312+ widg->set_has_tooltip(false);
313+ }
314+ }
315+ } else if (param->param_key == "from_original_width") {
316+ Glib::ustring * tip = param->param_getTooltip();
317+ if (widg) {
318+ button->pack_start(*widg, true, true, 2);
319+ if (tip) {
320+ widg->set_tooltip_text(*tip);
321+ } else {
322+ widg->set_tooltip_text("");
323+ widg->set_has_tooltip(false);
324+ }
325+ }
326+ } else if (widg) {
327+ vbox->pack_start(*widg, true, true, 2);
328+ if (tip) {
329+ widg->set_tooltip_text(*tip);
330+ } else {
331+ widg->set_tooltip_text("");
332+ widg->set_has_tooltip(false);
333+ }
334+ }
335+ }
336+
337+ ++it;
338+ }
339+ Gtk::Button *reset = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset"))));
340+ reset->signal_clicked().connect(sigc::mem_fun(*this, &LPETransform2Pts::reset));
341+ button->pack_start(*reset, true, true, 2);
342+ vbox->pack_start(*button, true, true, 2);
343+ return dynamic_cast<Gtk::Widget *>(vbox);
344+}
345+
346+Geom::Piecewise<Geom::D2<Geom::SBasis> >
347+LPETransform2Pts::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
348+{
349+ Geom::Piecewise<Geom::D2<Geom::SBasis> > output;
350+ double sca = Geom::distance((Geom::Point)start,(Geom::Point)end)/Geom::distance(point_a,point_b);
351+ Geom::Ray original(point_a,point_b);
352+ Geom::Ray transformed((Geom::Point)start,(Geom::Point)end);
353+ double rot = transformed.angle() - original.angle();
354+ Geom::Path helper;
355+ helper.start(point_a);
356+ helper.appendNew<Geom::LineSegment>(point_b);
357+ Geom::Affine m;
358+ m *= Geom::Scale(sca);
359+ m *= Geom::Rotate(rot);
360+ helper *= m;
361+ m *= Geom::Translate((Geom::Point)start - helper.initialPoint());
362+ output.concat(pwd2_in * m);
363+
364+ return output;
365+}
366+
367+void
368+LPETransform2Pts::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
369+{
370+ using namespace Geom;
371+ hp_vec.clear();
372+ Geom::Path hp;
373+ hp.start((Geom::Point)start);
374+ hp.appendNew<Geom::LineSegment>((Geom::Point)end);
375+ Geom::PathVector pathv;
376+ pathv.push_back(hp);
377+ hp_vec.push_back(pathv);
378+}
379+
380+
381+/* ######################## */
382+
383+} //namespace LivePathEffect
384+} /* namespace Inkscape */
385+
386+/*
387+ Local Variables:
388+ mode:c++
389+ c-file-style:"stroustrup"
390+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
391+ indent-tabs-mode:nil
392+ fill-column:99
393+ End:
394+*/
395+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
396
397=== added file 'src/live_effects/lpe-transform_2pts.h'
398--- src/live_effects/lpe-transform_2pts.h 1970-01-01 00:00:00 +0000
399+++ src/live_effects/lpe-transform_2pts.h 2015-08-24 19:48:57 +0000
400@@ -0,0 +1,80 @@
401+#ifndef INKSCAPE_LPE_TRANSFORM_2PTS_H
402+#define INKSCAPE_LPE_TRANSFORM_2PTS_H
403+
404+/** \file
405+ * LPE "Transform through 2 points" implementation
406+ */
407+
408+/*
409+ * Authors:
410+ *
411+ *
412+ *
413+ * Released under GNU GPL, read the file 'COPYING' for more information
414+ */
415+
416+#include "live_effects/effect.h"
417+#include "live_effects/lpegroupbbox.h"
418+#include "live_effects/parameter/parameter.h"
419+#include "live_effects/parameter/togglebutton.h"
420+#include "live_effects/parameter/point.h"
421+
422+namespace Inkscape {
423+namespace LivePathEffect {
424+
425+class LPETransform2Pts : public Effect, GroupBBoxEffect {
426+public:
427+ LPETransform2Pts(LivePathEffectObject *lpeobject);
428+ virtual ~LPETransform2Pts();
429+
430+ virtual void doOnApply (SPLPEItem const* lpeitem);
431+
432+ virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
433+
434+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
435+
436+ virtual Gtk::Widget *newWidget();
437+
438+ void updateIndex();
439+
440+ size_t nodeCount(Geom::PathVector pathvector) const;
441+
442+ Geom::Point pointAtNodeIndex(Geom::PathVector pathvector, size_t index) const;
443+
444+ Geom::Path pathAtNodeIndex(Geom::PathVector pathvector, size_t index) const;
445+
446+ void reset();
447+
448+protected:
449+ virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);
450+
451+private:
452+ ToggleButtonParam from_original_width;
453+ PointParam start;
454+ PointParam end;
455+ ScalarParam first_knot;
456+ ScalarParam last_knot;
457+ bool from_original_width_toggler;
458+ Geom::Point point_a;
459+ Geom::Point point_b;
460+ Geom::PathVector pathvector;
461+ bool append_path;
462+ LPETransform2Pts(const LPETransform2Pts&);
463+ LPETransform2Pts& operator=(const LPETransform2Pts&);
464+};
465+
466+} //namespace LivePathEffect
467+} //namespace Inkscape
468+
469+#endif
470+
471+/*
472+ Local Variables:
473+ mode:c++
474+ c-file-style:"stroustrup"
475+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
476+ indent-tabs-mode:nil
477+ fill-column:99
478+ End:
479+*/
480+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :