Code

a0a473fe7fdcbdcc6fecabf24685d34a5235d789
[inkscape.git] / src / live_effects / lpe-curvestitch.cpp
1 #define INKSCAPE_LPE_EXPRESSION_CPP\r
2 /** \file\r
3  * SVG <skeleton> implementation, used as an example for a base starting class\r
4  * when implementing new LivePathEffects.\r
5  *\r
6  */\r
7 /*\r
8  * Authors:\r
9  *   Johan Engelen\r
10 *\r
11 * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>\r
12  *\r
13  * Released under GNU GPL, read the file 'COPYING' for more information\r
14  */\r
15 \r
16 #include "live_effects/lpe-curvestitch.h"\r
17 #include "display/curve.h"\r
18 #include <libnr/n-art-bpath.h>\r
19 \r
20 #include <2geom/path.h>\r
21 #include <2geom/piecewise.h>\r
22 #include <2geom/sbasis.h>\r
23 #include <2geom/sbasis-geometric.h>\r
24 #include <2geom/bezier-to-sbasis.h>\r
25 #include <2geom/sbasis-to-bezier.h>\r
26 #include <2geom/d2.h>\r
27 #include <2geom/matrix.h>\r
28 \r
29 \r
30 #include "ui/widget/scalar.h"\r
31 #include "libnr/nr-values.h"\r
32 \r
33 namespace Inkscape {\r
34 namespace LivePathEffect {\r
35 \r
36 using namespace Geom;\r
37 \r
38 LPECurveStitch::LPECurveStitch(LivePathEffectObject *lpeobject) :\r
39     Effect(lpeobject),\r
40     strokepath(_("Stroke path"), _("The path that will be stroked, whatever, think of good text here."), "strokepath", &wr, this, "M0,0 L1,0"),\r
41     nrofpaths(_("Nr of paths"), _("The number of paths that will be generated."), "count", &wr, this, 5),\r
42     startpoint_variation(_("Startpoint variation"), _("..."), "startpoint_variation", &wr, this, 0),\r
43     endpoint_variation(_("Endpoint variation"), _("..."), "endpoint_variation", &wr, this, 0),\r
44     scale_y(_("Scale stroke y"), _("Scale the height of the stroke path with its length"), "scale_stroke_y", &wr, this, false)\r
45 {\r
46     registerParameter( dynamic_cast<Parameter *>(&nrofpaths) );\r
47     registerParameter( dynamic_cast<Parameter *>(&startpoint_variation) );\r
48     registerParameter( dynamic_cast<Parameter *>(&endpoint_variation) );\r
49     registerParameter( dynamic_cast<Parameter *>(&strokepath) );\r
50     registerParameter( dynamic_cast<Parameter *>(&scale_y) );\r
51 \r
52     nrofpaths.param_make_integer();\r
53     nrofpaths.param_set_range(2, NR_HUGE);\r
54 \r
55 //    startpoint_variation.param_set_range(-NR_HUGE, 1);\r
56 //    endpoint_variation.param_set_range(-1, NR_HUGE);\r
57 }\r
58 \r
59 LPECurveStitch::~LPECurveStitch()\r
60 {\r
61 \r
62 }\r
63 \r
64 std::vector<Geom::Path>\r
65 LPECurveStitch::doEffect (std::vector<Geom::Path> & path_in)\r
66 {\r
67     if (path_in.size() >= 2) {\r
68         startpoint_variation.resetRandomizer();\r
69         endpoint_variation.resetRandomizer();\r
70 \r
71         D2<Piecewise<SBasis> > stroke = make_cuts_independant(strokepath);\r
72         Interval bndsStroke = bounds_exact(stroke[0]);\r
73         gdouble scaling = bndsStroke.max() - bndsStroke.min();\r
74         Interval bndsStrokeY = bounds_exact(stroke[1]);\r
75         Point stroke_origin(bndsStroke.min(), (bndsStrokeY.max()+bndsStrokeY.min())/2);\r
76 \r
77         std::vector<Geom::Path> path_out (nrofpaths);\r
78 \r
79         // do this for all permutations if there are more than 2 paths? realllly cool!\r
80         Piecewise<D2<SBasis> > A = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[0].toPwSb()),2,.1);\r
81         Piecewise<D2<SBasis> > B = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[1].toPwSb()),2,.1);\r
82         Interval bndsA = A.domain();\r
83         Interval bndsB = B.domain();\r
84         gdouble incrementA = (bndsA.max()-bndsA.min()) / (nrofpaths-1);\r
85         gdouble incrementB = (bndsB.max()-bndsB.min()) / (nrofpaths-1);\r
86         gdouble tA = bndsA.min();\r
87         gdouble tB = bndsB.min();\r
88         for (int i = 0; i < nrofpaths; i++) {\r
89             Point start = A(tA);\r
90             Point end = B(tB);\r
91             if (startpoint_variation.get_value() != 0)\r
92                 start = start + startpoint_variation * (end - start);\r
93             if (endpoint_variation.get_value() != 0)\r
94                 end = end + endpoint_variation * (end - start);\r
95     \r
96             Matrix transform;\r
97             transform.setXAxis( (end-start) / scaling );\r
98             gdouble scaling_y = scale_y.get_value() ? L2(end-start)/scaling : 1.0;\r
99             transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y);\r
100             transform.setTranslation( start );\r
101             Piecewise<D2<SBasis> > pwd2_out = (strokepath-stroke_origin) * transform;\r
102             // add stuff to one big pw<d2<sbasis> > and then outside the loop convert to path?\r
103             std::vector<Path> result = Geom::path_from_piecewise(pwd2_out, LPE_CONVERSION_TOLERANCE);\r
104             path_out[i] = result[0];\r
105             tA += incrementA;\r
106             tB += incrementB;\r
107         }\r
108 \r
109         return path_out;\r
110     } else {\r
111         return path_in;\r
112     }\r
113 }\r
114 \r
115 } //namespace LivePathEffect\r
116 } /* namespace Inkscape */\r
117 \r
118 /*\r
119   Local Variables:\r
120   mode:c++\r
121   c-file-style:"stroustrup"\r
122   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
123   indent-tabs-mode:nil\r
124   fill-column:99\r
125   End:\r
126 */\r
127 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r