Code

2fec63f3c37141f18acde4442275fca463113d03
[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"
22 #include <2geom/path.h>
24 namespace Inkscape {
25 namespace LivePathEffect {
27 /* FIXME: We should arguably make these member functions of LPEPerpBisector.
28           Is there an easy way to register member functions with knotholder?
29  */
30 NR::Point bisector_left_end_get(SPItem *item) {
31     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
32         (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
34     return NR::Point(lpe->C);
35 }
37 NR::Point bisector_right_end_get(SPItem *item) {
38     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
39         (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
41     return NR::Point(lpe->D);
42 }
44 void
45 bisector_end_set(SPItem *item, NR::Point const &p, bool left) {
46     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
47         (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
49     Geom::Point v(Geom::unit_vector(lpe->B - lpe->A));
50     Geom::Point diff(lpe->M - p.to_2geom());
52     double lambda = - v[Geom::Y] * diff[Geom::X] + v[Geom::X] * diff[Geom::Y];
53     if (left) {
54         lpe->C = lpe->M + lpe->perp_dir * lambda;
55         lpe->length_left.param_set_value(lambda);
56     } else {
57         lpe->D = lpe->M + lpe->perp_dir * lambda;
58         lpe->length_right.param_set_value(-lambda);
59     }
61     sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
62 }
64 void
65 bisector_left_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
66     bisector_end_set(item, p);
67 }
69 void
70 bisector_right_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
71     bisector_end_set(item, p, false);
72 }
74 NR::Point path_start_get(SPItem *item) {
75     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
76         (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
78     return NR::Point(lpe->A);
79 }
81 NR::Point path_end_get(SPItem *item) {
82     Inkscape::LivePathEffect::LPEPerpBisector *lpe =
83         (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
85     return NR::Point(lpe->B);
86 }
88 void
89 path_set_start_end(SPItem *item, NR::Point const &p, bool start) {
90     SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(item)); // TODO: Should we use sp_shape_get_curve()?
91     NR::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(item)));
93     Geom::Point A, B;
94     if (start) {
95         A = p.to_2geom();
96         B = (curve->last_point()).to_2geom();
97     } else {
98         A = (curve->first_point()).to_2geom();
99         B = (p.to_2geom());
100     }
102     SPCurve *c = new SPCurve();
103     c->moveto(A);
104     c->lineto(B);
105     sp_path_set_original_curve(SP_PATH(item), c, TRUE, true);
106     c->unref();
109 void path_start_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
110     path_set_start_end(item, p);
113 void path_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
114     path_set_start_end(item, p, false);
117 LPEPerpBisector::LPEPerpBisector(LivePathEffectObject *lpeobject) :
118     Effect(lpeobject),
119     length_left(_("Length left"), _("Specifies the left end of the bisector"), "length-left", &wr, this, 200),
120     length_right(_("Length right"), _("Specifies the right end of the bisector"), "length-right", &wr, this, 200),
121     A(0,0), B(0,0), M(0,0), C(0,0), D(0,0), perp_dir(0,0)
123     // register all your parameters here, so Inkscape knows which parameters this effect has:
124     registerParameter( dynamic_cast<Parameter *>(&length_left) );
125     registerParameter( dynamic_cast<Parameter *>(&length_right) );
127     registerKnotHolderHandle(path_start_set, path_start_get);
128     registerKnotHolderHandle(path_end_set, path_end_get);
129     registerKnotHolderHandle(bisector_left_end_set, bisector_left_end_get);
130     registerKnotHolderHandle(bisector_right_end_set, bisector_right_end_get);
133 LPEPerpBisector::~LPEPerpBisector()
137 void
138 LPEPerpBisector::doOnApply (SPLPEItem *lpeitem)
140     /* make the path a straight line */
141     SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()?
143     Geom::Point A((curve->first_point()).to_2geom());
144     Geom::Point B((curve->last_point()).to_2geom());
146     SPCurve *c = new SPCurve();
147     c->moveto(A);
148     c->lineto(B);
149     // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work?
150     SP_PATH(lpeitem)->original_curve = c->ref();
151     c->unref();
155 Geom::Piecewise<Geom::D2<Geom::SBasis> >
156 LPEPerpBisector::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
158     using namespace Geom;
160     Piecewise<D2<SBasis> > output;
162     A = pwd2_in.firstValue();
163     B = pwd2_in.lastValue();
164     M = (A + B)/2;
166     perp_dir = unit_vector((B - A).ccw());
168     C = M + perp_dir * length_left;
169     D = M - perp_dir * length_right;
171     output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
173     return output;
176 /* ######################## */
178 } //namespace LivePathEffect
179 } /* namespace Inkscape */
181 /*
182   Local Variables:
183   mode:c++
184   c-file-style:"stroustrup"
185   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
186   indent-tabs-mode:nil
187   fill-column:99
188   End:
189 */
190 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :