1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** \file
3 * LPE <lattice2> implementation
4
5 */
6 /*
7 * Authors:
8 * Johan Engelen <j.b.c.engelen@utwente.nl>
9 * Steren Giannini
10 * No� Falzon
11 * Victor Navez
12 * ~suv
13 * Jabiertxo Arraiza
14 *
15 * Copyright (C) 2007-2008 Authors
16 *
17 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
18 */
19
20 #include <gtkmm.h>
21 #include "live_effects/lpe-lattice2.h"
22 #include "display/curve.h"
23 #include "helper/geom.h"
24 #include <2geom/sbasis-2d.h>
25 #include <2geom/bezier-to-sbasis.h>
26
27 // TODO due to internal breakage in glibmm headers, this must be last:
28 #include <glibmm/i18n.h>
29
30 using namespace Geom;
31
32 namespace Inkscape {
33 namespace LivePathEffect {
34
LPELattice2(LivePathEffectObject * lpeobject)35 LPELattice2::LPELattice2(LivePathEffectObject *lpeobject) :
36 Effect(lpeobject),
37 horizontal_mirror(_("Mirror movements in horizontal"), _("Mirror movements in horizontal"), "horizontal_mirror", &wr, this, false),
38 vertical_mirror(_("Mirror movements in vertical"), _("Mirror movements in vertical"), "vertical_mirror", &wr, this, false),
39 perimetral(_("Use only perimeter"), _("Use only perimeter"), "perimetral", &wr, this, false),
40 live_update(_("Update while moving knots (maybe slow)"), _("Update while moving knots (maybe slow)"), "live_update", &wr, this, true),
41 grid_point_0(_("Control 0:"), _("Control 0 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint0", &wr, this),
42 grid_point_1(_("Control 1:"), _("Control 1 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint1", &wr, this),
43 grid_point_2(_("Control 2:"), _("Control 2 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint2", &wr, this),
44 grid_point_3(_("Control 3:"), _("Control 3 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint3", &wr, this),
45 grid_point_4(_("Control 4:"), _("Control 4 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint4", &wr, this),
46 grid_point_5(_("Control 5:"), _("Control 5 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint5", &wr, this),
47 grid_point_6(_("Control 6:"), _("Control 6 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint6", &wr, this),
48 grid_point_7(_("Control 7:"), _("Control 7 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint7", &wr, this),
49 grid_point_8x9(_("Control 8x9:"), _("Control 8x9 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint8x9", &wr, this),
50 grid_point_10x11(_("Control 10x11:"), _("Control 10x11 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint10x11", &wr, this),
51 grid_point_12(_("Control 12:"), _("Control 12 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint12", &wr, this),
52 grid_point_13(_("Control 13:"), _("Control 13 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint13", &wr, this),
53 grid_point_14(_("Control 14:"), _("Control 14 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint14", &wr, this),
54 grid_point_15(_("Control 15:"), _("Control 15 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint15", &wr, this),
55 grid_point_16(_("Control 16:"), _("Control 16 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint16", &wr, this),
56 grid_point_17(_("Control 17:"), _("Control 17 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint17", &wr, this),
57 grid_point_18(_("Control 18:"), _("Control 18 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint18", &wr, this),
58 grid_point_19(_("Control 19:"), _("Control 19 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint19", &wr, this),
59 grid_point_20x21(_("Control 20x21:"), _("Control 20x21 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint20x21", &wr, this),
60 grid_point_22x23(_("Control 22x23:"), _("Control 22x23 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint22x23", &wr, this),
61 grid_point_24x26(_("Control 24x26:"), _("Control 24x26 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint24x26", &wr, this),
62 grid_point_25x27(_("Control 25x27:"), _("Control 25x27 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint25x27", &wr, this),
63 grid_point_28x30(_("Control 28x30:"), _("Control 28x30 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint28x30", &wr, this),
64 grid_point_29x31(_("Control 29x31:"), _("Control 29x31 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint29x31", &wr, this),
65 grid_point_32x33x34x35(_("Control 32x33x34x35:"), _("Control 32x33x34x35 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint32x33x34x35", &wr, this),
66 expanded(false)
67 {
68 // register all your parameters here, so Inkscape knows which parameters this effect has:
69 registerParameter(&horizontal_mirror);
70 registerParameter(&vertical_mirror);
71 registerParameter(&perimetral);
72 registerParameter(&live_update);
73 registerParameter(&grid_point_0);
74 registerParameter(&grid_point_1);
75 registerParameter(&grid_point_2);
76 registerParameter(&grid_point_3);
77 registerParameter(&grid_point_4);
78 registerParameter(&grid_point_5);
79 registerParameter(&grid_point_6);
80 registerParameter(&grid_point_7);
81 registerParameter(&grid_point_8x9);
82 registerParameter(&grid_point_10x11);
83 registerParameter(&grid_point_12);
84 registerParameter(&grid_point_13);
85 registerParameter(&grid_point_14);
86 registerParameter(&grid_point_15);
87 registerParameter(&grid_point_16);
88 registerParameter(&grid_point_17);
89 registerParameter(&grid_point_18);
90 registerParameter(&grid_point_19);
91 registerParameter(&grid_point_20x21);
92 registerParameter(&grid_point_22x23);
93 registerParameter(&grid_point_24x26);
94 registerParameter(&grid_point_25x27);
95 registerParameter(&grid_point_28x30);
96 registerParameter(&grid_point_29x31);
97 registerParameter(&grid_point_32x33x34x35);
98 apply_to_clippath_and_mask = true;
99 }
100
101 LPELattice2::~LPELattice2()
102 = default;
103
104 Geom::Piecewise<Geom::D2<Geom::SBasis> >
doEffect_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis>> const & pwd2_in)105 LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
106 {
107 PathVector pathv = path_from_piecewise(pwd2_in,0.001);
108 //this is because strange problems with sb2 and LineSegment
109 PathVector cubic = pathv_to_cubicbezier(pathv);
110 if (cubic.empty()) {
111 return pwd2_in;
112 }
113 Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in_linear_and_cubic = paths_to_pw(cubic);
114 D2<SBasis2d> sb2;
115
116 //Initialisation of the sb2
117 for(unsigned dim = 0; dim < 2; dim++) {
118 sb2[dim].us = 3;
119 sb2[dim].vs = 3;
120 const int depth = sb2[dim].us*sb2[dim].vs;
121 sb2[dim].resize(depth, Linear2d(0));
122 }
123
124 //Grouping the point params in a convenient vector
125
126 std::vector<Geom::Point > handles(36);
127
128 handles[0] = grid_point_0;
129 handles[1] = grid_point_1;
130 handles[2] = grid_point_2;
131 handles[3] = grid_point_3;
132 handles[4] = grid_point_4;
133 handles[5] = grid_point_5;
134 handles[6] = grid_point_6;
135 handles[7] = grid_point_7;
136 handles[8] = grid_point_8x9;
137 handles[9] = grid_point_8x9;
138 handles[10] = grid_point_10x11;
139 handles[11] = grid_point_10x11;
140 handles[12] = grid_point_12;
141 handles[13] = grid_point_13;
142 handles[14] = grid_point_14;
143 handles[15] = grid_point_15;
144 handles[16] = grid_point_16;
145 handles[17] = grid_point_17;
146 handles[18] = grid_point_18;
147 handles[19] = grid_point_19;
148 handles[20] = grid_point_20x21;
149 handles[21] = grid_point_20x21;
150 handles[22] = grid_point_22x23;
151 handles[23] = grid_point_22x23;
152 handles[24] = grid_point_24x26;
153 handles[25] = grid_point_25x27;
154 handles[26] = grid_point_24x26;
155 handles[27] = grid_point_25x27;
156 handles[28] = grid_point_28x30;
157 handles[29] = grid_point_29x31;
158 handles[30] = grid_point_28x30;
159 handles[31] = grid_point_29x31;
160 handles[32] = grid_point_32x33x34x35;
161 handles[33] = grid_point_32x33x34x35;
162 handles[34] = grid_point_32x33x34x35;
163 handles[35] = grid_point_32x33x34x35;
164
165 Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
166
167 double width = boundingbox_X.extent();
168 double height = boundingbox_Y.extent();
169
170 //numbering is based on 4 rectangles.16
171 for(unsigned dim = 0; dim < 2; dim++) {
172 Geom::Point dir(0,0);
173 dir[dim] = 1;
174 for(unsigned vi = 0; vi < sb2[dim].vs; vi++) {
175 for(unsigned ui = 0; ui < sb2[dim].us; ui++) {
176 for(unsigned iv = 0; iv < 2; iv++) {
177 for(unsigned iu = 0; iu < 2; iu++) {
178 unsigned corner = iu + 2*iv;
179 unsigned i = ui + vi*sb2[dim].us;
180
181 //This is the offset from the Upperleft point
182 Geom::Point base( (ui + iu*(4-2*ui))*width/4.,
183 (vi + iv*(4-2*vi))*height/4.);
184
185 //Special action for corners
186 if(vi == 0 && ui == 0) {
187 base = Geom::Point(0,0);
188 }
189
190 // i = Upperleft corner of the considerated rectangle
191 // corner = actual corner of the rectangle
192 // origin = Upperleft point
193 double dl = dot((handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
194 sb2[dim][i][corner] = dl/( dim ? height : width )*pow(4.0,ui+vi);
195 }
196 }
197 }
198 }
199 }
200
201 Piecewise<D2<SBasis> > output;
202 output.push_cut(0.);
203 for(unsigned i = 0; i < pwd2_in_linear_and_cubic.size(); i++) {
204 D2<SBasis> B = pwd2_in_linear_and_cubic[i];
205 B[Geom::X] -= origin[Geom::X];
206 B[Geom::X]*= 1/width;
207 B[Geom::Y] -= origin[Geom::Y];
208 B[Geom::Y]*= 1/height;
209 //Here comes the magic
210 D2<SBasis> tB = compose_each(sb2,B);
211 tB[Geom::X] = tB[Geom::X] * width + origin[Geom::X];
212 tB[Geom::Y] = tB[Geom::Y] * height + origin[Geom::Y];
213
214 output.push(tB,i+1);
215 }
216 return output;
217 }
218
219
220 Gtk::Widget *
newWidget()221 LPELattice2::newWidget()
222 {
223 // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
224 Gtk::Box *vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
225
226 vbox->set_border_width(5);
227 vbox->set_homogeneous(false);
228 vbox->set_spacing(6);
229 Gtk::Box * hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL,0));
230 Gtk::Box *vbox_expander = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
231 vbox_expander->set_border_width(0);
232 vbox_expander->set_spacing(2);
233 Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
234 reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
235 reset_button->set_size_request(140,30);
236 vbox->pack_start(*hbox, true,true,2);
237 hbox->pack_start(*reset_button, false, false,2);
238 std::vector<Parameter *>::iterator it = param_vector.begin();
239 while (it != param_vector.end()) {
240 if ((*it)->widget_is_visible) {
241 Parameter * param = *it;
242 Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
243 if(param->param_key == "grid") {
244 widg = nullptr;
245 }
246 Glib::ustring * tip = param->param_getTooltip();
247 if (widg) {
248 if (param->param_key == "horizontal_mirror" ||
249 param->param_key == "vertical_mirror" ||
250 param->param_key == "live_update" ||
251 param->param_key == "perimetral")
252 {
253 vbox->pack_start(*widg, true, true, 2);
254 } else {
255 vbox_expander->pack_start(*widg, true, true, 2);
256 }
257 if (tip) {
258 widg->set_tooltip_text(*tip);
259 } else {
260 widg->set_tooltip_text("");
261 widg->set_has_tooltip(false);
262 }
263 }
264 }
265
266 ++it;
267 }
268
269 expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show Points"))));
270 expander->add(*vbox_expander);
271 expander->set_expanded(expanded);
272 vbox->pack_start(*expander, true, true, 2);
273 expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPELattice2::onExpanderChanged) );
274 if(Gtk::Widget* widg = defaultParamSet()) {
275 vbox->pack_start(*widg, true, true, 2);
276 }
277 return dynamic_cast<Gtk::Widget *>(vbox);
278 }
279
280 void
onExpanderChanged()281 LPELattice2::onExpanderChanged()
282 {
283 expanded = expander->get_expanded();
284 if(expanded) {
285 expander->set_label (Glib::ustring(_("Hide Points")));
286 } else {
287 expander->set_label (Glib::ustring(_("Show Points")));
288 }
289 }
290 void
vertical(PointParam & param_one,PointParam & param_two,Geom::Line vert)291 LPELattice2::vertical(PointParam ¶m_one, PointParam ¶m_two, Geom::Line vert)
292 {
293 Geom::Point A = param_one;
294 Geom::Point B = param_two;
295 double Y = (A[Geom::Y] + B[Geom::Y])/2;
296 A[Geom::Y] = Y;
297 B[Geom::Y] = Y;
298 Geom::Point nearest = vert.pointAt(vert.nearestTime(A));
299 double distance_one = Geom::distance(A,nearest);
300 double distance_two = Geom::distance(B,nearest);
301 double distance_middle = (distance_one + distance_two)/2;
302 if(A[Geom::X] > B[Geom::X]) {
303 distance_middle *= -1;
304 }
305 A[Geom::X] = nearest[Geom::X] - distance_middle;
306 B[Geom::X] = nearest[Geom::X] + distance_middle;
307 param_one.param_setValue(A, live_update);
308 param_two.param_setValue(B, live_update);
309 }
310
311 void
horizontal(PointParam & param_one,PointParam & param_two,Geom::Line horiz)312 LPELattice2::horizontal(PointParam ¶m_one, PointParam ¶m_two, Geom::Line horiz)
313 {
314 Geom::Point A = param_one;
315 Geom::Point B = param_two;
316 double X = (A[Geom::X] + B[Geom::X])/2;
317 A[Geom::X] = X;
318 B[Geom::X] = X;
319 Geom::Point nearest = horiz.pointAt(horiz.nearestTime(A));
320 double distance_one = Geom::distance(A,nearest);
321 double distance_two = Geom::distance(B,nearest);
322 double distance_middle = (distance_one + distance_two)/2;
323 if(A[Geom::Y] > B[Geom::Y]) {
324 distance_middle *= -1;
325 }
326 A[Geom::Y] = nearest[Geom::Y] - distance_middle;
327 B[Geom::Y] = nearest[Geom::Y] + distance_middle;
328 param_one.param_setValue(A, live_update);
329 param_two.param_setValue(B, live_update);
330 }
331
332
333 void
doBeforeEffect(SPLPEItem const * lpeitem)334 LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem)
335 {
336 original_bbox(lpeitem, false, true);
337 setDefaults();
338 if (is_applied) {
339 resetGrid();
340 }
341 Geom::Line vert(grid_point_8x9.param_get_default(),grid_point_10x11.param_get_default());
342 Geom::Line horiz(grid_point_24x26.param_get_default(),grid_point_25x27.param_get_default());
343 if(vertical_mirror) {
344 vertical(grid_point_0, grid_point_1,vert);
345 vertical(grid_point_2, grid_point_3,vert);
346 vertical(grid_point_4, grid_point_5,vert);
347 vertical(grid_point_6, grid_point_7,vert);
348 vertical(grid_point_12, grid_point_13,vert);
349 vertical(grid_point_14, grid_point_15,vert);
350 vertical(grid_point_16, grid_point_17,vert);
351 vertical(grid_point_18, grid_point_19,vert);
352 vertical(grid_point_24x26, grid_point_25x27,vert);
353 vertical(grid_point_28x30, grid_point_29x31,vert);
354 }
355 if(horizontal_mirror) {
356 horizontal(grid_point_0, grid_point_2,horiz);
357 horizontal(grid_point_1, grid_point_3,horiz);
358 horizontal(grid_point_4, grid_point_6,horiz);
359 horizontal(grid_point_5, grid_point_7,horiz);
360 horizontal(grid_point_8x9, grid_point_10x11,horiz);
361 horizontal(grid_point_12, grid_point_14,horiz);
362 horizontal(grid_point_13, grid_point_15,horiz);
363 horizontal(grid_point_16, grid_point_18,horiz);
364 horizontal(grid_point_17, grid_point_19,horiz);
365 horizontal(grid_point_20x21, grid_point_22x23,horiz);
366 }
367 if (perimetral) {
368 grid_point_16.param_hide_knot(true);
369 grid_point_20x21.param_hide_knot(true);
370 grid_point_17.param_hide_knot(true);
371 grid_point_28x30.param_hide_knot(true);
372 grid_point_32x33x34x35.param_hide_knot(true);
373 grid_point_29x31.param_hide_knot(true);
374 grid_point_18.param_hide_knot(true);
375 grid_point_22x23.param_hide_knot(true);
376 grid_point_19.param_hide_knot(true);
377 grid_point_16.param_set_default();
378 grid_point_20x21.param_set_default();
379 grid_point_17.param_set_default();
380 grid_point_28x30.param_set_default();
381 grid_point_32x33x34x35.param_set_default();
382 grid_point_29x31.param_set_default();
383 grid_point_18.param_set_default();
384 grid_point_22x23.param_set_default();
385 grid_point_19.param_set_default();
386 } else {
387 grid_point_16.param_hide_knot(false);
388 grid_point_20x21.param_hide_knot(false);
389 grid_point_17.param_hide_knot(false);
390 grid_point_28x30.param_hide_knot(false);
391 grid_point_32x33x34x35.param_hide_knot(false);
392 grid_point_29x31.param_hide_knot(false);
393 grid_point_18.param_hide_knot(false);
394 grid_point_22x23.param_hide_knot(false);
395 grid_point_19.param_hide_knot(false);
396 }
397 }
398
399 void
setDefaults()400 LPELattice2::setDefaults()
401 {
402 Geom::Point gp0((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
403 (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
404
405 Geom::Point gp1((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
406 (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
407
408 Geom::Point gp2((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
409 (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
410
411 Geom::Point gp3((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
412 (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
413
414 Geom::Point gp4((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
415 (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
416
417 Geom::Point gp5((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
418 (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
419
420 Geom::Point gp6((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
421 (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
422
423 Geom::Point gp7((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
424 (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
425
426 Geom::Point gp8x9((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
427 (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
428
429 Geom::Point gp10x11((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
430 (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
431
432 Geom::Point gp12((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
433 (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
434
435 Geom::Point gp13((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
436 (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
437
438 Geom::Point gp14((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
439 (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
440
441 Geom::Point gp15((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
442 (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
443
444 Geom::Point gp16((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
445 (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
446
447 Geom::Point gp17((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
448 (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
449
450 Geom::Point gp18((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
451 (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
452
453 Geom::Point gp19((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
454 (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
455
456 Geom::Point gp20x21((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
457 (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
458
459 Geom::Point gp22x23((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
460 (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
461
462 Geom::Point gp24x26((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
463 (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
464
465 Geom::Point gp25x27((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
466 (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
467
468 Geom::Point gp28x30((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
469 (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
470
471 Geom::Point gp29x31((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
472 (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
473
474 Geom::Point gp32x33x34x35((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
475 (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
476
477 grid_point_0.param_update_default(gp0);
478 grid_point_1.param_update_default(gp1);
479 grid_point_2.param_update_default(gp2);
480 grid_point_3.param_update_default(gp3);
481 grid_point_4.param_update_default(gp4);
482 grid_point_5.param_update_default(gp5);
483 grid_point_6.param_update_default(gp6);
484 grid_point_7.param_update_default(gp7);
485 grid_point_8x9.param_update_default(gp8x9);
486 grid_point_10x11.param_update_default(gp10x11);
487 grid_point_12.param_update_default(gp12);
488 grid_point_13.param_update_default(gp13);
489 grid_point_14.param_update_default(gp14);
490 grid_point_15.param_update_default(gp15);
491 grid_point_16.param_update_default(gp16);
492 grid_point_17.param_update_default(gp17);
493 grid_point_18.param_update_default(gp18);
494 grid_point_19.param_update_default(gp19);
495 grid_point_20x21.param_update_default(gp20x21);
496 grid_point_22x23.param_update_default(gp22x23);
497 grid_point_24x26.param_update_default(gp24x26);
498 grid_point_25x27.param_update_default(gp25x27);
499 grid_point_28x30.param_update_default(gp28x30);
500 grid_point_29x31.param_update_default(gp29x31);
501 grid_point_32x33x34x35.param_update_default(gp32x33x34x35);
502 grid_point_0.param_set_liveupdate(live_update);
503 grid_point_1.param_set_liveupdate(live_update);
504 grid_point_2.param_set_liveupdate(live_update);
505 grid_point_3.param_set_liveupdate(live_update);
506 grid_point_4.param_set_liveupdate(live_update);
507 grid_point_5.param_set_liveupdate(live_update);
508 grid_point_6.param_set_liveupdate(live_update);
509 grid_point_7.param_set_liveupdate(live_update);
510 grid_point_8x9.param_set_liveupdate(live_update);
511 grid_point_10x11.param_set_liveupdate(live_update);
512 grid_point_12.param_set_liveupdate(live_update);
513 grid_point_13.param_set_liveupdate(live_update);
514 grid_point_14.param_set_liveupdate(live_update);
515 grid_point_15.param_set_liveupdate(live_update);
516 grid_point_16.param_set_liveupdate(live_update);
517 grid_point_17.param_set_liveupdate(live_update);
518 grid_point_18.param_set_liveupdate(live_update);
519 grid_point_19.param_set_liveupdate(live_update);
520 grid_point_20x21.param_set_liveupdate(live_update);
521 grid_point_22x23.param_set_liveupdate(live_update);
522 grid_point_24x26.param_set_liveupdate(live_update);
523 grid_point_25x27.param_set_liveupdate(live_update);
524 grid_point_28x30.param_set_liveupdate(live_update);
525 grid_point_29x31.param_set_liveupdate(live_update);
526 grid_point_32x33x34x35.param_set_liveupdate(live_update);
527 }
528
529 void
resetGrid()530 LPELattice2::resetGrid()
531 {
532 grid_point_0.param_set_default();
533 grid_point_1.param_set_default();
534 grid_point_2.param_set_default();
535 grid_point_3.param_set_default();
536 grid_point_4.param_set_default();
537 grid_point_5.param_set_default();
538 grid_point_6.param_set_default();
539 grid_point_7.param_set_default();
540 grid_point_8x9.param_set_default();
541 grid_point_10x11.param_set_default();
542 grid_point_12.param_set_default();
543 grid_point_13.param_set_default();
544 grid_point_14.param_set_default();
545 grid_point_15.param_set_default();
546 grid_point_16.param_set_default();
547 grid_point_17.param_set_default();
548 grid_point_18.param_set_default();
549 grid_point_19.param_set_default();
550 grid_point_20x21.param_set_default();
551 grid_point_22x23.param_set_default();
552 grid_point_24x26.param_set_default();
553 grid_point_25x27.param_set_default();
554 grid_point_28x30.param_set_default();
555 grid_point_29x31.param_set_default();
556 grid_point_32x33x34x35.param_set_default();
557 }
558
559 void
resetDefaults(SPItem const * item)560 LPELattice2::resetDefaults(SPItem const* item)
561 {
562 Effect::resetDefaults(item);
563 original_bbox(SP_LPE_ITEM(item), false, true);
564 setDefaults();
565 resetGrid();
566 }
567
568 void
calculateCurve(Geom::Point a,Geom::Point b,SPCurve * c,bool horizontal,bool move)569 LPELattice2::calculateCurve(Geom::Point a,Geom::Point b, SPCurve* c, bool horizontal, bool move)
570 {
571 using Geom::X;
572 using Geom::Y;
573 if(move) c->moveto(a);
574 Geom::Point cubic1 = a + (1./3)* (b - a);
575 Geom::Point cubic2 = b + (1./3)* (a - b);
576 if(horizontal) c->curveto(Geom::Point(cubic1[X],a[Y]),Geom::Point(cubic2[X],b[Y]),b);
577 else c->curveto(Geom::Point(a[X],cubic1[Y]),Geom::Point(b[X],cubic2[Y]),b);
578 }
579
580 void
addCanvasIndicators(SPLPEItem const *,std::vector<Geom::PathVector> & hp_vec)581 LPELattice2::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
582 {
583 hp_vec.clear();
584
585 SPCurve *c = new SPCurve();
586 if (perimetral) {
587 calculateCurve(grid_point_0,grid_point_4, c,true, true);
588 calculateCurve(grid_point_4,grid_point_8x9, c,true, false);
589 calculateCurve(grid_point_8x9,grid_point_5, c,true, false);
590 calculateCurve(grid_point_5,grid_point_1, c,true, false);
591
592 calculateCurve(grid_point_1,grid_point_13, c, false, true);
593 calculateCurve(grid_point_13,grid_point_25x27, c,false, false);
594 calculateCurve(grid_point_25x27,grid_point_15, c,false, false);
595 calculateCurve(grid_point_15,grid_point_3, c, false, false);
596
597 calculateCurve(grid_point_2,grid_point_6, c,true, true);
598 calculateCurve(grid_point_6,grid_point_10x11, c,true, false);
599 calculateCurve(grid_point_10x11,grid_point_7, c,true, false);
600 calculateCurve(grid_point_7,grid_point_3, c,true, false);
601
602 calculateCurve(grid_point_0,grid_point_12, c,false, true);
603 calculateCurve(grid_point_12,grid_point_24x26, c,false, false);
604 calculateCurve(grid_point_24x26,grid_point_14, c,false, false);
605 calculateCurve(grid_point_14,grid_point_2, c,false, false);
606
607 } else {
608 calculateCurve(grid_point_0,grid_point_4, c,true, true);
609 calculateCurve(grid_point_4,grid_point_8x9, c,true, false);
610 calculateCurve(grid_point_8x9,grid_point_5, c,true, false);
611 calculateCurve(grid_point_5,grid_point_1, c,true, false);
612
613 calculateCurve(grid_point_12,grid_point_16, c,true, true);
614 calculateCurve(grid_point_16,grid_point_20x21, c,true, false);
615 calculateCurve(grid_point_20x21,grid_point_17, c,true, false);
616 calculateCurve(grid_point_17,grid_point_13, c,true, false);
617
618 calculateCurve(grid_point_24x26,grid_point_28x30, c,true, true);
619 calculateCurve(grid_point_28x30,grid_point_32x33x34x35, c,true, false);
620 calculateCurve(grid_point_32x33x34x35,grid_point_29x31, c,true, false);
621 calculateCurve(grid_point_29x31,grid_point_25x27, c,true, false);
622
623 calculateCurve(grid_point_14,grid_point_18, c,true, true);
624 calculateCurve(grid_point_18,grid_point_22x23, c,true, false);
625 calculateCurve(grid_point_22x23,grid_point_19, c,true, false);
626 calculateCurve(grid_point_19,grid_point_15, c,true, false);
627
628 calculateCurve(grid_point_2,grid_point_6, c,true, true);
629 calculateCurve(grid_point_6,grid_point_10x11, c,true, false);
630 calculateCurve(grid_point_10x11,grid_point_7, c,true, false);
631 calculateCurve(grid_point_7,grid_point_3, c,true, false);
632
633 calculateCurve(grid_point_0,grid_point_12, c,false, true);
634 calculateCurve(grid_point_12,grid_point_24x26, c,false, false);
635 calculateCurve(grid_point_24x26,grid_point_14, c,false, false);
636 calculateCurve(grid_point_14,grid_point_2, c,false, false);
637
638 calculateCurve(grid_point_4,grid_point_16, c,false, true);
639 calculateCurve(grid_point_16,grid_point_28x30, c,false, false);
640 calculateCurve(grid_point_28x30,grid_point_18, c,false, false);
641 calculateCurve(grid_point_18,grid_point_6, c,false, false);
642
643 calculateCurve(grid_point_8x9,grid_point_20x21, c,false, true);
644 calculateCurve(grid_point_20x21,grid_point_32x33x34x35, c,false, false);
645 calculateCurve(grid_point_32x33x34x35,grid_point_22x23, c,false, false);
646 calculateCurve(grid_point_22x23,grid_point_10x11, c,false, false);
647
648 calculateCurve(grid_point_5,grid_point_17, c, false, true);
649 calculateCurve(grid_point_17,grid_point_29x31, c,false, false);
650 calculateCurve(grid_point_29x31,grid_point_19, c,false, false);
651 calculateCurve(grid_point_19,grid_point_7, c,false, false);
652
653 calculateCurve(grid_point_1,grid_point_13, c, false, true);
654 calculateCurve(grid_point_13,grid_point_25x27, c,false, false);
655 calculateCurve(grid_point_25x27,grid_point_15, c,false, false);
656 calculateCurve(grid_point_15,grid_point_3, c, false, false);
657 }
658 hp_vec.push_back(c->get_pathvector());
659 }
660
661
662 /* ######################## */
663
664 } //namespace LivePathEffect
665 } /* namespace Inkscape */
666
667
668
669
670 /*
671 Local Variables:
672 mode:c++
673 c-file-style:"stroustrup"
674 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
675 indent-tabs-mode:nil
676 fill-column:99
677 End:
678 */
679 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
680