6#include <glibmm/i18n.h>
7#include <glibmm/ustring.h>
9#include <gtkmm/button.h>
10#include <gtkmm/entry.h>
11#include <gtkmm/enums.h>
12#include <gtkmm/widget.h>
35 steps(_(
"Steps with CTRL:"), _(
"Change number of steps with CTRL pressed"),
"steps", &wr, this, 2),
36 helper_size(_(
"Helper size:"), _(
"Helper size"),
"helper_size", &wr, this, 0),
37 apply_no_weight(_(
"Apply changes if weight = 0%"), _(
"Apply changes if weight = 0%"),
"apply_no_weight", &wr, this, true),
38 apply_with_weight(_(
"Apply changes if weight > 0%"), _(
"Apply changes if weight > 0%"),
"apply_with_weight", &wr, this, true),
39 only_selected(_(
"Change only selected nodes"), _(
"Change only selected nodes"),
"only_selected", &wr, this, false),
40 uniform(_(
"Uniform BSpline"), _(
"Uniform bspline"),
"uniform", &wr, this, false),
75 if (!is<SPShape>(lpeitem)) {
76 g_warning(
"LPE BSpline can only be applied to shapes (not groups).");
78 item->removeCurrentPathEffect(
false);
93 auto const vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
97 if (!param->widget_is_visible)
continue;
99 auto const widg = param->param_newWidget();
102 if (param->param_key ==
"weight") {
103 auto const buttons = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,0);
105 auto const default_weight = Gtk::make_managed<Gtk::Button>(_(
"Default weight"));
106 default_weight->signal_clicked()
110 auto const make_cusp = Gtk::make_managed<Gtk::Button>(_(
"Make cusp"));
111 make_cusp->signal_clicked()
117 if (param->param_key ==
"weight" || param->param_key ==
"steps") {
120 scalar.getSpinButton().set_width_chars(9);
125 if (
auto const tip = param->param_getTooltip()) {
126 widg->set_tooltip_markup(*tip);
128 widg->set_tooltip_text({});
129 widg->set_has_tooltip(
false);
161 auto curve = *path->curveForEdit();
174 if (
curve.curveCount() < 1) {
180 for (
auto & path_it : original_pathv) {
181 if (path_it.empty()) {
184 if (!prefs->
getBool(
"/tools/nodes/show_outline",
true)){
190 if (
uniform && !path_it.closed() && path_it.size_open() > 1) {
196 path_it.erase(path_it.begin());
202 path_it.erase(path_it.begin());
211 if (cubic && path_it.size_open() > 2) {
215 path_it.erase_last();
217 if (cubic && path_it.size_open() > 3) {
221 path_it.erase_last();
227 path_it.append(newp);
238 auto curve_n =
Geom::Path{curve_it1->initialPoint()};
239 if (path_it.closed()) {
240 const Geom::Curve &closingline = path_it.back_closed();
248 curve_endit = path_it.end_open();
251 while (curve_it1 != curve_endit) {
252 auto const in =
Geom::LineSegment{curve_it1->initialPoint(), curve_it1->finalPoint()};
255 if (
are_near((*cubic)[1], (*cubic)[0]) && !
are_near((*cubic)[2], (*cubic)[3])) {
260 if (
uniform && curve_n.size_default() == 0) {
261 point_at1 = curve_it1->initialPoint();
263 if (
are_near((*cubic)[2], (*cubic)[3]) && !
are_near((*cubic)[1], (*cubic)[0])) {
269 point_at1 = in.initialPoint();
270 point_at2 = in.finalPoint();
272 if (curve_it2 != curve_endit) {
273 auto const out =
Geom::LineSegment{curve_it2->initialPoint(), curve_it2->finalPoint()};
276 if (
are_near((*cubic)[1], (*cubic)[0]) && !
are_near((*cubic)[2], (*cubic)[3])) {
282 next_point_at1 = out.initialPoint();
285 if (path_it.closed() && curve_it2 == curve_endit) {
305 }
else if (curve_it2 == curve_endit) {
307 curve_n.appendNew<
Geom::CubicBezier>(point_at1, curve_it1->finalPoint(), curve_it1->finalPoint());
309 curve_n.appendNew<
Geom::CubicBezier>(point_at1, point_at2, curve_it1->finalPoint());
311 move_endpoints(curve_n, path_it.begin()->initialPoint(), curve_it1->finalPoint());
315 node = line.pointAt(0.5);
317 if ((cubic &&
are_near((*cubic)[0], (*cubic)[1])) || (cubic2 &&
are_near((*cubic2)[2], (*cubic2)[3]))) {
318 node = curve_it1->finalPoint();
322 if(!
are_near(
node,curve_it1->finalPoint()) && helper_size > 0.0) {
328 if (path_it.closed()) {
331 curve.push_back(std::move(curve_n));
333 if (helper_size > 0.0) {
340 char const * svgd =
"M 1,0.5 A 0.5,0.5 0 0 1 0.5,1 0.5,0.5 0 0 1 0,0.5 0.5,0.5 0 0 1 0.5,0 0.5,0.5 0 0 1 1,0.5 Z";
354 if (
curve.curveCount() < 1)
360 for (
const auto & path_it : original_pathv) {
361 if (path_it.empty()) {
374 auto curve_n =
Geom::Path{curve_it1->initialPoint()};
375 if (path_it.closed()) {
376 const Geom::Curve &closingline = path_it.back_closed();
384 curve_endit = path_it.end_open();
387 while (curve_it1 != curve_endit) {
388 auto const in =
Geom::LineSegment{curve_it1->initialPoint(), curve_it1->finalPoint()};
390 point_at0 = in.initialPoint();
391 point_at3 = in.finalPoint();
392 auto const sbasis_in = in.toSBasis();
399 point_at1 = sbasis_in.valueAt(weight_amount);
401 point_at1 = (*cubic)[1];
404 point_at1 = (*cubic)[1];
411 point_at2 = in.pointAt(1 - weight_amount);
417 point_at2 = (*cubic)[2];
420 point_at2 = (*cubic)[2];
428 point_at1 = in.pointAt(weight_amount);
430 point_at1 = in.initialPoint();
433 point_at2 = sbasis_in.valueAt(1 - weight_amount);
435 point_at2 = in.finalPoint();
438 point_at1 = in.initialPoint();
439 point_at2 = in.finalPoint();
446 if (path_it.closed()) {
448 path_it.initialPoint(),
449 path_it.initialPoint());
452 path_it.initialPoint(),
455 if (path_it.closed()) {
458 curve.push_back(std::move(curve_n));
3x3 matrix representing an affine transformation.
Bezier curve with compile-time specified order.
void setInitial(Point const &v) override
Change the starting point of the curve.
Point pointAt(Coord t) const override
Evaluate the curve at a specified time value.
Point initialPoint() const override
Retrieve the start of the curve.
void setFinal(Point const &v) override
Change the ending point of the curve.
Abstract continuous curve on a plane defined on [0,1].
virtual Point initialPoint() const =0
Retrieve the start of the curve.
virtual Point finalPoint() const =0
Retrieve the end of the curve.
Adaptor that creates 2D functions from 1D ones.
void push_back(Path const &path)
Append a path at the end.
void clear()
Remove all paths from the vector.
bool empty() const
Check whether the vector contains any paths.
Sequence of contiguous curves, aka spline.
Curve const & back_open() const
void append(Curve *curve)
Add a new curve to the end of the path.
Point initialPoint() const
Get the first point in the path.
void setFinal(Point const &p)
void appendNew(Args &&... args)
Append a new curve to the path.
Two-dimensional point that doubles as a vector.
std::vector< Parameter * > param_vector
void registerParameter(Parameter *param)
bool isNodePointSelected(Geom::Point const &nodePoint) const
void makeUndoDone(Glib::ustring message)
void param_setValue(Glib::ustring newvalue, bool write=false)
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
void doEffect(Geom::PathVector &curve) override
void changeWeight(double weightValue)
BoolParam apply_with_weight
Gtk::Widget * newWidget() override
This creates a managed widget.
void doOnApply(SPLPEItem const *lpeitem) override
Is performed a single time when the effect is freshly applied to a path.
void addCanvasIndicators(SPLPEItem const *, std::vector< Geom::PathVector > &hp_vec) override
Add possible canvas indicators (i.e., helperpaths other than the original path) to hp_vec This functi...
void doBSplineFromWidget(Geom::PathVector &curve, double value)
BoolParam apply_no_weight
LPEBSpline(LivePathEffectObject *lpeobject)
void param_set_digits(unsigned digits)
void param_set_range(double min, double max)
void param_set_increments(double step, double page)
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
void move_endpoints(Geom::PathVector &pathv, Geom::Point const &new_p0, Geom::Point const &new_p1)
Sets start of first path to new_p0, and end of first path to new_p1.
void closepath_current(Geom::Path &path)
Close path by setting the end point to the start point instead of adding a new lineto.
Inkscape::XML::Node * node
Coord nearest_time(Point const &p, Curve const &c)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
void sp_bspline_do_effect(Geom::PathVector &curve, double helper_size, Geom::PathVector &hp, bool uniform)
static constexpr double NO_POWER
Geom::Path sp_bspline_drawHandle(Geom::Point p, double helper_size)
static constexpr double DEFAULT_END_POWER
static constexpr double DEFAULT_START_POWER
static constexpr double BSPLINE_TOL
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Singleton class to access the preferences file in a convenient way.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
Geom::PathVector sp_svg_read_pathv(char const *str)
static void sp_svg_write_path(Inkscape::SVG::PathString &str, Geom::Path const &p, bool normalize=false)