Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
nodesatellitesarray.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Author(s):
4 * Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
5 *
6 * Copyright (C) 2014 Author(s)
7 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8 */
9
10#include "nodesatellitesarray.h"
11
12#include <glibmm/i18n.h>
13
15
17#include "inkscape.h"
18#include "preferences.h"
19
21#include "helper/geom.h"
22#include "live_effects/effect.h"
24#include "object/sp-lpe-item.h"
26#include "ui/knot/knot-holder.h"
27#include "ui/shape-editor.h"
28#include "ui/tools/node-tool.h"
29
30
31// TODO due to internal breakage in glibmm headers,
32// this has to be included last.
33
34namespace Inkscape {
35
36namespace LivePathEffect {
37
38NodeSatelliteArrayParam::NodeSatelliteArrayParam(const Glib::ustring &label, const Glib::ustring &tip,
39 const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr,
40 Effect *effect)
41 : ArrayParam<std::vector<NodeSatellite>>(label, tip, key, wr, effect, 0)
42{
44}
45
47{
48 _knot_shape = shape;
49 _knot_color = color;
50}
51
62
64{
65 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
66 if (desktop && !_global_knot_hide) {
67 // TODO: move this code to the Node Tool
69 if (nt) {
70 for (auto &_shape_editor : nt->_shape_editors) {
71 Inkscape::UI::ShapeEditor *shape_editor = _shape_editor.second.get();
72 if (shape_editor && shape_editor->lpeknotholder) {
73 // TODO: move this code to ShapeEditor
74 SPItem *item = shape_editor->lpeknotholder->item;
75 shape_editor->lpeknotholder.reset();
76 shape_editor->set_item(item);
77 }
78 }
79 }
80 }
81}
82void NodeSatelliteArrayParam::setUseDistance(bool use_knot_distance)
83{
84 _use_distance = use_knot_distance;
85}
86
88{
89 _current_zoom = current_zoom;
90}
91
93{
94 _global_knot_hide = global_knot_hide;
95}
96
101
103{
105 return;
106 }
107
108 if (!_hp.empty()) {
109 _hp.clear();
110 }
112 if (pathv.empty()) {
113 return;
114 }
115 if (mirror == true) {
116 _hp.clear();
117 }
119 for (size_t i = 0; i < _vector.size(); ++i) {
120 for (size_t j = 0; j < _vector[i].size(); ++j) {
121 if (_vector[i][j].hidden || // Ignore if hidden
122 (!_vector[i][j].has_mirror && mirror == true) || // Ignore if not have mirror and we are in mirror
123 // loop
124 _vector[i][j].amount == 0 || // no helper in 0 value
125 j >= count_path_nodes(pathv[i]) || // ignore last nodesatellite in open paths with fillet chamfer
126 // effect
127 (!pathv[i].closed() && j == 0) || // ignore first nodesatellites on open paths
128 count_path_nodes(pathv[i]) == 2) {
129 continue;
130 }
131 Geom::Curve *curve_in = pathv[i][j].duplicate();
132 double pos = 0;
133 bool overflow = false;
134 double size_out = _vector[i][j].arcDistance(*curve_in);
135 double length_out = curve_in->length();
136 gint previous_index =
137 j - 1; // Always are previous index because we skip first nodesatellite on open paths
138 if (j == 0 && pathv[i].closed()) {
139 previous_index = count_path_nodes(pathv[i]) - 1;
140 }
141 if ( previous_index < 0 ) {
142 return;
143 }
144 double length_in = pathv.curveAt(previous_index).length();
145 if (mirror) {
146 curve_in = const_cast<Geom::Curve *>(&pathv.curveAt(previous_index));
147 pos = _vector[i][j].time(size_out, true, *curve_in);
148 if (length_out < size_out) {
149 overflow = true;
150 }
151 } else {
152 pos = _vector[i][j].time(*curve_in);
153 if (length_in < size_out) {
154 overflow = true;
155 }
156 }
157 if (pos <= 0 || pos >= 1) {
158 continue;
159 }
160 }
161 }
162 }
163 if (mirror) {
165 }
166}
171
172void NodeSatelliteArrayParam::addCanvasIndicators(SPLPEItem const * /*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
173{
174 hp_vec.push_back(_hp);
175}
176
178{
180
181 if (prefs->getBool("/options/transform/rectcorners", true)) {
182 for (auto & i : _vector) {
183 for (auto & j : i) {
184 if (!j.is_time && j.amount > 0) {
185 j.amount = j.amount * ((postmul.expansionX() + postmul.expansionY()) / 2);
186 }
187 }
188 }
190 }
191}
192
194{
196 return;
197 }
198 size_t index = 0;
199 for (size_t i = 0; i < _vector.size(); ++i) {
200 for (size_t j = 0; j < _vector[i].size(); ++j) {
201 if (!_vector[i][j].has_mirror && mirror) {
202 continue;
203 }
204 NodeSatelliteType type = _vector[i][j].nodesatellite_type;
205 if (mirror && i == 0 && j == 0) {
207 }
208 using namespace Geom;
209 //If is for filletChamfer effect...
211 const gchar *tip;
212 if (type == CHAMFER) {
213 tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
214 "<b>Shift+Click</b> open dialog, "
215 "<b>Ctrl+Alt+Click</b> reset");
216 } else if (type == INVERSE_CHAMFER) {
217 tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
218 "<b>Shift+Click</b> open dialog, "
219 "<b>Ctrl+Alt+Click</b> reset");
220 } else if (type == INVERSE_FILLET) {
221 tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggles type, "
222 "<b>Shift+Click</b> open dialog, "
223 "<b>Ctrl+Alt+Click</b> reset");
224 } else {
225 tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggles type, "
226 "<b>Shift+Click</b> open dialog, "
227 "<b>Ctrl+Alt+Click</b> reset");
228 }
230 e->create(nullptr, item, knotholder, Inkscape::CANVAS_ITEM_CTRL_TYPE_LPE, "LPE:Chamfer",
231 tip, _knot_color);
232 knotholder->add(e);
233 }
234 index++;
235 }
236 }
237 if (mirror) {
238 addKnotHolderEntities(knotholder, item, false);
239 }
240}
241
243{
246 for (size_t i = 0; i < nodesatellites.size(); ++i) {
247 for (size_t j = 0; j < nodesatellites[i].size(); ++j) {
248 Geom::Curve const &curve_in = pathv[i][j];
250 _vector[i][j].amount = amount;
251 _vector[i][j].setSelected(true);
252 } else {
253 _vector[i][j].setSelected(false);
254 }
255 }
256 }
257}
258
263
268
270 Geom::Point const &/*origin*/,
271 guint state)
272{
274 return;
275 }
276 size_t total_nodesatellites = _pparam->_last_pathvector_nodesatellites->getTotalNodeSatellites();
277 bool is_mirror = false;
278 size_t index = _index;
279 if (_index >= total_nodesatellites) {
280 index = _index - total_nodesatellites;
281 is_mirror = true;
282 }
283 std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_nodesatellites->getIndexData(index);
284 size_t satelite_index = index_data.first;
285 size_t subsatelite_index = index_data.second;
286 Geom::Point s = p;
287 if (!valid_index(satelite_index, subsatelite_index)) {
288 return;
289 }
290 NodeSatellite nodesatellite = _pparam->_vector[satelite_index][subsatelite_index];
292 if (nodesatellite.hidden ||
293 (!pathv[satelite_index].closed() &&
294 (subsatelite_index == 0 || // ignore first nodesatellites on open paths
295 count_path_nodes(pathv[satelite_index]) - 1 == subsatelite_index))) // ignore last nodesatellite in open paths
296 // with fillet chamfer effect
297 {
298 return;
299 }
300 gint previous_index = subsatelite_index - 1;
301 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
302 previous_index = count_path_nodes(pathv[satelite_index]) - 1;
303 }
304 if ( previous_index < 0 ) {
305 return;
306 }
307 Geom::Curve const &curve_in = pathv[satelite_index][previous_index];
308 double mirror_time = Geom::nearest_time(s, curve_in);
309 Geom::Point mirror = curve_in.pointAt(mirror_time);
310 double normal_time = Geom::nearest_time(s, pathv[satelite_index][subsatelite_index]);
311 Geom::Point normal = pathv[satelite_index][subsatelite_index].pointAt(normal_time);
312 double distance_mirror = Geom::distance(mirror,s);
313 double distance_normal = Geom::distance(normal,s);
314 if ((normal_time == 0 && !is_mirror) ||
315 (mirror_time == 1 && is_mirror) ||
316 Geom::are_near(s, pathv[satelite_index][subsatelite_index].initialPoint(), 1.5 / _pparam->_current_zoom))
317 {
318 nodesatellite.amount = 0;
319 } else if (distance_mirror < distance_normal) {
320 double time_start = 0;
322 time_start = nodesatellites[satelite_index][previous_index].time(curve_in);
323 if (time_start > mirror_time) {
324 mirror_time = time_start;
325 }
326 double size = arcLengthAt(mirror_time, curve_in);
327 double amount = curve_in.length() - size;
328 if (nodesatellite.is_time) {
329 amount = timeAtArcLength(amount, pathv[satelite_index][subsatelite_index]);
330 }
331 if (_set_circle && time_start < 0.1001) {
332 return;
333 }
334 nodesatellite.amount = amount;
335 } else {
336 nodesatellite.setPosition(s, pathv[satelite_index][subsatelite_index]);
337 }
339 filletchamfer->helperpath = true;
340 _pparam->updateAmmount(nodesatellite.amount);
341 _pparam->_vector[satelite_index][subsatelite_index] = nodesatellite;
342 if (!_updating) {
343 Geom::Point b = knot_get();
344 Geom::Point a = snap_knot_position(b, state);
345 if (!Geom::are_near(b,a,0.001)) {
346 _updating = true;
347 knot_set(a, Geom::Point(), state);
348 knot_get();
349 _updating = false;
350 }
351 }
352 sp_lpe_item_update_patheffect(cast<SPLPEItem>(item), false, false);
353}
354
355void
357{
359 return;
360 }
362 if (filletchamfer) {
363 filletchamfer->helperpath = false;
364 filletchamfer->makeUndoDone(_("Move handle"));
365 }
366}
367
369{
372 }
373 Geom::Point tmp_point;
374 size_t total_nodesatellites = _pparam->_last_pathvector_nodesatellites->getTotalNodeSatellites();
375 bool is_mirror = false;
376 size_t index = _index;
377 if (_index >= total_nodesatellites) {
378 index = _index - total_nodesatellites;
379 is_mirror = true;
380 }
381 std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_nodesatellites->getIndexData(index);
382 size_t satelite_index = index_data.first;
383 size_t subsatelite_index = index_data.second;
384 if (!valid_index(satelite_index, subsatelite_index)) {
386 }
387 NodeSatellite nodesatellite = _pparam->_vector[satelite_index][subsatelite_index];
389 if (nodesatellite.hidden ||
390 (!pathv[satelite_index].closed() &&
391 (subsatelite_index == 0 || subsatelite_index == count_path_nodes(pathv[satelite_index]) -
392 1))) // ignore first and last nodesatellites on open paths
393 {
395 }
396 Geom::Point contracted = Geom::Point();
397 bool pathdir = Geom::path_direction(pathv[satelite_index]);
398 gint previous_index = subsatelite_index - 1;
399 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
400 previous_index = count_path_nodes(pathv[satelite_index]) - 1;
401 }
402 if (previous_index < 0 || subsatelite_index > pathv[satelite_index].size_open()) {
404 }
405 auto const &ssat_path = pathv[satelite_index][subsatelite_index];
406 auto const &prev_path = pathv[satelite_index][previous_index ];
407 Geom::Curve const &curve_in = pathv[satelite_index][previous_index];
408 double s = nodesatellite.arcDistance(ssat_path);
409 if (Geom::are_near(ssat_path.length(),0, 0.5) ||
410 Geom::are_near(prev_path.length(), 0, 0.5))
411 {
413 }
414 double t = nodesatellite.time(s, true, curve_in);
415 if (t > 1) {
416 t = 1;
417 }
418 if (t < 0) {
419 t = 0;
420 }
421 double time_start = 0;
422 time_start = _pparam->_last_pathvector_nodesatellites->getNodeSatellites()[satelite_index][previous_index].time(
423 curve_in);
424 if (time_start > t) {
425 t = time_start;
426 }
427 tmp_point = (curve_in).pointAt(t);
428 Geom::Affine itemtransform = cast<SPLPEItem>(item)->i2doc_affine();
429 Geom::Path segment(curve_in.initialPoint());
430 segment.append(curve_in);
431 segment = segment.portion(0,t);
432 segment *= itemtransform;
433 Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&segment[0]);
434 Geom::Ray ray(segment.finalPoint(), segment.initialPoint());
435 if (cubic) {
436 ray.setPoints(segment.finalPoint(), (*cubic)[2]);
437 }
438 double angle = ray.angle();
439 Geom::Point other = tmp_point;
440 tmp_point = nodesatellite.getPosition(ssat_path);
441 segment.clear();
442 segment.append(ssat_path);
443 segment = segment.portion(Geom::nearest_time(tmp_point,segment), 1);
444 segment *= itemtransform;
445 Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&segment[0]);
446 Geom::Ray ray2(segment.initialPoint(), segment.finalPoint());
447 if (cubic2) {
448 ray2.setPoints(segment.initialPoint(), (*cubic2)[1]);
449 }
450 bool ccw_toggle = Geom::cross(curve_in.finalPoint() - other, tmp_point - other) < 0;
451 double angle_between = Geom::angle_between(ray, ray2, ccw_toggle);
452
453 if (!is_mirror) {
454 angle = ray2.angle() + Geom::rad_from_deg(180);
455 contracted = ssat_path.pointAt(0.1);
456 }
457 if (is_mirror) {
458 tmp_point = other;
459 }
460 knot->show();
461 if (pathdir) {
462 angle -= Geom::rad_from_deg(180);
463 }
464 if (Geom::deg_from_rad(angle_between) > 180) {
465 angle += Geom::rad_from_deg(180);
466 }
467 /* if (itemtransform.flips()) {
468 angle += Geom::rad_from_deg(180);
469 } */
470
471 knot->setAngle(angle + Geom::rad_from_deg(90));
474 if (nodesatellite.amount == 0) {
475 if (is_mirror) {
476 knot->hide();
477 } else {
478 tmp_point = contracted;
479 _set_circle = true;
482 }
483 }
484
485 if (_pparam->_current_zoom &&
486 (Geom::are_near(ssat_path.pointAt(0), ssat_path.pointAt(0.1), 0.5 / _pparam->_current_zoom) ||
487 Geom::are_near(prev_path.pointAt(0), prev_path.pointAt(0.1), 0.5 / _pparam->_current_zoom)))
488 {
489 knot->hide();
490 }
491 knot->updateCtrl();
492 return tmp_point;
493}
494
496{
498 return;
499 }
500 size_t total_nodesatellites = _pparam->_last_pathvector_nodesatellites->getTotalNodeSatellites();
501 bool is_mirror = false;
502 size_t index = _index;
503 if (_index >= total_nodesatellites) {
504 index = _index - total_nodesatellites;
505 is_mirror = true;
506 }
507 std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_nodesatellites->getIndexData(index);
508 size_t satelite_index = index_data.first;
509 size_t subsatelite_index = index_data.second;
510 if (!valid_index(satelite_index, subsatelite_index)) {
511 return;
512 }
514 if (!pathv[satelite_index].closed() &&
515 (subsatelite_index == 0 ||
516 count_path_nodes(pathv[satelite_index]) - 1 == subsatelite_index)) // ignore last nodesatellite in open paths
517 // with fillet chamfer effect
518 {
519 return;
520 }
521 if (state & GDK_CONTROL_MASK) {
522 if (state & GDK_ALT_MASK) {
523 _pparam->_vector[satelite_index][subsatelite_index].amount = 0.0;
524 sp_lpe_item_update_patheffect(cast<SPLPEItem>(item), false, false);
525 } else {
526 using namespace Geom;
527 NodeSatelliteType type = _pparam->_vector[satelite_index][subsatelite_index].nodesatellite_type;
528 switch (type) {
529 case FILLET:
530 type = INVERSE_FILLET;
531 break;
532 case INVERSE_FILLET:
533 type = CHAMFER;
534 break;
535 case CHAMFER:
536 type = INVERSE_CHAMFER;
537 break;
538 default:
539 type = FILLET;
540 break;
541 }
542 _pparam->_vector[satelite_index][subsatelite_index].nodesatellite_type = type;
543 sp_lpe_item_update_patheffect(cast<SPLPEItem>(item), false, false);
544 const gchar *tip;
545 if (type == CHAMFER) {
546 tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
547 "<b>Shift+Click</b> open dialog, "
548 "<b>Ctrl+Alt+Click</b> resets");
549 } else if (type == INVERSE_CHAMFER) {
550 tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
551 "<b>Shift+Click</b> open dialog, "
552 "<b>Ctrl+Alt+Click</b> resets");
553 } else if (type == INVERSE_FILLET) {
554 tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggles type, "
555 "<b>Shift+Click</b> open dialog, "
556 "<b>Ctrl+Alt+Click</b> resets");
557 } else {
558 tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggles type, "
559 "<b>Shift+Click</b> open dialog, "
560 "<b>Ctrl+Alt+Click</b> resets");
561 }
562 this->knot->setTip(tip);
563 this->knot->show();
564 }
565 } else if (state & GDK_SHIFT_MASK) {
566 double amount = _pparam->_vector[satelite_index][subsatelite_index].amount;
567 gint previous_index = subsatelite_index - 1;
568 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
569 previous_index = count_path_nodes(pathv[satelite_index]) - 1;
570 }
571 if ( previous_index < 0 ) {
572 return;
573 }
574 if (!_pparam->_use_distance && !_pparam->_vector[satelite_index][subsatelite_index].is_time) {
575 amount = _pparam->_vector[satelite_index][subsatelite_index].lenToRad(
576 amount, pathv[satelite_index][previous_index], pathv[satelite_index][subsatelite_index],
577 _pparam->_vector[satelite_index][previous_index]);
578 }
579 bool aprox = false;
580 Geom::D2<Geom::SBasis> d2_out = pathv[satelite_index][subsatelite_index].toSBasis();
581 Geom::D2<Geom::SBasis> d2_in = pathv[satelite_index][previous_index].toSBasis();
582 aprox = ((d2_in)[0].degreesOfFreedom() != 2 ||
583 d2_out[0].degreesOfFreedom() != 2) &&
585 ? true
586 : false;
588 this->desktop, amount, this, _pparam->_use_distance, aprox,
589 _pparam->_vector[satelite_index][subsatelite_index]);
590 }
591}
592
594{
596 return;
597 }
598 size_t total_nodesatellites = _pparam->_last_pathvector_nodesatellites->getTotalNodeSatellites();
599 bool is_mirror = false;
600 size_t index = _index;
601 if (_index >= total_nodesatellites) {
602 index = _index - total_nodesatellites;
603 is_mirror = true;
604 }
605 std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_nodesatellites->getIndexData(index);
606 size_t satelite_index = index_data.first;
607 size_t subsatelite_index = index_data.second;
608 if (!valid_index(satelite_index, subsatelite_index)) {
609 return;
610 }
612 if (nodesatellite.hidden ||
613 (!pathv[satelite_index].closed() &&
614 (subsatelite_index == 0 ||
615 count_path_nodes(pathv[satelite_index]) - 1 == subsatelite_index))) // ignore last nodesatellite in open paths
616 // with fillet chamfer effect
617 {
618 return;
619 }
620 double amount = nodesatellite.amount;
621 double max_amount = amount;
622 if (!_pparam->_use_distance && !nodesatellite.is_time) {
623 gint previous_index = subsatelite_index - 1;
624 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
625 previous_index = count_path_nodes(pathv[satelite_index]) - 1;
626 }
627 if ( previous_index < 0 ) {
628 return;
629 }
630 amount = _pparam->_vector[satelite_index][subsatelite_index].radToLen(
631 amount, pathv[satelite_index][previous_index], pathv[satelite_index][subsatelite_index]);
632 if (max_amount > 0 && amount == 0) {
633 amount = _pparam->_vector[satelite_index][subsatelite_index].amount;
634 }
635 }
636 nodesatellite.amount = amount;
637 _pparam->_vector[satelite_index][subsatelite_index] = nodesatellite;
640}
641
642} /* namespace LivePathEffect */
643
644} /* namespace Inkscape */
645
646/*
647 Local Variables:
648 mode:c++
649 c-file-style:"stroustrup"
650 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
651 indent-tabs-mode:nil
652 fill-column:99
653 End:
654*/
655// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
Point origin
Definition aa.cpp:227
Enums for CanvasItems.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord expansionX() const
Calculates the amount of x-scaling imparted by the Affine.
Definition affine.cpp:64
Coord expansionY() const
Calculates the amount of y-scaling imparted by the Affine.
Definition affine.cpp:71
Bezier curve with compile-time specified order.
Abstract continuous curve on a plane defined on [0,1].
Definition curve.h:78
virtual Point initialPoint() const =0
Retrieve the start of the curve.
virtual Point finalPoint() const =0
Retrieve the end of the curve.
virtual Coord length(Coord tolerance=0.01) const
Compute the arc length of this curve.
Definition curve.cpp:56
virtual Point pointAt(Coord t) const
Evaluate the curve at a specified time value.
Definition curve.h:110
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
Sequence of subpaths.
Definition pathvector.h:122
Point pointAt(Coord t) const
Curve const & curveAt(Coord t, Coord *rest=NULL) const
void clear()
Remove all paths from the vector.
Definition pathvector.h:195
bool empty() const
Check whether the vector contains any paths.
Definition pathvector.h:145
Sequence of contiguous curves, aka spline.
Definition path.h:353
Point finalPoint() const
Get the last point in the path.
Definition path.h:709
void clear()
Remove all curves from the path.
Definition path.cpp:337
Path portion(Coord f, Coord t) const
Definition path.h:645
void append(Curve *curve)
Add a new curve to the end of the path.
Definition path.h:750
Point initialPoint() const
Get the first point in the path.
Definition path.h:705
Two-dimensional point that doubles as a vector.
Definition point.h:66
Straight ray from a specific point to infinity.
Definition ray.h:53
void setPoints(Point const &a, Point const &b)
Definition ray.h:75
Coord angle() const
Definition ray.h:73
void param_set_and_write_new_value(std::vector< std::vector< NodeSatellite > > const &new_vector)
Definition array.h:92
void param_setValue(std::vector< std::vector< NodeSatellite > > const &new_vector)
Definition array.h:84
std::vector< std::vector< NodeSatellite > > _vector
Definition array.h:104
bool isNodePointSelected(Geom::Point const &nodePoint) const
Definition effect.cpp:1258
void makeUndoDone(Glib::ustring message)
Definition effect.cpp:1521
FilletChamferKnotHolderEntity(NodeSatelliteArrayParam *p, size_t index)
void knot_ungrabbed(Geom::Point const &p, Geom::Point const &origin, guint state) override
void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) override
bool valid_index(size_t index, size_t subindex) const
Checks whether the index falls within the size of the parameter's vector.
void set_oncanvas_looks(Inkscape::CanvasItemCtrlShape shape, uint32_t color)
void addKnotHolderEntities(KnotHolder *knotholder, SPItem *item) override
void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector< Geom::PathVector > &hp_vec) override
void setPathVectorNodeSatellites(PathVectorNodeSatellites *pathVectorNodeSatellites, bool write=true)
void param_transform_multiply(Geom::Affine const &postmul, bool) override
NodeSatelliteArrayParam(const Glib::ustring &label, const Glib::ustring &tip, const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr, Effect *effect)
virtual void param_widget_is_visible(bool is_visible)
Definition parameter.h:69
Preference storage class.
Definition preferences.h:66
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
static void showDialog(SPDesktop *desktop, double amount, LivePathEffect::FilletChamferKnotHolderEntity *knot, bool use_distance, bool approx_radius, NodeSatellite nodesatellite)
void set_item(SPItem *item)
std::unique_ptr< KnotHolder > lpeknotholder
std::map< SPItem *, std::unique_ptr< ShapeEditor > > _shape_editors
Definition node-tool.h:53
Geom::Point snap_knot_position(Geom::Point const &p, unsigned state)
void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, Inkscape::CanvasItemCtrlType type=Inkscape::CANVAS_ITEM_CTRL_TYPE_DEFAULT, Glib::ustring const &name="unknown", char const *tip="", uint32_t color=0xffffff00)
KnotHolder * parent_holder
void knot_ungrabbed_handler(SPKnot *knot, unsigned int state)
void add(KnotHolderEntity *e)
NodeSatellite a per node holder of data.
Geom::Point getPosition(Geom::Curve const &curve_in, bool inverse=false) const
Get the point position of the nodesatellite.
double arcDistance(Geom::Curve const &curve_in) const
Get the length of the nodesatellite in curve_in.
double time(Geom::Curve const &curve_in, bool inverse=false) const
Get the time position of the nodesatellite in curve_in.
void setPosition(Geom::Point const p, Geom::Curve const &curve_in, bool inverse=false)
Set the position of the nodesatellite from a given point P.
PathVectorNodeSatellites a class to manage nodesatellites in a pathvector.
std::pair< size_t, size_t > getIndexData(size_t index)
To do: update description of desktop.
Definition desktop.h:149
Inkscape::UI::Tools::ToolBase * getTool() const
Definition desktop.h:187
Base class for visual SVG elements.
Definition sp-item.h:109
void setSize(Inkscape::HandleSize size)
Definition knot.cpp:413
void setAngle(double i)
Definition knot.cpp:422
CanvasItemPtr< Inkscape::CanvasItemCtrl > ctrl
Our CanvasItemCtrl.
Definition knot.h:60
void hide()
Hide knot on its canvas.
Definition knot.cpp:327
void show()
Show knot on its canvas.
Definition knot.cpp:322
void setTip(Glib::ustring &&tip)
Definition knot.cpp:438
void updateCtrl()
Update knot's control state.
Definition knot.cpp:389
double timeAtArcLength(double const A, Geom::Curve const &curve_in)
Calculate the time in curve_in with a size of A.
double arcLengthAt(double const A, Geom::Curve const &curve_in)
Calculate the size in curve_in with a point at A.
NodeSatelliteType
@ INVERSE_FILLET
@ INVERSE_CHAMFER
@ CHAMFER
std::vector< std::vector< NodeSatellite > > NodeSatellites
constexpr Coord infinity()
Get a value representing infinity.
Definition coord.h:88
size_t count_path_nodes(Geom::Path const &path)
Definition geom.cpp:798
Specific geometry functions for Inkscape, not provided my lib2geom.
SPItem * item
Glib::ustring label
Various utility functions.
Definition affine.h:22
Coord nearest_time(Point const &p, Curve const &c)
Definition curve.h:354
bool path_direction(Path const &p)
This function should only be applied to simple paths (regions), as otherwise a boolean winding direct...
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
double angle_between(Line const &l1, Line const &l2)
Definition line.h:456
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Helper class to stream background task notifications as a series of messages.
@ CANVAS_ITEM_CTRL_TYPE_POINTER
@ CANVAS_ITEM_CTRL_TYPE_MOVE
@ CANVAS_ITEM_CTRL_TYPE_LPE
STL namespace.
New node tool with support for multiple path editing.
static cairo_user_data_key_t key
Path intersection.
Singleton class to access the preferences file in a convenient way.
Inkscape::ShapeEditor This is a container class which contains a knotholder for shapes.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
Base class for live path effect items.
int index
SPDesktop * desktop