58static constexpr double NO_POWER = 0.0;
73 _node->addObserver(*
this);
76 ~PathManipulatorObserver()
override {
77 _node->removeObserver(*
this);
87 GQuark path_d = g_quark_from_static_string(
"d");
88 GQuark path_transform = g_quark_from_static_string(
"transform");
89 GQuark lpe_quark = _pm->_lpe_key.empty() ? 0 : g_quark_from_string(_pm->_lpe_key.data());
92 if (attr == lpe_quark || attr == path_d) {
93 _pm->_externalChange(PATH_CHANGE_D);
94 }
else if (attr == path_transform) {
95 _pm->_externalChange(PATH_CHANGE_TRANSFORM);
99 void block() { _blocked =
true; }
100 void unblock() { _blocked =
false; }
102 PathManipulator *_pm;
112 , _multi_path_manipulator(mpm)
115 , _observer(new PathManipulatorObserver(this, path->getRepr()))
116 , _edit_transform(et)
117 , _lpe_key(
std::move(lpe_key))
119 auto lpeobj = cast<LivePathEffectObject>(
_path);
120 auto pathshadow = cast<SPPath>(
_path);
133 _outline->set_stroke(outline_color);
268 if (k && j->selected() && k->selected()) {
287 if (take_selection) {
300 if (testvalue > extrvalue) {
303 vec.emplace_back(
node, t );
304 extrvalue = testvalue;
307 vec.emplace_back(
node, t );
321 std::vector< std::pair<NodeList::iterator, double> > extremum_vector;
323 for (
NodeList::iterator first = _subpath->begin(); first != _subpath->end(); ++first) {
325 if (second && first->selected() && second->selected()) {
328 if (first->front()->isDegenerate() && second->back()->isDegenerate()) {
333 Geom::Bezier temp1d(first->position()[dim], first->front()->position()[dim],
334 second->back()->position()[dim], second->position()[dim]);
337 std::vector<double>
rs = deriv1d.
roots();
338 for (
double & r :
rs) {
345 for (
auto & i : extremum_vector) {
375 n->front()->setPosition(j->front()->position());
376 j->front()->retract();
378 _subpath->insert(k, n);
407 if (!
_path || cast<LivePathEffectObject>(
_path))
411 Node *prev =
nullptr;
412 bool is_last_node =
false;
413 for (
auto &
node : *subpath) {
414 if (
node.selected()) {
416 if (!
builder->inPath() || !prev) {
424 is_last_node =
false;
429 if (subpath->closed() && is_last_node) {
430 if (!prev->
front()->
isDegenerate() || !subpath->begin()->back()->isDegenerate()) {
446 bool pos_valid = preserve_pos;
448 unsigned num_selected = 0, num_unselected = 0;
449 for (
auto & j : *sp) {
450 if (j.selected()) ++num_selected;
451 else ++num_unselected;
453 if (num_selected < 2)
continue;
454 if (num_unselected == 0) {
463 while (sel_beg->selected()) ++sel_beg;
467 while (num_selected > 0) {
469 while (sel_beg && !sel_beg->selected()) sel_beg = sel_beg.
next();
470 if (!sel_beg)
throw std::logic_error(
"Join nodes: end of open path reached, "
471 "but there are still nodes to process!");
475 unsigned num_points = 0;
476 bool use_pos =
false;
478 back_pos = sel_beg->back()->position();
480 for (sel_end = sel_beg; sel_end && sel_end->selected(); sel_end = sel_end.
next()) {
482 front_pos = sel_end->front()->position();
483 if (pos_valid && sel_end == preserve_pos) use_pos =
true;
485 if (num_points > 1) {
488 joined_pos = preserve_pos->position();
494 sel_beg->move(joined_pos);
496 if (!sel_beg->back()->isDegenerate()) {
497 sel_beg->back()->setPosition(back_pos);
499 if (!sel_end.prev()->front()->isDegenerate()) {
500 sel_beg->front()->setPosition(front_pos);
502 sel_beg = sel_beg.
next();
503 while (sel_beg != sel_end) {
522 unsigned num_selected = 0, num_unselected = 0;
523 for (
auto & j : *sp) {
524 if (j.selected()) ++num_selected;
525 else ++num_unselected;
529 if (num_selected <= 2)
continue;
531 if (num_unselected == 0 && sp->closed()) {
540 while (sel_beg->selected()) ++sel_beg;
544 while (num_selected > 0) {
546 while (sel_beg && !sel_beg->selected()) sel_beg = sel_beg.
next();
547 if (!sel_beg)
throw std::logic_error(
"Join nodes: end of open path reached, "
548 "but there are still nodes to process!");
552 unsigned num_points = 0;
555 for (sel_end = sel_beg; sel_end && sel_end->selected(); sel_end = sel_end.
next()) {
558 if (num_points > 2) {
561 sel_beg = sel_beg.
next();
562 while (sel_beg != sel_end.
prev()) {
570 num_selected -= num_points;
587 for (; cur !=
end; ++cur) {
588 if (!cur->selected())
continue;
590 bool becomes_open =
false;
594 if (cur != sp->begin())
595 sp->splice(sp->begin(), *sp, cur, sp->end());
596 sp->setClosed(
false);
601 new_sp->splice(new_sp->end(), *sp, sp->begin(), cur);
609 ins->insert(ins->end(), n);
611 n->back()->setRelativePos(cur->back()->relativePos());
612 cur->back()->retract();
616 cur->back()->retract();
648 unsigned num_unselected = 0, num_selected = 0;
649 for (
auto & j : *sp) {
650 if (j.selected()) ++num_selected;
651 else ++num_unselected;
653 if (num_selected == 0) {
657 if (sp->closed() ? (num_unselected < 1) : (num_unselected < 2)) {
666 while (sel_beg->selected()) ++sel_beg;
670 while (num_selected > 0) {
671 while (sel_beg && !sel_beg->selected()) {
672 sel_beg = sel_beg.
next();
676 while (sel_end && sel_end->selected()) {
677 sel_end = sel_end.
next();
690 if (d1.isZero() || d2.isZero())
return M_PI;
708 unsigned const samples_per_segment = 10;
709 double const t_step = 1.0 / samples_per_segment;
711 unsigned del_len = 0;
715 if (del_len == 0)
return 0;
722 auto back = cur->back() ->isDegenerate() ? cur.prev()->position() : cur->back() ->position();
723 auto front = cur->front()->isDegenerate() ? cur.next()->position() : cur->front()->position();
724 auto angle =
get_angle(back, cur->position(), front);
725 auto a = fmod(fabs(angle), 2*M_PI);
726 auto diff = fabs(a - M_PI);
727 auto tolerance = (180 - angle_flat) * M_PI / 180;
728 bool flat = diff < tolerance;
732 keep_shape = !keep_shape;
741 auto p =
start.prev();
743 p->front()->retract();
747 end->back()->retract();
750 if (keep_shape &&
start.prev() &&
end) {
751 std::vector<InputPoint> input;
757 auto bc =
Geom::CubicBezier(cur->position(), cur->front()->position(), cur.next()->back()->position(), cur.next()->position());
758 for (
unsigned s = 0; s < samples_per_segment; ++s) {
760 input.emplace_back(bc.pointAt(t), t);
766 input.emplace_back(
end->position(),
Geom::Point(),
end->back()->position(), 1.0);
800 start.prev()->front()->move(
start.prev()->position());
804 end->back()->move(
end->position());
824 bool has_unselected =
false;
825 unsigned num_selected = 0;
826 for (
auto & j : *sp) {
830 has_unselected =
true;
833 if (!has_unselected) {
840 while (sel_beg && sel_beg->selected()) ++sel_beg;
842 while (num_selected > 0) {
843 if (!sel_beg->selected()) {
844 sel_beg = sel_beg.
next();
848 unsigned num_points = 0;
849 while (sel_end && sel_end->selected()) {
850 sel_end = sel_end.
next();
853 if (num_points >= (2 - delete_singles)) {
856 sel_end.
prev()->back()->retract();
858 sel_beg->front()->retract();
863 if (sel_end.
prev() != sp->begin())
864 sp->splice(sp->begin(), *sp, sel_end.
prev(), sp->end());
865 sp->setClosed(
false);
866 sp->erase(sel_beg.
next(), sp->end());
871 if (sel_beg == sp->begin()) {
872 sp->erase(sp->begin(), sel_end.
prev());
873 }
else if (sel_end == sp->end()) {
874 sp->erase(sel_beg.
next(), sp->end());
877 new_sp->splice(new_sp->end(), *sp, sp->begin(), sel_beg.
next());
880 sp->erase(sp->begin(), sel_end.
prev());
885 num_selected -= num_points;
917 if (!(k && j->selected() && k->selected()))
continue;
920 if (j->front()->isDegenerate() && k->back()->isDegenerate())
922 j->front()->move(j->position());
923 k->back()->move(k->position());
926 if (!j->front()->isDegenerate() || !k->back()->isDegenerate())
929 j->front()->move(j->position() + (k->position() - j->position()) / 3);
930 k->back()->move(k->position() + (j->position() - k->position()) / 3);
943 double length_change;
949 length_change = prefs->
getDoubleLimited(
"/options/defaultscale/value", 2, 1, 1000,
"px");
950 length_change *= dir;
956 Node *nh = n->nodeToward(h);
961 double rellen = relpos.
length();
962 relpos *= ((rellen + length_change) / rellen);
966 gchar
const *
key = which < 0 ?
"handle:scale:left" :
"handle:scale:right";
984 int snaps = prefs->
getIntLimited(
"/options/rotationsnapsperpi/value", 12, 1, 1000);
985 angle = M_PI * dir / snaps;
990 gchar
const *
key = which < 0 ?
"handle:rotate:left" :
"handle:rotate:right";
1001 if (!next)
return n->back();
1002 if (!prev)
return n->front();
1010 std::swap(npos, ppos);
1027 if (!j->selected())
continue;
1028 j->showHandles(
true);
1029 if (j.prev()) j.prev()->showHandles(
true);
1030 if (j.next()) j.next()->showHandles(
true);
1035 for (
auto & j : *_subpath) {
1036 j.showHandles(
false);
1071 for (
auto & j : *_subpath) {
1082 for (
auto & j : *_subpath) {
1102 if (!first)
throw std::invalid_argument(
"Subdivide after invalid iterator");
1105 if (!second)
throw std::invalid_argument(
"Subdivide after last node in open path");
1118 if (first->front()->isDegenerate() && second->back()->isDegenerate()) {
1121 Geom::lerp(t, first->position(), second->position()));
1123 inserted = list.
insert(insert_at, n);
1127 second->back()->position(), second->position());
1128 std::pair<Geom::CubicBezier, Geom::CubicBezier> div = temp.
subdivide(t);
1129 std::vector<Geom::Point> seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints();
1134 n->back()->setPosition(seg1[2]);
1135 n->front()->setPosition(seg2[1]);
1140 if(second->back()->isDegenerate()){
1141 line_inside_nodes.
moveto(n->position());
1142 line_inside_nodes.
lineto(second->position());
1145 line_inside_nodes.
reset();
1146 n->front()->setPosition(next);
1148 n->front()->setPosition(seg2[1]);
1150 if(first->front()->isDegenerate()){
1151 line_inside_nodes.
moveto(n->position());
1152 line_inside_nodes.
lineto(first->position());
1155 n->back()->setPosition(previous);
1157 n->back()->setPosition(seg1[2]);
1161 inserted = list.
insert(insert_at, n);
1163 first->front()->move(seg1[1]);
1164 second->back()->move(seg2[2]);
1177 bool search_unselected,
bool closest)
1180 double extr_dist = closest ? HUGE_VAL : -HUGE_VAL;
1186 if (!search_selected)
continue;
1188 if (!search_unselected)
continue;
1191 bool cond = closest ? (dist < extr_dist) : (dist > extr_dist);
1213 case PATH_CHANGE_D: {
1218 std::vector<bool> selpos;
1220 for (
auto & j : *_subpath) {
1221 selpos.push_back(j.selected());
1224 unsigned size = selpos.size(), curpos = 0;
1230 if (curpos >=
size)
goto end_restore;
1239 case PATH_CHANGE_TRANSFORM: {
1240 auto path = cast<SPPath>(
_path);
1247 for (
auto & j : *_subpath) {
1248 j.transform(i2d_change);
1286 if (pathv.
empty()) {
1294 for (
auto & pit : pathv) {
1300 subpath->push_back(previous_node);
1302 bool closed = pit.closed();
1309 if (closed && cit == --(pit.end())) {
1310 current_node = subpath->begin().get_pointer();
1316 subpath->push_back(current_node);
1323 if (bezier && bezier->
order() == 3)
1325 previous_node->front()->
setPosition((*bezier)[1]);
1328 previous_node = current_node;
1331 if (pit.closed()) subpath->setClosed(
true);
1348 auto const *tsi = nts_raw ? nts_raw :
"";
1350 for (
auto & j : *_subpath) {
1351 char nodetype = (*tsi) ? (*tsi++) :
'b';
1354 if (_subpath->closed() && *tsi) {
1367 auto path = cast<SPLPEItem>(
_path);
1369 if(path->hasPathEffect()){
1379 steps = lpe_bsp->
steps+1;
1386 auto path = cast<SPPath>(
_path);
1387 if (path && path->hasPathEffect()) {
1409 Node * next_node =
nullptr;
1410 next_node = n->nodeToward(h);
1413 line_inside_nodes.
moveto(n->position());
1415 if(!are_near(h->
position(), n->position())){
1440 Node * next_node =
nullptr;
1441 next_node = n->nodeToward(h);
1443 line_inside_nodes.
moveto(n->position());
1446 ret = sbasis_inside_nodes.
valueAt(pos);
1449 ret = n->position();
1464 for (std::list<SubpathPtr>::iterator spi =
_subpaths.begin(); spi !=
_subpaths.end(); ) {
1466 if (subpath->empty()) {
1471 builder.moveTo(prev->position());
1476 if (subpath->closed()) {
1479 if (!prev->front()->isDegenerate() || !subpath->begin()->back()->isDegenerate()) {
1499 if (pathv.
empty()) {
1509 auto path = cast<SPPath>(
_path);
1510 if (path && path->hasPathEffect()) {
1549 std::stringstream tstr;
1551 for (
auto & j : *_subpath) {
1555 if (_subpath->closed()) tstr << _subpath->begin()->type();
1577 for (
auto & path : pv) {
1588 pv.insert(pv.end(), arrows.
begin(), arrows.
end());
1590 auto tmp =
SPCurve(std::move(pv));
1599 auto lpeobj = cast<LivePathEffectObject>(
_path);
1600 auto path = cast<SPPath>(
_path);
1602 Effect *lpe = lpeobj->get_lpe();
1608 if (path->curveForEdit()) {
1620 auto lpeobj = cast<LivePathEffectObject>(
_path);
1621 auto path = cast<SPPath>(
_path);
1626 Effect *lpe = lpeobj->get_lpe();
1633 lpeobj->requestModified(SP_OBJECT_MODIFIED_FLAG);
1638 if (
empty())
return;
1639 if (path->curveBeforeLPE()) {
1640 path->setCurveBeforeLPE(&
_spcurve);
1641 if (path->hasPathEffectRecursive()) {
1653 auto lpeobj = cast<LivePathEffectObject>(
_path);
1655 return "sodipodi:nodetypes";
1666 auto lpeobj = cast<LivePathEffectObject>(
_path);
1670 return lpeobj->getRepr();
1675 if (
event.button != 1)
return false;
1700 if (!n->isEndNode()) {
1703 _commit(_(
"Cycle node type"));
1734 for (
auto & n : pvec) {
1751 iters[1] = iters[2].
prev();
1752 iters[3] = iters[2].
next();
1755 node->showHandles(
true);
1756 if (iters[1]) iters[1]->showHandles(
true);
1757 if (iters[3]) iters[3]->showHandles(
true);
1763 if (iters[1]) iters[0] = iters[1].
prev();
1764 if (iters[3]) iters[4] = iters[3].
next();
1766 for (
int i = 0; i < 5; ++i) {
1767 nodesel[i] = iters[i] && iters[i]->selected();
1769 for (
int i = 1; i < 4; ++i) {
1770 if (iters[i] && !nodesel[i-1] && !nodesel[i] && !nodesel[i+1]) {
1771 iters[i]->showHandles(
false);
1818 if (!pvp)
return dist;
1825 bool drag_point_updated =
false;
1826 if (dist < stroke_tolerance) {
1828 double fracpart = pvp->t;
1829 std::list<SubpathPtr>::iterator spi =
_subpaths.begin();
1830 for (
unsigned i = 0; i < pvp->path_index; ++i, ++spi) {}
1833 if (first && first.
next() &&
1837 drag_point_updated =
true;
1839 int tolerance = std::max(2, (
int)stroke_tolerance);
1865 double ret = prefs->
getIntLimited(
"/options/dragtolerance/value", 2, 0, 100);
Cartesian point / 2D vector and related operations.
int bezier_fit(Geom::Point bezier[4], const std::vector< InputPoint > &data)
Bezier fitting algorithms.
3x3 matrix representing an affine transformation.
Coord descrim() const
Calculate the descriminant.
Affine inverse() const
Compute the inverse matrix.
std::pair< BezierCurveN, BezierCurveN > subdivide(Coord t) const
Divide a Bezier curve into two curves.
Two-dimensional Bezier curve of arbitrary order.
unsigned order() const
Get the order of the Bezier curve.
Polynomial in Bernstein-Bezier basis.
std::vector< Coord > roots() const
Coord valueAt(double t) const
virtual D2< SBasis > toSBasis() const =0
Convert the curve to a symmetric power basis polynomial.
Point valueAt(double t) const
Axis-aligned rectangle that can be empty.
Store paths to a PathVector.
void push_back(Path const &path)
Append a path at the end.
Point pointAt(Coord t) const
iterator erase(iterator i)
Remove a path from the vector.
bool empty() const
Check whether the vector contains any paths.
std::optional< PathVectorTime > nearestTime(Point const &p, Coord *dist=NULL) const
Sequence::iterator iterator
Sequence of contiguous curves, aka spline.
Two-dimensional point that doubles as a vector.
Coord length() const
Compute the distance from origin.
Rotation around the origin.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
static void maybeDone(SPDocument *document, const gchar *keyconst, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
Parameter * getParameter(const char *key)
LivePathEffectObject * getLPEObj()
void adjustForNewPath() override
Geom::PathVector const & get_pathvector() const
void set_new_value(Geom::PathVector const &newpath, bool write_to_svg)
Preference storage class.
static Preferences * get()
Access the singleton Preferences object.
int getIntLimited(Glib::ustring const &pref_path, int def=0, int min=INT_MIN, int max=INT_MAX)
Retrieve a limited integer.
double getDoubleLimited(Glib::ustring const &pref_path, double def=0.0, double min=DBL_MIN, double max=DBL_MAX, Glib::ustring const &unit="")
Retrieve a limited floating point value.
Class to store data for points which are snap candidates, either as a source or as a target.
Class describing the result of an attempt to snap.
Geom::Point getPoint() const
std::pair< iterator, bool > insert(const value_type &x, bool notify=true, bool to_update=true)
Add a control point to the selection.
sigc::signal< void()> signal_update
Fires when the display needs to be updated to reflect changes.
sigc::signal< void(std::vector< SelectableControlPoint * >, bool)> signal_selection_changed
void erase(iterator pos, bool to_update=true)
Remove a point from the selection.
void restoreTransformHandles()
void clear()
Remove all points from the selection, making it empty.
void hideTransformHandles()
Geom::Point const & position() const
Current position of the control point.
virtual void setVisible(bool v)
Set the visibility of the control point.
virtual void setPosition(Geom::Point const &pos)
Relocate the control point without side effects.
An invisible point used to drag curves.
void setIterator(NodeList::iterator i)
NodeList::iterator getIterator()
void setTimeValue(double t)
Geom::Point relativePos() const
void setRelativePos(Geom::Point const &p)
bool isDegenerate() const
void setPosition(Geom::Point const &p) override
Relocate the control point without side effects.
void move(Geom::Point const &p) override
Move the control point to new position with side effects.
SPDesktop *const _desktop
Manipulator that manages multiple path manipulators active at the same time.
PathSharedData const & _path_data
void _doneWithCleanup(gchar const *reason, bool alert_LPE=false)
Commits changes to XML, adds undo stack entry and removes empty manipulators.
static NodeList & get(Node *n)
iterator insert(iterator pos, Node *x)
insert a node before pos.
static iterator get_iterator(Node *n)
iterator erase(iterator pos)
static NodeType parse_nodetype(char x)
void _updateOutline()
Update the path outline.
CanvasItemPtr< Inkscape::CanvasItemBpath > _outline
void update(bool alert_LPE=false)
Update the display and the outline of the path.
Inkscape::XML::Node * _getXMLNode()
Return the XML node we are editing.
std::string _createTypeString()
Construct a node type string to store in the sodipodi:nodetypes attribute.
void _createGeometryFromControlPoints(bool alert_LPE=false)
Construct the geometric representation of nodes and handles, update the outline and display.
Glib::ustring _nodetypesKey()
Figure out in what attribute to store the nodetype string.
void setSegmentType(SegmentType)
Make selected segments curves / lines.
void hideDragPoint()
Hide the curve drag point until the next motion event.
void _selectionChanged(SelectableControlPoint *p, bool selected)
void setLiveOutline(bool set)
void insertNodeAtExtremum(ExtremumType extremum)
Insert a new node at the extremum of the selected segments.
Geom::Coord _updateDragPoint(Geom::Point const &)
Update the position of the curve drag point such that it is over the nearest point of the path.
~PathManipulator() override
std::shared_ptr< NodeList > SubpathPtr
void _commit(Glib::ustring const &annotation)
Update the XML representation and put the specified annotation on the undo stack.
Geom::Point _bsplineHandleReposition(Handle *h, bool check_other=true)
void rotateHandle(Node *n, int which, int dir, bool pixel)
void _externalChange(unsigned type)
Called by the XML observer when something else than us modifies the path.
void build_segment(Geom::PathBuilder &builder, Node *prev_node, Node *cur_node)
Build one segment of the geometric representation.
void reverseSubpaths(bool selected_only)
Reverse subpaths of the path.
void _removeNodesFromSelection()
Removes all nodes belonging to this manipulator from the control point selection.
void _getGeometry()
Retrieve the geometry of the edited object from the object tree.
bool _nodeClicked(Node *, ButtonReleaseEvent const &)
void _updateOutlineOnZoomChange()
This is called on zoom change to update the direction arrows.
void _deleteSegments(bool delete_singles)
Removes selected segments.
bool _handleClicked(Handle *, ButtonReleaseEvent const &)
void showHandles(bool show)
Set the visibility of handles.
double _getStrokeTolerance()
Compute the radius from the edge of the path where clicks should initiate a curve drag or segment sel...
void weldNodes(NodeList::iterator preserve_pos=NodeList::iterator())
Replace contiguous selections of nodes in each subpath with one node.
void selectSubpaths()
Select all nodes in subpaths that have something selected.
void setControlsTransform(Geom::Affine const &)
void setLiveObjects(bool set)
void _recalculateIsBSpline()
bool empty()
Check whether the manipulator has any nodes.
void showPathDirection(bool show)
void showOutline(bool show)
Set the visibility of outline.
void invertSelectionInSubpaths()
Invert selection in the selected subpaths.
bool _show_path_direction
unsigned _deleteStretch(NodeList::iterator first, NodeList::iterator last, NodeDeleteMode mode)
Delete nodes between the two iterators.
void duplicateNodes()
Insert new nodes exactly at the positions of selected nodes while preserving shape.
void clear()
Remove all nodes from the path.
Geom::Affine _getTransform() const
void _setGeometry()
Set the geometry of the edited object in the object tree, but do not commit to XML.
Geom::Affine _i2d_transform
item-to-desktop transform, inverse of _d2i_transform
Geom::Affine _edit_transform
additional transform to apply to editing controls
bool event(Inkscape::UI::Tools::ToolBase *tool, CanvasEvent const &event) override
Handle motion events to update the position of the curve drag point.
Geom::Affine _d2i_transform
desktop-to-item transform
PathManipulatorObserver * _observer
void deleteNodes(NodeDeleteMode mode)
Delete selected nodes in the path, optionally substituting deleted segments with bezier curves in a w...
void insertNodes()
Insert a new node in the middle of each selected segment.
PathManipulator(MultiPathManipulator &mpm, SPObject *path, Geom::Affine const &edit_trans, uint32_t outline_color, Glib::ustring lpe_key)
void scaleHandle(Node *n, int which, int dir, bool pixel)
CurveDragPoint * _dragpoint
void weldSegments()
Remove nodes in the middle of selected segments.
void insertNode(Geom::Point)
Handle * _chooseHandle(Node *n, int which)
NodeList::iterator extremeNode(NodeList::iterator origin, bool search_selected, bool search_unselected, bool closest)
Find the node that is closest/farthest from the origin.
MultiPathManipulator & _multi_path_manipulator
void writeXML()
Store the changes to the path in XML.
void _selectionChangedM(std::vector< SelectableControlPoint * > pvec, bool selected)
NodeList::iterator subdivideSegment(NodeList::iterator after, double t)
Insert a node in the segment beginning with the supplied iterator, at the given time value.
int _bsplineGetSteps() const
void _createControlPointsFromGeometry()
Create nodes and handles based on the XML of the edited path.
void copySelectedPath(Geom::PathBuilder *builder)
Copy the selected nodes using the PathBuilder.
SPObject * _path
can be an SPPath or an Inkscape::LivePathEffect::Effect !!!
double _bsplineHandlePosition(Handle *h, bool check_other=true)
Tool component that edits something on the canvas using selectable control points.
ExtremumType
Type of extremum points to add in PathManipulator::insertNodeAtExtremum.
ControlPointSelection & _selection
Desktop-bound selectable control object.
Interface for XML node observers.
Interface for refcounted XML nodes.
virtual void setPosition(int pos)=0
Set the position of this node in parent's child order.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual unsigned position() const =0
Get the index of this node in parent's child order.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
virtual void removeObserver(NodeObserver &observer)=0
Remove an object from the list of observers.
Inkscape::LivePathEffect::Effect * get_lpe()
Wrapper around a Geom::PathVector object.
void moveto(Geom::Point const &p)
Perform a moveto to a point, thus starting a new subpath.
void reset()
Set curve to empty curve.
Geom::PathVector const & get_pathvector() const
void lineto(Geom::Point const &p)
Adds a line to the current subpath.
Geom::Curve const * first_segment() const
Return first pathsegment in PathVector or NULL.
double current_zoom() const
SPDocument * getDocument() const
Geom::Affine const & d2w() const
Transformation from desktop to window coordinates.
SPNamedView * getNamedView() const
sigc::signal< void(double)> signal_zoom_changed
Emitted when the zoom factor changes (not emitted when scrolling).
Geom::Affine const & w2d() const
Transformation from window to desktop coordinates (zoom/rotate).
SPObject is an abstract base class of all of the document nodes at the SVG document level.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
T< SPAttr::STROKE, SPIPaint > stroke
stroke
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
void setup(SPDesktop const *desktop, bool snapindicator=true, SPObject const *item_to_ignore=nullptr, std::vector< Inkscape::SnapCandidatePoint > *unselected_nodes=nullptr)
Convenience shortcut when there is only one item to ignore.
vector< vpsc::Rectangle * > rs
Control point selection - stores a set of control points and applies transformations to them.
Contains forward declarations of 2geom types.
BezierCurveN< 3 > CubicBezier
Cubic (order 3) Bezier curve.
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
Dim2
2D axis enumeration (X or Y).
constexpr Coord infinity()
Get a value representing infinity.
double Coord
Floating point type used to store coordinates.
Geom::PathVector pathv_to_cubicbezier(Geom::PathVector const &pathv, bool nolines)
Geom::PathVector pathv_to_linear_and_cubic_beziers(Geom::PathVector const &pathv)
Specific geometry functions for Inkscape, not provided my lib2geom.
Macro for icon names used in Inkscape.
Inkscape::XML::Node * node
PowerStroke LPE effect, see lpe-powerstroke.cpp.
Multi path manipulator - a tool component that edits multiple paths at once.
Coord nearest_time(Point const &p, Curve const &c)
Angle distance(Angle const &a, Angle const &b)
Affine identity()
Create an identity matrix.
Point unit_vector(Point const &a)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Point middle_point(LineSegment const &_segment)
static R & anchor(R &r)
Increments the reference count of a anchored object.
static R & release(R &r)
Decrements the reference count of a anchored object.
void build_segment(Geom::PathBuilder &, Node *, Node *)
NodeType
Types of nodes supported in the node tool.
@ NODE_CUSP
Cusp node - no handle constraints.
@ NODE_SYMMETRIC
Symmetric node - handles must be colinear and of equal length.
@ NODE_AUTO
Auto node - handles adjusted automatically based on neighboring nodes.
@ NODE_LAST_REAL_TYPE
Last real type of node - used for ctrl+click on a node.
@ NODE_SMOOTH
Smooth node - handles must be colinear.
double get_angle(const Geom::Point &p0, const Geom::Point &p1, const Geom::Point &p2)
SegmentType
Types of segments supported in the node tool.
@ SEGMENT_STRAIGHT
Straight linear segment.
@ SEGMENT_CUBIC_BEZIER
Bezier curve with two control points.
const double DEFAULT_START_POWER
static void add_or_replace_if_extremum(std::vector< std::pair< NodeList::iterator, double > > &vec, double &extrvalue, double testvalue, NodeList::iterator const &node, double t)
bool held_ctrl(CanvasEvent const &event)
void inspect_event(E &&event, Fs... funcs)
Perform pattern-matching on a CanvasEvent.
@ SNAPSOURCE_OTHER_HANDLE
bool held_alt(CanvasEvent const &event)
Interface for XML node observers.
Node types and other small enums.
static cairo_user_data_key_t key
Path manipulator - a component that edits a single path on-canvas.
callback interface for SVG path data
static double sign(double const x)
Returns -1 or 1 according to the sign of x.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
Abstract base class for events.
Movement of the mouse pointer.
Inkscape::CanvasItemGroup * outline_group
SPStyle - a style object for SPItem objects.
Glib::RefPtr< Gtk::Builder > builder