Code

Write all effect parameters to SVG when a LPE knotholder handle is ungrabbed
[inkscape.git] / src / live_effects / lpe-perp_bisector.cpp
1 #define INKSCAPE_LPE_PERP_BISECTOR_CPP
2 /** \file
3  * LPE <perp_bisector> implementation.
4  */
5 /*
6  * Authors:
7  *   Maximilian Albert
8  *   Johan Engelen
9  *
10  * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
11  * Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com>
12  *
13  * Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #include "live_effects/lpe-perp_bisector.h"
17 #include "display/curve.h"
18 #include <libnr/n-art-bpath.h>
19 #include "sp-path.h"
20 #include "line-geometry.h"
21 #include "sp-lpe-item.h"
22 #include <2geom/path.h>
24 namespace Inkscape {
25 namespace LivePathEffect {
26 namespace PB {
28 class KnotHolderEntityLeftEnd : public KnotHolderEntity
29 {
30 public:
31     virtual bool isLPEParam() { return true; }
33     virtual void knot_set(NR::Point const &p, NR::Point const &origin, guint state);
34     virtual NR::Point knot_get();
35 };
37 class KnotHolderEntityRightEnd : public KnotHolderEntity
38 {
39 public:
40     virtual bool isLPEParam() { return true; }
42     virtual void knot_set(NR::Point const &p, NR::Point const &origin, guint state);
43     virtual NR::Point knot_get();
44 };
46 // TODO: Make this more generic
47 static LPEPerpBisector *
48 get_effect(SPItem *item)
49 {
50     Effect *effect = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item));
51     if (effect->effectType() != PERP_BISECTOR) {
52         g_print ("Warning: Effect is not of type LPEPerpBisector!\n");
53         return NULL;
54     }
55     return static_cast<LPEPerpBisector *>(effect);
56 }
58 NR::Point
59 KnotHolderEntityLeftEnd::knot_get() {
60     Inkscape::LivePathEffect::LPEPerpBisector *lpe = get_effect(item);
61     return NR::Point(lpe->C);
62 }
64 NR::Point
65 KnotHolderEntityRightEnd::knot_get() {
66     Inkscape::LivePathEffect::LPEPerpBisector *lpe = get_effect(item);
67     return NR::Point(lpe->D);
68 }
70 void
71 bisector_end_set(SPItem *item, NR::Point const &p, bool left) {
72     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
73         dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));
75     if (!lpe)
76         return;
78     double lambda = Geom::nearest_point(p.to_2geom(), lpe->M, lpe->perp_dir);
79     if (left) {
80         lpe->C = lpe->M + lpe->perp_dir * lambda;
81         lpe->length_left.param_set_value(lambda);
82     } else {
83         lpe->D = lpe->M + lpe->perp_dir * lambda;
84         lpe->length_right.param_set_value(-lambda);
85     }
87     // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
88     sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true, true);
89 }
91 void
92 KnotHolderEntityLeftEnd::knot_set(NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
93     bisector_end_set(item, p);
94 }
96 void
97 KnotHolderEntityRightEnd::knot_set(NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
98     bisector_end_set(item, p, false);
99 }
101 /**
102 NR::Point path_start_get(SPItem *item) {
103     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
104         dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));
106     if (lpe)
107         return NR::Point(lpe->A);
108     else
109         return NR::Point(0,0);
112 NR::Point path_end_get(SPItem *item) {
113     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
114         dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));
116     if (lpe)
117         return NR::Point(lpe->B);
118     else
119         return NR::Point(0,0);
122 void
123 path_set_start_end(SPItem *item, NR::Point const &p, bool start) {
124     SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(item)); // TODO: Should we use sp_shape_get_curve()?
125     NR::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(item)));
127     Geom::Point A, B;
128     if (start) {
129         A = p.to_2geom();
130         B = (curve->last_point()).to_2geom();
131     } else {
132         A = (curve->first_point()).to_2geom();
133         B = (p.to_2geom());
134     }
136     SPCurve *c = new SPCurve();
137     c->moveto(A);
138     c->lineto(B);
139     sp_path_set_original_curve(SP_PATH(item), c, TRUE, true);
140     c->unref();
142 **/
144 //void path_start_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
145 //    path_set_start_end(item, p);
146 //}
148 //void path_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
149 //    path_set_start_end(item, p, false);
150 //}
152 } //namescape PB
154 LPEPerpBisector::LPEPerpBisector(LivePathEffectObject *lpeobject) :
155     Effect(lpeobject),
156     length_left(_("Length left"), _("Specifies the left end of the bisector"), "length-left", &wr, this, 200),
157     length_right(_("Length right"), _("Specifies the right end of the bisector"), "length-right", &wr, this, 200),
158     A(0,0), B(0,0), M(0,0), C(0,0), D(0,0), perp_dir(0,0)
160     // register all your parameters here, so Inkscape knows which parameters this effect has:
161     registerParameter( dynamic_cast<Parameter *>(&length_left) );
162     registerParameter( dynamic_cast<Parameter *>(&length_right) );
164     registerKnotHolderHandle(new PB::KnotHolderEntityLeftEnd(), _("Lala"));
165     registerKnotHolderHandle(new PB::KnotHolderEntityRightEnd(), _("Lolo"));
166 /**
167     registerKnotHolderHandle(path_start_set, path_start_get);
168     registerKnotHolderHandle(path_end_set, path_end_get);
169     registerKnotHolderHandle(bisector_left_end_set, bisector_left_end_get);
170     registerKnotHolderHandle(bisector_right_end_set, bisector_right_end_get);
171 **/
174 LPEPerpBisector::~LPEPerpBisector()
178 void
179 LPEPerpBisector::doOnApply (SPLPEItem *lpeitem)
181     /* make the path a straight line */
182     SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()?
184     Geom::Point A((curve->first_point()).to_2geom());
185     Geom::Point B((curve->last_point()).to_2geom());
187     SPCurve *c = new SPCurve();
188     c->moveto(A);
189     c->lineto(B);
190     // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work?
191     SP_PATH(lpeitem)->original_curve = c->ref();
192     c->unref();
196 Geom::Piecewise<Geom::D2<Geom::SBasis> >
197 LPEPerpBisector::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
199     using namespace Geom;
201     Piecewise<D2<SBasis> > output;
203     A = pwd2_in.firstValue();
204     B = pwd2_in.lastValue();
205     M = (A + B)/2;
207     perp_dir = unit_vector((B - A).ccw());
209     C = M + perp_dir * length_left;
210     D = M - perp_dir * length_right;
212     output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
214     return output;
217 /* ######################## */
219 } //namespace LivePathEffect
220 } /* namespace Inkscape */
222 /*
223   Local Variables:
224   mode:c++
225   c-file-style:"stroustrup"
226   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
227   indent-tabs-mode:nil
228   fill-column:99
229   End:
230 */
231 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :