19#include <boost/functional/hash.hpp>
21#include <glibmm/i18n.h>
23#include <gtkmm/label.h>
24#include <gtkmm/separator.h>
35namespace LivePathEffect {
38 {
DM_SEGMENTS, N_(
"Number of segments"),
"segments" },
39 {
DM_SIZE, N_(
"Segment size"),
"size" }
45 {
HM_RAND, N_(
"Random"),
"rand" },
53 , method(_(
"Method"), _(
"<b>Segment size:</b> add nodes to path evenly; <b>Number of segments:</b> add nodes between existing nodes"),
"method",
DMConverter, &wr, this,
DM_SIZE)
54 , max_segment_size(_(
"Segment size"), _(
"Add nodes to path evenly. Choose <b>Segment size</b> method from the dropdown to use this subdivision method."),
"max_segment_size", &wr, this, 10)
55 , segments(_(
"Number of segments"), _(
"Add nodes between existing nodes. Choose <b>Number of segments</b> method from the dropdown to use this subdivision method."),
"segments", &wr, this, 2)
56 , displace_x(_(
"Displace ←→"), _(
"Maximal displacement in x direction"),
"displace_x", &wr, this, 10.)
57 , displace_y(_(
"Displace ↑↓"), _(
"Maximal displacement in y direction"),
"displace_y", &wr, this, 10.)
58 , global_randomize(_(
"Global randomize"), _(
"Global displacement in all directions"),
"global_randomize", &wr, this, 1.)
60 , shift_nodes(_(
"Apply displacement"), _(
"Uncheck to use this LPE for just adding nodes, without roughening; useful for further interactive processing."),
"shift_nodes", &wr, this, true)
61 , fixed_displacement(_(
"Fixed displacement"), _(
"Fixed displacement, 1/3 of segment length"),
"fixed_displacement",
63 , spray_tool_friendly(_(
"Spray Tool friendly"), _(
"For use with Spray Tool in copy mode"),
"spray_tool_friendly",
101 auto const pref_path = Glib::ustring::compose(
"/live_effects/%1/%2",
107 if (param->param_key ==
"max_segment_size") {
108 auto const minor = std::min(bbox->width(), bbox->height());
110 param->param_readSVGValue(max_segment_size_str.c_str());
111 }
else if (param->param_key ==
"displace_x") {
113 param->param_readSVGValue(displace_x_str.c_str());
114 }
else if (param->param_key ==
"displace_y") {
116 param->param_readSVGValue(displace_y_str.c_str());
127 std::string id_item(lpeitem->
getId());
128 long seed =
static_cast<long>(boost::hash_value(id_item));
144 auto const vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 2);
147 std::vector<Parameter *>::iterator it =
param_vector.begin();
149 if ((*it)->widget_is_visible) {
153 auto const method_label = Gtk::make_managed<Gtk::Label>(
154 Glib::ustring(_(
"<b>Resolution</b>")), Gtk::Align::START);
155 method_label->set_use_markup(
true);
157 UI::pack_start(*vbox, *Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::HORIZONTAL),
161 auto const options = Gtk::make_managed<Gtk::Label>(
162 Glib::ustring(_(
"<b>Options</b>")), Gtk::Align::START);
163 options->set_use_markup(
true);
165 UI::pack_start(*vbox, *Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::HORIZONTAL),
173 widg->set_tooltip_markup(*tip);
175 widg->set_tooltip_text(
"");
176 widg->set_has_tooltip(
false);
189 if (rand() % 100 < 49) {
190 random_number *= -1.;
193 return random_number;
198 double factor = 1.0 / 3.0;
207 output = Geom::Point::polar(ray.
angle(), max_length);
216 for (
const auto &path_it : original_pathv) {
227 if (path_it.closed()) {
228 const Geom::Curve &closingline = path_it.back_closed();
236 curve_endit = path_it.end_open();
239 while (curve_it1 != curve_endit) {
247 double length = curve_it1->length(0.01);
248 std::size_t splits = 0;
255 for (
unsigned int t = 1; t <= splits; t++) {
256 if (t == splits && splits != 1) {
264 if (t == splits - 1) {
275 nCurve = std::move(tmp);
281 if (path_it.closed()) {
288 Geom::Ray ray((*cubic_start)[1], (*cubic_start)[0]);
289 double dist =
Geom::distance((*cubic_start)[1], (*cubic_start)[0]);
290 oposite = Geom::Point::polar(ray.
angle(), dist) + (*cubic_start)[0];
294 out.
start((*cubic)[0]);
308 out.
start((*cubic)[0]);
355 std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
356 std::vector<Geom::Point> seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints();
357 Geom::Ray ray(seg1[3] + point_a3, seg2[1] + point_a3);
358 double length = max_length;
362 point_b1 = seg1[3] + point_a3 + Geom::Point::polar(ray.
angle(),
length);
364 point_b3 = seg2[3] + point_b3;
365 point_a3 = seg1[3] + point_a3;
376 point_b2 = point_b3 + Geom::Point::polar(ray.
angle(),
length);
379 point_a2 = point_a3 + Geom::Point::polar(ray.
angle(), max_length);
390 double length = max_length;
395 point_b2 = A.
pointAt(t + ((t / 3) * 2));
397 point_a3 = A.
pointAt(t) + point_a3;
411 point_b2 = point_b3 + Geom::Point::polar(ray.
angle(),
length);
414 point_a2 = point_a3 + Geom::Point::polar(ray.
angle(), max_length);
427 if (cubic && !last) {
428 std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->
subdivide(t);
429 std::vector<Geom::Point> seg2 = div.second.controlPoints();
436 std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->
subdivide(t);
437 std::vector<Geom::Point> seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints();
440 last_move = point_a3;
442 last_move = point_b3;
452 std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->
subdivide(t);
453 std::vector<Geom::Point> seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints();
484 point_a1 = Geom::Point::polar(ray.
angle(), max_length);
488 ray.
setPoints((*cubic)[3] + point_a3, (*cubic)[2] + point_a3);
494 prev = (*cubic)[2] + point_a2;
495 out.
start((*cubic)[0]);
499 point_a1 = Geom::Point::polar(ray.
angle(), max_length);
509 prev = A.
pointAt((1.0 / 3.0) * 2) + point_a2 + point_a3;
519 out.
start((*cubic)[0]);
521 last_move = point_a3;
Bezier curve with compile-time specified order.
std::pair< BezierCurveN, BezierCurveN > subdivide(Coord t) const
Divide a Bezier curve into two curves.
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.
virtual Point pointAt(Coord t) const
Evaluate the curve at a specified time value.
Axis-aligned rectangle that can be empty.
void push_back(Path const &path)
Append a path at the end.
Point finalPoint() const
Get the last point in the last path of the vector.
void reverse(bool reverse_paths=true)
Reverse the direction of paths in the vector.
size_type curveCount() const
Get the total number of curves in the vector.
Sequence of contiguous curves, aka spline.
Point pointAt(Coord t) const
Get the point at the specified time value.
void appendNew(Args &&... args)
Append a new curve to the path.
void start(Point const &p)
Two-dimensional point that doubles as a vector.
Straight ray from a specific point to infinity.
void setPoints(Point const &a, Point const &b)
std::vector< Parameter * > param_vector
void registerParameter(Parameter *param)
bool apply_to_clippath_and_mask
EffectType effectType() const
void param_setValue(Glib::ustring newvalue, bool write=false)
Glib::ustring param_getSVGValue() const override
virtual Geom::Point tPoint(Geom::Point A, Geom::Point B, double t=0.5)
Gtk::Widget * newWidget() override
This creates a managed widget.
Geom::Path addNodesAndJitter(Geom::Curve const &A, Geom::Point &prev, Geom::Point &last_move, double t, bool last)
virtual double sign(double randNumber)
LPERoughen(LivePathEffectObject *lpeobject)
void doEffect(Geom::PathVector &curve) override
EnumParam< DivisionMethod > method
Geom::Path jitter(Geom::Curve const &A, Geom::Point &prev, Geom::Point &last_move)
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
BoolParam spray_tool_friendly
virtual Geom::Point randomize(double max_length, bool is_node=false)
ScalarParam max_segment_size
RandomParam global_randomize
BoolParam fixed_displacement
EnumParam< HandlesMethod > handles
void doOnApply(SPLPEItem const *lpeitem) override
Is performed a single time when the effect is freshly applied to a path.
Glib::ustring const * param_getTooltip() const
virtual Gtk::Widget * param_newWidget()=0
void param_set_value(gdouble val, long newseed)
void param_set_randomsign(bool randomsign)
void param_set_range(gdouble min, gdouble max)
void param_set_digits(unsigned digits)
void param_set_range(double min, double max)
void param_set_increments(double step, double page)
void param_make_integer(bool yes=true)
bool isSet() const
Check whether the received entry is set.
Preference storage class.
static Preferences * get()
Access the singleton Preferences object.
Entry const getEntry(Glib::ustring const &pref_path)
Retrieve a preference entry without specifying its type.
Simplified management of enumerations of svg items with UI labels.
Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform=Geom::identity()) const
char const * getId() const
Returns the objects current ID string.
void backspace(Geom::PathVector &pathv)
Remove last segment of curve.
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 pathvector_append(Geom::PathVector &to, Geom::PathVector const &pathv, bool use_lineto)
Append pathv to to.
Geom::Curve const * get_last_segment(Geom::PathVector const &pathv)
Return last pathsegment (possibly the closing path segment) of the last path in PathVector or null.
Geom::Curve const * get_first_segment(Geom::PathVector const &pathv)
Return first pathsegment in PathVector or NULL.
void closepath_current(Geom::Path &path)
Close path by setting the end point to the start point instead of adding a new lineto.
bool pathvector_append_continuous(Geom::PathVector &to, Geom::PathVector const &pathv, double tolerance)
Append pathv to to with possible fusing of close endpoints.
Geom::PathVector pathv_to_linear_and_cubic_beziers(Geom::PathVector const &pathv)
Specific geometry functions for Inkscape, not provided my lib2geom.
Roughen LPE effect, see lpe-roughen.cpp.
Coord length(LineSegment const &seg)
Coord nearest_time(Point const &p, Curve const &c)
Angle distance(Angle const &a, Angle const &b)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
static const Util::EnumDataConverter< HandlesMethod > HMConverter(HandlesMethodData, HM_END)
static const Util::EnumData< HandlesMethod > HandlesMethodData[]
const EnumEffectDataConverter< EffectType > LPETypeConverter
defined in effect.cpp
static const Util::EnumData< DivisionMethod > DivisionMethodData[]
static const Util::EnumDataConverter< DivisionMethod > DMConverter(DivisionMethodData, DM_END)
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.
Glib::ustring format_classic(T const &... args)
Helper class to stream background task notifications as a series of messages.
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Singleton class to access the preferences file in a convenient way.
Base class for live path effect items.
Simplified management of enumerations of svg items with UI labels.