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);
110 }
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);
120 }
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 Geom::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();
141 }
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)
159 {
160 show_orig_path = true;
162 // register all your parameters here, so Inkscape knows which parameters this effect has:
163 registerParameter( dynamic_cast<Parameter *>(&length_left) );
164 registerParameter( dynamic_cast<Parameter *>(&length_right) );
166 registerKnotHolderHandle(new PB::KnotHolderEntityLeftEnd(), _("Lala"));
167 registerKnotHolderHandle(new PB::KnotHolderEntityRightEnd(), _("Lolo"));
168 /**
169 registerKnotHolderHandle(path_start_set, path_start_get);
170 registerKnotHolderHandle(path_end_set, path_end_get);
171 registerKnotHolderHandle(bisector_left_end_set, bisector_left_end_get);
172 registerKnotHolderHandle(bisector_right_end_set, bisector_right_end_get);
173 **/
174 }
176 LPEPerpBisector::~LPEPerpBisector()
177 {
178 }
180 void
181 LPEPerpBisector::doOnApply (SPLPEItem */*lpeitem*/)
182 {
183 /* make the path a straight line */
184 /**
185 SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()?
187 Geom::Point A((curve->first_point()).to_2geom());
188 Geom::Point B((curve->last_point()).to_2geom());
190 SPCurve *c = new SPCurve();
191 c->moveto(A);
192 c->lineto(B);
193 // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work?
194 SP_PATH(lpeitem)->original_curve = c->ref();
195 c->unref();
196 **/
197 }
200 Geom::Piecewise<Geom::D2<Geom::SBasis> >
201 LPEPerpBisector::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
202 {
203 using namespace Geom;
205 Piecewise<D2<SBasis> > output;
207 A = pwd2_in.firstValue();
208 B = pwd2_in.lastValue();
209 M = (A + B)/2;
211 perp_dir = unit_vector((B - A).ccw());
213 C = M + perp_dir * length_left;
214 D = M - perp_dir * length_right;
216 output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
218 return output;
219 }
221 /* ######################## */
223 } //namespace LivePathEffect
224 } /* namespace Inkscape */
226 /*
227 Local Variables:
228 mode:c++
229 c-file-style:"stroustrup"
230 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
231 indent-tabs-mode:nil
232 fill-column:99
233 End:
234 */
235 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :