a4c722acc99e8b684ac413f2429d2b91cae33875
1 #define INKSCAPE_LPE_INTERPOLATE_CPP
2 /** \file
3 * LPE interpolate implementation
4 */
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, read the file 'COPYING' for more information
12 */
14 #include "live_effects/lpe-interpolate.h"
16 #include <2geom/path.h>
17 #include <2geom/sbasis-to-bezier.h>
18 #include <2geom/d2-sbasis.h>
19 #include <2geom/piecewise.h>
20 #include <2geom/sbasis-geometric.h>
22 #include "sp-path.h"
23 #include "display/curve.h"
25 namespace Inkscape {
26 namespace LivePathEffect {
28 LPEInterpolate::LPEInterpolate(LivePathEffectObject *lpeobject) :
29 Effect(lpeobject),
30 trajectory_path(_("Trajectory"), _("Path along which intermediate steps are created."), "trajectory", &wr, this, "M0,0 L0,0"),
31 number_of_steps(_("Steps"), _("Determines the number of steps from start to end path."), "steps", &wr, this, 5),
32 equidistant_spacing(_("Equidistant spacing"), _("If true, the spacing between intermediates is constant along the length of the path. If false, the distance depends on the location of the nodes of the trajectory path."), "equidistant_spacing", &wr, this, true)
33 {
34 show_orig_path = true;
36 registerParameter( dynamic_cast<Parameter *>(&trajectory_path) );
37 registerParameter( dynamic_cast<Parameter *>(&equidistant_spacing) );
38 registerParameter( dynamic_cast<Parameter *>(&number_of_steps) );
40 number_of_steps.param_make_integer();
41 number_of_steps.param_set_range(2, NR_HUGE);
42 }
44 LPEInterpolate::~LPEInterpolate()
45 {
47 }
49 /*
50 * interpolate path_in[0] to path_in[1]
51 */
52 Geom::PathVector
53 LPEInterpolate::doEffect_path (Geom::PathVector const & path_in)
54 {
55 if ( (path_in.size() < 2) || (number_of_steps < 2))
56 return path_in;
58 std::vector<Geom::Path> path_out;
60 Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_A = path_in[0].toPwSb();
61 Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_B = path_in[1].toPwSb();
63 // Transform both paths to (0,0) midpoint, so they can easily be positioned along interpolate_path
64 pwd2_A -= Geom::bounds_exact(pwd2_A).midpoint();
65 pwd2_B -= Geom::bounds_exact(pwd2_B).midpoint();
67 // Make sure both paths have the same number of segments and cuts at the same locations
68 pwd2_B.setDomain(pwd2_A.domain());
69 Geom::Piecewise<Geom::D2<Geom::SBasis> > pA = Geom::partition(pwd2_A, pwd2_B.cuts);
70 Geom::Piecewise<Geom::D2<Geom::SBasis> > pB = Geom::partition(pwd2_B, pwd2_A.cuts);
72 Geom::Piecewise<Geom::D2<Geom::SBasis> > trajectory = trajectory_path.get_pathvector()[0].toPwSb();
73 if (equidistant_spacing)
74 trajectory = Geom::arc_length_parametrization(trajectory);
76 Geom::Interval trajectory_domain = trajectory.domain();
78 for (int i = 0; i < number_of_steps; ++i) {
79 double fraction = i / (number_of_steps-1);
81 Geom::Piecewise<Geom::D2<Geom::SBasis> > pResult = pA*(1-fraction) + pB*fraction;
82 pResult += trajectory.valueAt(trajectory_domain.min() + fraction*trajectory_domain.extent());
84 Geom::PathVector pathv = Geom::path_from_piecewise(pResult, LPE_CONVERSION_TOLERANCE);
85 path_out.push_back( pathv[0] );
86 }
88 return path_out;
89 }
91 void
92 LPEInterpolate::resetDefaults(SPItem * item)
93 {
94 if (!SP_IS_PATH(item))
95 return;
97 SPCurve const *crv = sp_path_get_curve_reference(SP_PATH(item));
98 Geom::PathVector const &pathv = crv->get_pathvector();
99 if ( (pathv.size() < 2) )
100 return;
102 Geom::Rect bounds_A = pathv[0].boundsExact();
103 Geom::Rect bounds_B = pathv[1].boundsExact();
105 Geom::PathVector traj_pathv;
106 traj_pathv.push_back( Geom::Path() );
107 traj_pathv[0].start( bounds_A.midpoint() );
108 traj_pathv[0].appendNew<Geom::LineSegment>( bounds_B.midpoint() );
109 trajectory_path.set_new_value( traj_pathv, true );
110 }
112 } //namespace LivePathEffect
113 } /* namespace Inkscape */
115 /*
116 Local Variables:
117 mode:c++
118 c-file-style:"stroustrup"
119 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
120 indent-tabs-mode:nil
121 fill-column:99
122 End:
123 */
124 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :