Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
lpe-interpolate.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
5/*
6 * Authors:
7 * Johan Engelen
8 *
9 * Copyright (C) Johan Engelen 2007-2008 <j.b.c.engelen@utwente.nl>
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
15#include "display/curve.h"
16#include "object/sp-path.h"
17
18// TODO due to internal breakage in glibmm headers, this must be last:
19#include <glibmm/i18n.h>
20
21
22namespace Inkscape {
23namespace LivePathEffect {
24
26 : Effect(lpeobject)
27 , trajectory_path(_("Trajectory:"), _("Path along which intermediate steps are created."), "trajectory", &wr, this,
28 "M0,0 L0,0")
29 , number_of_steps(_("Steps_:"), _("Determines the number of steps from start to end path."), "steps", &wr, this, 5)
30 , equidistant_spacing(_("E_quidistant spacing"),
31 _("If true, the spacing between intermediates is constant along the length of the path. If "
32 "false, the distance depends on the location of the nodes of the trajectory path."),
33 "equidistant_spacing", &wr, this, true)
34{
35 show_orig_path = true;
36
40
42 number_of_steps.param_set_range(2, std::numeric_limits<gint>::max());
43}
44
46
47
48bool
50{
51 if (!is_load || is_applied) {
52 return false;
53 }
55 return false;
56}
57
58
65
66/*
67 * interpolate path_in[0] to path_in[1]
68 */
70{
71 if ((path_in.size() < 2) || (number_of_steps < 2)) {
72 return path_in;
73 }
74 // Don't allow empty path parameter:
76 return path_in;
77 }
78 if (is_load) {
80 }
81
82 Geom::PathVector path_out;
83
84 Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_A = path_in[0].toPwSb();
85 Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_B = path_in[1].toPwSb();
86
87 // Transform both paths to (0,0) midpoint, so they can easily be positioned along interpolate_path
88 Geom::OptRect bounds_A = Geom::bounds_exact(pwd2_A);
89 if (bounds_A) {
90 pwd2_A -= bounds_A->midpoint();
91 }
92 Geom::OptRect bounds_B = Geom::bounds_exact(pwd2_B);
93 if (bounds_B) {
94 pwd2_B -= bounds_B->midpoint();
95 }
96
97 // Make sure both paths have the same number of segments and cuts at the same locations
98 pwd2_B.setDomain(pwd2_A.domain());
99 Geom::Piecewise<Geom::D2<Geom::SBasis> > pA = Geom::partition(pwd2_A, pwd2_B.cuts);
100 Geom::Piecewise<Geom::D2<Geom::SBasis> > pB = Geom::partition(pwd2_B, pwd2_A.cuts);
101
102 auto trajectory = calculate_trajectory(bounds_A, bounds_B);
103
104 Geom::Interval trajectory_domain = trajectory.domain();
105
106 for (int i = 0; i < number_of_steps; ++i) {
107 double fraction = i / (number_of_steps - 1);
108
109 Geom::Piecewise<Geom::D2<Geom::SBasis> > pResult = pA * (1 - fraction) + pB * fraction;
110 pResult += trajectory.valueAt(trajectory_domain.min() + fraction * trajectory_domain.extent());
111
112 Geom::PathVector pathv = Geom::path_from_piecewise(pResult, LPE_CONVERSION_TOLERANCE);
113 path_out.push_back(pathv[0]);
114 }
115
116 return path_out;
117}
118
119
120// returns the lpe parameter trajectory_path, transformed so that it starts at the
121// bounding box center of the first path and ends at the bounding box center of the
122// second path
124 Geom::OptRect bounds_B)
125{
127 Geom::Piecewise<Geom::D2<Geom::SBasis> > trajectory = trajectory_path.get_pathvector()[0].toPwSb() * affine;
128
130 trajectory = Geom::arc_length_parametrization(trajectory);
131 }
132
133 if (!bounds_A || !bounds_B) {
134 return trajectory;
135 }
136
137 auto trajectory_start = trajectory.firstValue();
138 auto trajectory_end = trajectory.lastValue();
139
140 auto midpoint_A = bounds_A->midpoint();
141 auto midpoint_B = bounds_B->midpoint();
142
143 Geom::Ray original(trajectory_start, trajectory_end);
144 Geom::Ray transformed(midpoint_A, midpoint_B);
145
146 double rotation = transformed.angle() - original.angle();
147 double scale = Geom::distance(midpoint_A, midpoint_B) / Geom::distance(trajectory_start, trajectory_end);
148
149 Geom::Affine transformation;
150
151 transformation *= Geom::Translate(-trajectory_start);
152 transformation *= Geom::Scale(scale, scale);
153 transformation *= Geom::Rotate(rotation);
154
155 transformation *= Geom::Translate(midpoint_A);
156
157 return trajectory * transformation;
158}
159
161{
163
164 if (!is<SPPath>(item))
165 return;
166
167 auto const *crv = cast<SPPath>(item)->curveForEdit();
168 Geom::PathVector const &pathv = *crv;
169 if ((pathv.size() < 2))
170 return;
171
172 Geom::OptRect bounds_A = pathv[0].boundsExact();
173 Geom::OptRect bounds_B = pathv[1].boundsExact();
174
175 if (bounds_A && bounds_B) {
176 Geom::PathVector traj_pathv;
177 traj_pathv.push_back(Geom::Path());
178 traj_pathv[0].start(bounds_A->midpoint());
179 traj_pathv[0].appendNew<Geom::LineSegment>(bounds_B->midpoint());
180 trajectory_path.set_new_value(traj_pathv, true);
181 }
182 else {
184 }
185}
186
187} // namespace LivePathEffect
188} /* namespace Inkscape */
189
190/*
191 Local Variables:
192 mode:c++
193 c-file-style:"stroustrup"
194 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
195 indent-tabs-mode:nil
196 fill-column:99
197 End:
198*/
199// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
double scale
Definition aa.cpp:228
3x3 matrix representing an affine transformation.
Definition affine.h:70
constexpr C extent() const
constexpr C min() const
Range of real numbers that is never empty.
Definition interval.h:59
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Sequence of subpaths.
Definition pathvector.h:122
size_type size() const
Get the number of paths in the vector.
Definition pathvector.h:147
void push_back(Path const &path)
Append a path at the end.
Definition pathvector.h:172
OptRect boundsExact() const
bool empty() const
Check whether the vector contains any paths.
Definition pathvector.h:145
Sequence of contiguous curves, aka spline.
Definition path.h:353
Function defined as discrete pieces.
Definition piecewise.h:71
Interval domain() const
Definition piecewise.h:215
output_type valueAt(double t) const
Definition piecewise.h:102
output_type lastValue() const
Definition piecewise.h:109
std::vector< double > cuts
Definition piecewise.h:75
output_type firstValue() const
Definition piecewise.h:106
void setDomain(Interval dom)
Definition piecewise.h:218
Straight ray from a specific point to infinity.
Definition ray.h:53
Coord angle() const
Definition ray.h:73
Rotation around the origin.
Definition transforms.h:187
Scaling from the origin.
Definition transforms.h:150
Translation by a vector.
Definition transforms.h:115
void registerParameter(Parameter *param)
Definition effect.cpp:1704
virtual void resetDefaults(SPItem const *item)
Sets all parameters to their default values and writes them to SVG.
Definition effect.cpp:2008
LPEInterpolate(LivePathEffectObject *lpeobject)
Geom::PathVector doEffect_path(Geom::PathVector const &path_in) override
void resetDefaults(SPItem const *item) override
Sets all parameters to their default values and writes them to SVG.
bool doOnOpen(SPLPEItem const *lpeitem) override
Is performed on load document or revert If the item is fixed legacy return true.
Geom::Piecewise< Geom::D2< Geom::SBasis > > calculate_trajectory(Geom::OptRect bounds_A, Geom::OptRect bounds_B)
void transform_multiply(Geom::Affine const &postmul, bool set) override
Overridden function to apply transforms for example to powerstroke, jointtype or tapperstroke.
Geom::PathVector const & get_pathvector() const
Definition path.cpp:99
void set_new_value(Geom::PathVector const &newpath, bool write_to_svg)
Definition path.cpp:370
void param_transform_multiply(Geom::Affine const &postmul, bool set) override
Definition path.cpp:323
Geom::Affine get_relative_affine()
Definition path.cpp:86
void param_set_range(double min, double max)
Base class for visual SVG elements.
Definition sp-item.h:109
bool pathEffectsEnabled() const
bool optimizeTransforms()
returns false when LPE write unoptimiced
SPItem * item
std::string original
LPE interpolate implementation, see lpe-interpolate.cpp.
OptInterval bounds_exact(Bezier const &b)
Definition bezier.cpp:310
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
PathVector path_from_piecewise(Piecewise< D2< SBasis > > const &B, double tol, bool only_cubicbeziers=false)
Make a path from a d2 sbasis.
Piecewise< D2< SBasis > > arc_length_parametrization(D2< SBasis > const &M, unsigned order=3, double tol=.01)
Helper class to stream background task notifications as a series of messages.
Conversion between SBasis and Bezier basis polynomials.