Code

add powerstroke initial shot
[inkscape.git] / src / live_effects / lpe-powerstroke.cpp
1 #define INKSCAPE_LPE_POWERSTROKE_CPP
2 /** \file
3  * @brief  PowerStroke LPE implementation. Creates curves with modifiable stroke width.
4  */
5 /* Authors:
6  *   Johan Engelen <j.b.c.engelen@utwente.nl>
7  *
8  * Copyright (C) 2010 Authors
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #include "live_effects/lpe-powerstroke.h"
15 #include "sp-shape.h"
16 #include "display/curve.h"
18 #include <2geom/path.h>
19 #include <2geom/piecewise.h>
20 #include <2geom/sbasis-geometric.h>
21 #include <2geom/svg-elliptical-arc.h>
22 #include <2geom/transforms.h>
24 namespace Inkscape {
25 namespace LivePathEffect {
27 LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) :
28     Effect(lpeobject),
29     offset_1(_("Start Offset"), _("Handle to control the distance of the offset from the curve"), "offset_1", &wr, this),
30     offset_2(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_2", &wr, this),
31     offset_3(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_3", &wr, this)
32 //    offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this)
33 {
34     show_orig_path = true;
36     registerParameter( dynamic_cast<Parameter *>(&offset_1) );
37     registerParameter( dynamic_cast<Parameter *>(&offset_2) );
38     registerParameter( dynamic_cast<Parameter *>(&offset_3) );
39 //    registerParameter( dynamic_cast<Parameter *>(&offset_points) );
41     /* register all your knotholder handles here: */
42     //registerKnotHolderHandle(new PowerStroke::KnotHolderEntityAttachMyHandle(), _("help message"));
43 }
45 LPEPowerStroke::~LPEPowerStroke()
46 {
48 }
51 void
52 LPEPowerStroke::doOnApply(SPLPEItem *lpeitem)
53 {
54     offset_1.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->first_point()));
55     offset_2.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->last_point()));
56     offset_3.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->last_point()));
57 }
59 static void append_half_circle(Geom::Piecewise<Geom::D2<Geom::SBasis> > &pwd2,
60                                Geom::Point const center, Geom::Point const &dir) {
61     using namespace Geom;
63     double r = L2(dir);
64     SVGEllipticalArc cap(center + dir, r, r, angle_between(Point(1,0), dir), false, false, center - dir);
65     Piecewise<D2<SBasis> > cap_pwd2(cap.toSBasis());
66     pwd2.continuousConcat(cap_pwd2);
67 }
69 Geom::Piecewise<Geom::D2<Geom::SBasis> >
70 LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
71 {
72     using namespace Geom;
74     double t1 = nearest_point(offset_1, pwd2_in);
75     double offset1 = L2(pwd2_in.valueAt(t1) - offset_1);
77     double t2 = nearest_point(offset_2, pwd2_in);
78     double offset2 = L2(pwd2_in.valueAt(t2) - offset_2);
80     double t3 = nearest_point(offset_3, pwd2_in);
81     double offset3 = L2(pwd2_in.valueAt(t3) - offset_3);
83     /*
84     unsigned number_of_points = offset_points.data.size();
85     double* t = new double[number_of_points];
86     Point*  offset = new double[number_of_points];
87     for (unsigned i = 0; i < number_of_points; ++i) {
88         t[i] = nearest_point(offset_points.data[i], pwd2_in);
89         Point A = pwd2_in.valueAt(t[i]);
90         offset[i] = L2(A - offset_points.data[i]);
91     }
92     */
94     // create stroke path where points (x,y) = (t, offset)
95     Path strokepath;
96     strokepath.start( Point(pwd2_in.domain().min(),0) );
97     strokepath.appendNew<Geom::LineSegment>( Point(t1, offset1) );
98     strokepath.appendNew<Geom::LineSegment>( Point(t2, offset2) );
99     strokepath.appendNew<Geom::LineSegment>( Point(t3, offset3) );
100     strokepath.appendNew<Geom::LineSegment>( Point(pwd2_in.domain().max(), 0) );
101     strokepath.appendNew<Geom::LineSegment>( Point(t3, -offset3) );
102     strokepath.appendNew<Geom::LineSegment>( Point(t2, -offset2) );
103     strokepath.appendNew<Geom::LineSegment>( Point(t1, -offset1) );
104     strokepath.close();
105     
106     D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(strokepath.toPwSb());
107     Piecewise<SBasis> x = Piecewise<SBasis>(patternd2[0]);
108     Piecewise<SBasis> y = Piecewise<SBasis>(patternd2[1]);
110     Piecewise<D2<SBasis> > der = unitVector(derivative(pwd2_in));
111     Piecewise<D2<SBasis> > n   = rot90(der);
113 //    output  = pwd2_in + n * offset;
114 //    append_half_circle(output, pwd2_in.lastValue(), n.lastValue() * offset);
115 //    output.continuousConcat(reverse(pwd2_in - n * offset));
116 //    append_half_circle(output, pwd2_in.firstValue(), -n.firstValue() * offset);
118     Piecewise<D2<SBasis> > output = compose(pwd2_in,x) + y*compose(n,x);
119     return output;
123 /* ########################
124  *  Define the classes for your knotholder handles here
125  */
127 /*
128 namespace PowerStroke {
130 class KnotHolderEntityMyHandle : public LPEKnotHolderEntity
132 public:
133     // the set() and get() methods must be implemented, click() is optional
134     virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
135     virtual Geom::Point knot_get();
136     //virtual void knot_click(guint state);
137 };
139 } // namespace PowerStroke
140 */
142 /* ######################## */
144 } //namespace LivePathEffect
145 } /* namespace Inkscape */
147 /*
148   Local Variables:
149   mode:c++
150   c-file-style:"stroustrup"
151   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
152   indent-tabs-mode:nil
153   fill-column:99
154   End:
155 */
156 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :