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 "sp-path.h"
19 #include "line-geometry.h"
20 #include "sp-lpe-item.h"
21 #include <2geom/path.h>
23 namespace Inkscape {
24 namespace LivePathEffect {
25 namespace PB {
27 class KnotHolderEntityEnd : public LPEKnotHolderEntity {
28 public:
29 void bisector_end_set(Geom::Point const &p, bool left = true);
30 };
32 class KnotHolderEntityLeftEnd : public KnotHolderEntityEnd {
33 public:
34 virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
35 virtual Geom::Point knot_get();
36 };
38 class KnotHolderEntityRightEnd : public KnotHolderEntityEnd {
39 public:
40 virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
41 virtual Geom::Point knot_get();
42 };
44 // TODO: Make this more generic
45 static LPEPerpBisector *
46 get_effect(SPItem *item)
47 {
48 Effect *effect = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item));
49 if (effect->effectType() != PERP_BISECTOR) {
50 g_print ("Warning: Effect is not of type LPEPerpBisector!\n");
51 return NULL;
52 }
53 return static_cast<LPEPerpBisector *>(effect);
54 }
56 Geom::Point
57 KnotHolderEntityLeftEnd::knot_get() {
58 Inkscape::LivePathEffect::LPEPerpBisector *lpe = get_effect(item);
59 return Geom::Point(lpe->C);
60 }
62 Geom::Point
63 KnotHolderEntityRightEnd::knot_get() {
64 Inkscape::LivePathEffect::LPEPerpBisector *lpe = get_effect(item);
65 return Geom::Point(lpe->D);
66 }
68 void
69 KnotHolderEntityEnd::bisector_end_set(Geom::Point const &p, bool left) {
70 Inkscape::LivePathEffect::LPEPerpBisector *lpe =
71 dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));
72 if (!lpe) return;
74 Geom::Point const s = snap_knot_position(p);
76 double lambda = Geom::nearest_point(s, lpe->M, lpe->perp_dir);
77 if (left) {
78 lpe->C = lpe->M + lpe->perp_dir * lambda;
79 lpe->length_left.param_set_value(lambda);
80 } else {
81 lpe->D = lpe->M + lpe->perp_dir * lambda;
82 lpe->length_right.param_set_value(-lambda);
83 }
85 // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
86 sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true, true);
87 }
89 void
90 KnotHolderEntityLeftEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) {
91 bisector_end_set(p);
92 }
94 void
95 KnotHolderEntityRightEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) {
96 bisector_end_set(p, false);
97 }
99 /**
100 Geom::Point path_start_get(SPItem *item) {
101 Inkscape::LivePathEffect::LPEPerpBisector *lpe =
102 dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));
104 if (lpe)
105 return Geom::Point(lpe->A);
106 else
107 return Geom::Point(0,0);
108 }
110 Geom::Point path_end_get(SPItem *item) {
111 Inkscape::LivePathEffect::LPEPerpBisector *lpe =
112 dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));
114 if (lpe)
115 return Geom::Point(lpe->B);
116 else
117 return Geom::Point(0,0);
118 }
120 void
121 path_set_start_end(SPItem *item, Geom::Point const &p, bool start) {
122 SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(item)); // TODO: Should we use sp_shape_get_curve()?
123 Geom::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(item)));
125 Geom::Point A, B;
126 if (start) {
127 A = p;
128 B = curve->last_point();
129 } else {
130 A = curve->first_point();
131 B = p;
132 }
134 SPCurve *c = new SPCurve();
135 c->moveto(A);
136 c->lineto(B);
137 sp_path_set_original_curve(SP_PATH(item), c, TRUE, true);
138 c->unref();
139 }
140 **/
142 //void path_start_set(SPItem *item, Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) {
143 // path_set_start_end(item, p);
144 //}
146 //void path_end_set(SPItem *item, Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) {
147 // path_set_start_end(item, p, false);
148 //}
150 } //namescape PB
152 LPEPerpBisector::LPEPerpBisector(LivePathEffectObject *lpeobject) :
153 Effect(lpeobject),
154 length_left(_("Length left"), _("Specifies the left end of the bisector"), "length-left", &wr, this, 200),
155 length_right(_("Length right"), _("Specifies the right end of the bisector"), "length-right", &wr, this, 200),
156 A(0,0), B(0,0), M(0,0), C(0,0), D(0,0), perp_dir(0,0)
157 {
158 show_orig_path = true;
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 **/
172 }
174 LPEPerpBisector::~LPEPerpBisector()
175 {
176 }
178 void
179 LPEPerpBisector::doOnApply (SPLPEItem */*lpeitem*/)
180 {
181 /* make the path a straight line */
182 /**
183 SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()?
185 Geom::Point A(curve->first_point());
186 Geom::Point B(curve->last_point());
188 SPCurve *c = new SPCurve();
189 c->moveto(A);
190 c->lineto(B);
191 // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work?
192 SP_PATH(lpeitem)->original_curve = c->ref();
193 c->unref();
194 **/
195 }
198 Geom::Piecewise<Geom::D2<Geom::SBasis> >
199 LPEPerpBisector::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
200 {
201 using namespace Geom;
203 Piecewise<D2<SBasis> > output;
205 A = pwd2_in.firstValue();
206 B = pwd2_in.lastValue();
207 M = (A + B)/2;
209 perp_dir = unit_vector((B - A).ccw());
211 C = M + perp_dir * length_left;
212 D = M - perp_dir * length_right;
214 output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
216 return output;
217 }
219 /* ######################## */
221 } //namespace LivePathEffect
222 } /* namespace Inkscape */
224 /*
225 Local Variables:
226 mode:c++
227 c-file-style:"stroustrup"
228 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
229 indent-tabs-mode:nil
230 fill-column:99
231 End:
232 */
233 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :