Code

b0e8dc8f7106cc0333159a46e3f9339ea7a58120
[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 {\r
45     registerParameter( dynamic_cast<Parameter *>(&nrofpaths) );\r
46     registerParameter( dynamic_cast<Parameter *>(&startpoint_variation) );\r
47     registerParameter( dynamic_cast<Parameter *>(&endpoint_variation) );\r
48     registerParameter( dynamic_cast<Parameter *>(&strokepath) );\r
49 \r
50     nrofpaths.param_make_integer();\r
51     nrofpaths.param_set_range(2, NR_HUGE);\r
52 \r
53 //    startpoint_variation.param_set_range(-NR_HUGE, 1);\r
54 //    endpoint_variation.param_set_range(-1, NR_HUGE);\r
55 }\r
56 \r
57 LPECurveStitch::~LPECurveStitch()\r
58 {\r
59 \r
60 }\r
61 \r
62 std::vector<Geom::Path>\r
63 LPECurveStitch::doEffect (std::vector<Geom::Path> & path_in)\r
64 {\r
65     if (path_in.size() >= 2) {\r
66         D2<Piecewise<SBasis> > stroke = make_cuts_independant(strokepath);\r
67         Interval bndsStroke = bounds_exact(stroke[0]);\r
68         gdouble scaling = bndsStroke.max() - bndsStroke.min();\r
69         Interval bndsStrokeY = bounds_exact(stroke[1]);\r
70         Point stroke_origin(bndsStroke.min(), (bndsStrokeY.max()+bndsStrokeY.min())/2);\r
71 \r
72         std::vector<Geom::Path> path_out (nrofpaths);\r
73 \r
74         // do this for all permutations if there are more than 2 paths? realllly cool!\r
75         Piecewise<D2<SBasis> > A = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[0].toPwSb()),2,.1);\r
76         Piecewise<D2<SBasis> > B = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[1].toPwSb()),2,.1);\r
77         Interval bndsA = A.domain();\r
78         Interval bndsB = B.domain();\r
79         gdouble incrementA = (bndsA.max()-bndsA.min()) / (nrofpaths-1);\r
80         gdouble incrementB = (bndsB.max()-bndsB.min()) / (nrofpaths-1);\r
81         gdouble tA = bndsA.min();\r
82         gdouble tB = bndsB.min();\r
83         for (int i = 0; i < nrofpaths; i++) {\r
84             Point start = A(tA);\r
85             Point end = B(tB);\r
86             if (startpoint_variation != 0)\r
87                 start = start + g_random_double_range(0, startpoint_variation) * (end - start);\r
88             if (endpoint_variation != 0)\r
89                 end = end + g_random_double_range(0, endpoint_variation) * (end - start);\r
90     \r
91             Matrix transform;\r
92             transform.setXAxis( (end-start) / scaling );\r
93             transform.setYAxis( rot90(unit_vector(end-start)));\r
94             transform.setTranslation( start );\r
95             Piecewise<D2<SBasis> > pwd2_out = (strokepath-stroke_origin) * transform;\r
96             std::vector<Path> result = Geom::path_from_piecewise(pwd2_out, LPE_CONVERSION_TOLERANCE);\r
97             path_out[i] = result[0];\r
98             tA += incrementA;\r
99             tB += incrementB;\r
100         }\r
101 \r
102         return path_out;\r
103     } else {\r
104         return path_in;\r
105     }\r
106 }\r
107 \r
108 } //namespace LivePathEffect\r
109 } /* namespace Inkscape */\r
110 \r
111 /*\r
112   Local Variables:\r
113   mode:c++\r
114   c-file-style:"stroustrup"\r
115   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
116   indent-tabs-mode:nil\r
117   fill-column:99\r
118   End:\r
119 */\r
120 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r