22#include <glibmm/i18n.h>
46namespace LivePathEffect {
52 ~KnotHolderEntityWidthPatternAlongPath()
override
74 pattern(_(
"Pattern source:"), _(
"Path to put along the skeleton path"),
"pattern", &wr, this,
"M0,0 L1,0"),
76 prop_scale(_(
"_Width:"), _(
"Width of the pattern"),
"prop_scale", &wr, this, 1.0),
77 copytype(_(
"Pattern copies:"), _(
"How many pattern copies to place along the skeleton path"),
79 scale_y_rel(_(
"Wid_th in units of length"),
80 _(
"Scale the width of the pattern in units of its length"),
81 "scale_y_rel", &wr, this, false),
82 spacing(_(
"Spa_cing:"),
84 _(
"Space between copies of the pattern. Negative values allowed, but are limited to -90% of pattern width."),
85 "spacing", &wr, this, 0),
86 normal_offset(_(
"No_rmal offset:"),
"",
"normal_offset", &wr, this, 0),
87 tang_offset(_(
"Tan_gential offset:"),
"",
"tang_offset", &wr, this, 0),
88 prop_units(_(
"Offsets in _unit of pattern size"),
89 _(
"Spacing, tangential and normal offset are expressed as a ratio of width/height"),
90 "prop_units", &wr, this, false),
91 vertical_pattern(_(
"Pattern is _vertical"), _(
"Rotate pattern 90 deg before applying"),
92 "vertical_pattern", &wr, this, false),
93 hide_knot(_(
"Hide width knot"), _(
"Hide width knot"),
"hide_knot", &wr, this, false),
94 fuse_tolerance(_(
"_Fuse nearby ends:"), _(
"Fuse ends closer than this number. 0 means don't fuse."),
95 "fuse_tolerance", &wr, this, 0)
163 using namespace Geom;
172 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pre_output;
181 if (pattBndsX && pattBndsY) {
182 x0 -= pattBndsX->min();
183 y0 -= pattBndsY->middle();
189 xspace *= pattBndsX->extent();
190 noffset *= pattBndsY->extent();
191 toffset *= pattBndsX->extent();
195 if (xspace < -pattBndsX->extent() * 0.9) {
196 xspace = -pattBndsX->extent() * 0.9;
207 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > paths_in;
210 for (
auto path_i : paths_in){
214 uskeleton = remove_short_cuts(uskeleton, 0.01);
216 if (
Geom::are_near(pwd2_in[0].at0(),pwd2_in[pwd2_in.size()-1].at1(), 0.01)) {
225 nbCopies =
static_cast<int>(
floor((uskeleton.
domain().
extent() - toffset + xspace)/(pattBndsX->extent()+xspace)));
226 pattBndsX =
Interval(pattBndsX->min(),pattBndsX->max()+xspace);
230 nbCopies = (toffset + pattBndsX->extent() < uskeleton.
domain().
extent()) ? 1 : 0;
235 scaling = (uskeleton.
domain().
extent() - toffset)/pattBndsX->extent();
240 if (
are_near(path_i.segs.front().at0(), path_i.segs.back().at1())){
241 nbCopies = std::max(1,
static_cast<int>(std::floor((uskeleton.
domain().
extent() - toffset)/(pattBndsX->extent()+xspace))));
242 pattBndsX =
Interval(pattBndsX->min(),pattBndsX->max()+xspace);
243 scaling = (uskeleton.
domain().
extent() - toffset)/(((
double)nbCopies)*pattBndsX->extent());
246 nbCopies = std::max(1,
static_cast<int>(std::floor((uskeleton.
domain().
extent() - toffset + xspace)/(pattBndsX->extent()+xspace))));
247 pattBndsX =
Interval(pattBndsX->min(),pattBndsX->max()+xspace);
248 scaling = (uskeleton.
domain().
extent() - toffset)/(((
double)nbCopies)*pattBndsX->extent() - xspace);
257 scaling = ceil(scaling * 1000000) / 1000000;
258 double pattWidth = pattBndsX->extent() * scaling;
269 for (
int i=0; i<nbCopies; i++){
272 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > splited_output_piece =
split_at_discontinuities(output_piece);
273 pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() );
282 for (
const auto & i : pre_output){
305 _(
"Change the width"));
320 Geom::Point const s = snap_knot_position(p, state);
321 SPShape const *sp_shape = cast<SPShape>(cast<SPLPEItem>(
item));
324 auto curve_before = *
c;
332 ray.setPoints(ptA, (*cubic)[1]);
334 ray.setAngle(ray.angle() + Geom::rad_from_deg(90));
336 Geom::Coord nearest_to_ray = ray.nearestTime(knot_pos);
337 if(nearest_to_ray == 0){
353KnotHolderEntityWidthPatternAlongPath::knot_get()
const
355 LPEPatternAlongPath *lpe =
dynamic_cast<LPEPatternAlongPath *
> (_effect);
356 if (
auto const sp_shape = cast<SPShape>(cast<SPLPEItem>(
item))) {
358 auto curve_before = *
c;
366 ray.setPoints(ptA, (*cubic)[1]);
368 ray.setAngle(ray.angle() + Geom::rad_from_deg(90));
370 lpe->helper_path.clear();
371 if (!lpe->hide_knot) {
374 lpe->helper_path.push_back(hp);
Conversion between Bezier control points and SBasis curves.
3x3 matrix representing an affine transformation.
Affine inverse() const
Compute the inverse matrix.
Bezier curve with compile-time specified order.
Abstract continuous curve on a plane defined on [0,1].
Adaptor that creates 2D functions from 1D ones.
constexpr C extent() const
Range of real numbers that is never empty.
Range of real numbers that can be empty.
Axis-aligned rectangle that can be empty.
OptRect boundsFast() const
void clear()
Remove all paths from the vector.
bool empty() const
Check whether the vector contains any paths.
Sequence of contiguous curves, aka spline.
Point pointAt(Coord t) const
Get the point at the specified time value.
Curve const & front() const
Access the first curve in the path.
Curve const & curveAt(Coord t, Coord *rest=NULL) const
Get the curve at the specified time value.
Function defined as discrete pieces.
void concat(const Piecewise< T > &other)
Two-dimensional point that doubles as a vector.
static Point polar(Coord angle, Coord radius)
Construct a point from its polar coordinates.
Straight ray from a specific point to infinity.
void registerParameter(Parameter *param)
bool _provides_knotholder_entities
BoolParam vertical_pattern
void addKnotHolderEntities(KnotHolder *knotholder, SPItem *item) override
~LPEPatternAlongPath() override
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
ScalarParam fuse_tolerance
void transform_multiply(Geom::Affine const &postmul, bool set) override
Overridden function to apply transforms for example to powerstroke, jointtype or tapperstroke.
Geom::PathVector helper_path
EnumParam< PAPCopyType > copytype
Geom::Piecewise< Geom::D2< Geom::SBasis > > doEffect_pwd2(Geom::Piecewise< Geom::D2< Geom::SBasis > > const &pwd2_in) override
friend class WPAP::KnotHolderEntityWidthPatternAlongPath
bool doOnOpen(SPLPEItem const *lpeitem) override
Is performed on load document or revert If the item is fixed legacy return true.
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...
ScalarParam normal_offset
LPEPatternAlongPath(LivePathEffectObject *lpeobject)
Geom::PathVector const & get_pathvector() const
Geom::Piecewise< Geom::D2< Geom::SBasis > > const & get_pwd2()
void param_transform_multiply(Geom::Affine const &postmul, bool set) override
Geom::Affine get_relative_affine()
void param_set_digits(unsigned digits)
void param_set_increments(double step, double page)
void param_set_value(double val)
Preference storage class.
static Preferences * get()
Access the singleton Preferences object.
void setDouble(Glib::ustring const &pref_path, double value)
Set a floating point value.
Simplified management of enumerations of svg items with UI labels.
KnotHolderEntity definition.
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)
virtual void update_knot()
std::list< KnotHolderEntity * > entity
void add(KnotHolderEntity *e)
Inkscape::LivePathEffect::Effect * _effect
Base class for visual SVG elements.
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
void hide()
Hide knot on its canvas.
bool pathEffectsEnabled() const
bool optimizeTransforms()
returns false when LPE write unoptimiced
Base class for shapes, including <path> element.
Geom::PathVector const * curveForEdit() const
Return a borrowed pointer of the curve for edit.
double Coord
Floating point type used to store coordinates.
auto floor(Geom::Rect const &rect)
Various utility functions.
D2< Piecewise< SBasis > > make_cuts_independent(Piecewise< D2< SBasis > > const &a)
OptInterval bounds_exact(Bezier const &b)
Angle distance(Angle const &a, Angle const &b)
std::vector< Geom::Piecewise< Geom::D2< Geom::SBasis > > > split_at_discontinuities(Geom::Piecewise< Geom::D2< Geom::SBasis > > const &pwsbin, double tol=.0001)
std::vector< Piecewise< D2< SBasis > > > fuse_nearby_ends(std::vector< Piecewise< D2< SBasis > > > const &f, double tol=0)
D2< T > compose(D2< T > const &a, T const &b)
Bezier derivative(Bezier const &a)
Piecewise< D2< SBasis > > arc_length_parametrization(D2< SBasis > const &M, unsigned order=3, double tol=.01)
Piecewise< D2< SBasis > > force_continuity(Piecewise< D2< SBasis > > const &f, double tol=0, bool closed=false)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
D2< T > rot90(D2< T > const &a)
static const Util::EnumData< PAPCopyType > PAPCopyTypeData[PAPCT_END]
@ PAPCT_REPEATED_STRETCHED
static const Util::EnumDataConverter< PAPCopyType > PAPCopyTypeConverter(PAPCopyTypeData, PAPCT_END)
Helper class to stream background task notifications as a series of messages.
@ CANVAS_ITEM_CTRL_TYPE_LPE
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.
Generalized time value in the path.
Simplified management of enumerations of svg items with UI labels.