5be5970c1593b15f85144c580939fba4bd967fe5
1 #define INKSCAPE_LPE_PERSPECTIVE_PATH_CPP
2 /** \file
3 * LPE <perspective_path> implementation, used as an example for a base starting class
4 * when implementing new LivePathEffects.
5 *
6 * In vi, three global search-and-replaces will let you rename everything
7 * in this and the .h file:
8 *
9 * :%s/PERSPECTIVE_PATH/YOURNAME/g
10 * :%s/PerspectivePath/Yourname/g
11 * :%s/perspective_path/yourname/g
12 */
13 /*
14 * Authors:
15 * Johan Engelen
16 * Maximilian Albert
17 *
18 * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
19 * Copyright (C) Maximilian Albert 2008 <maximilian.albert@gmail.com>
20 *
21 * Released under GNU GPL, read the file 'COPYING' for more information
22 */
24 #include "persp3d.h"
25 //#include "transf_mat_3x4.h"
26 #include "document.h"
28 #include "live_effects/lpe-perspective_path.h"
29 #include "display/curve.h"
30 #include <libnr/n-art-bpath.h>
31 #include "sp-item-group.h"
33 #include "inkscape.h"
35 // You might need to include other 2geom files. You can add them here:
36 #include <2geom/path.h>
38 namespace Inkscape {
39 namespace LivePathEffect {
41 LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) :
42 Effect(lpeobject),
43 // initialise your parameters here:
44 scalex(_("Scale x"), _("Scale factor in x direction"), "scalex", &wr, this, 1.0),
45 scaley(_("Scale y"), _("Scale factor in y direction"), "scaley", &wr, this, 1.0),
46 offsetx(_("Offset x"), _("Offset in x direction"), "offsetx", &wr, this, 0.0),
47 offsety(_("Offset y"), _("Offset in y direction"), "offsety", &wr, this, 0.0),
48 uses_plane_xy(_("Uses XY plane?"), _("If true, put the path on the left side of an imaginary box, otherwise on the right side"), "uses_plane_xy", &wr, this, true)
49 {
50 // register all your parameters here, so Inkscape knows which parameters this effect has:
51 registerParameter( dynamic_cast<Parameter *>(&scalex) );
52 registerParameter( dynamic_cast<Parameter *>(&scaley) );
53 registerParameter( dynamic_cast<Parameter *>(&offsetx) );
54 registerParameter( dynamic_cast<Parameter *>(&offsety) );
55 registerParameter( dynamic_cast<Parameter *>(&uses_plane_xy) );
57 concatenate_before_pwd2 = true; // don't split the path into its subpaths
59 Persp3D *persp = persp3d_document_first_persp(inkscape_active_document());
61 Proj::TransfMat3x4 pmat = persp->tmat;
63 pmat.copy_tmat(tmat);
65 groupSpecialBehavior = false;
66 }
68 LPEPerspectivePath::~LPEPerspectivePath()
69 {
71 }
73 void
74 LPEPerspectivePath::doBeforeEffect (SPLPEItem *lpeitem)
75 {
76 if(SP_IS_GROUP(lpeitem))
77 {
78 groupSpecialBehavior = true;
79 original_bbox(lpeitem);
80 }
81 }
84 Geom::Piecewise<Geom::D2<Geom::SBasis> >
85 LPEPerspectivePath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
86 {
87 using namespace Geom;
89 Piecewise<D2<SBasis> > path_a_pw = pwd2_in;
91 // FIXME: the minus sign is there because the SVG coordinate system goes down;
92 // remove this once we have unified coordinate systems
93 path_a_pw = path_a_pw + Geom::Point(offsetx, -offsety);
95 D2<Piecewise<SBasis> > B = make_cuts_independant(path_a_pw);
96 Piecewise<SBasis> preimage[4];
98 if(!groupSpecialBehavior)
99 {
100 boundingbox_X = bounds_fast(pwd2_in)[0];
101 boundingbox_Y = bounds_fast(pwd2_in)[1];
102 }
104 Geom::Point orig = Geom::Point(uses_plane_xy ? boundingbox_X.max() : boundingbox_X.min(),
105 boundingbox_Y.middle());
106 //Geom::Point orig = Geom::Point(bounds_X.min(), bounds_Y.middle());
107 //orig = Geom::Point(orig[X], sp_document_height(inkscape_active_document()) - orig[Y]);
109 //double offset = uses_plane_xy ? boundingbox_X.extent() : 0.0;
111 /**
112 g_print ("Orig: (%8.2f, %8.2f)\n", orig[X], orig[Y]);
114 g_print ("B[1] - orig[1]: %8.2f\n", (B[1] - orig[1])[0].valueAt(0));
115 g_print ("B[0] - orig[0]: %8.2f\n", (B[0] - orig[0])[0].valueAt(0));
116 **/
118 if (uses_plane_xy) {
119 preimage[0] = (-B[0] + orig[0]) * scalex / 200.0;
120 preimage[1] = ( B[1] - orig[1]) * scaley / 400.0;
121 preimage[2] = B[0] - B[0]; // hack!
122 } else {
123 preimage[0] = B[0] - B[0]; // hack!
124 preimage[1] = (B[1] - orig[1]) * scaley / 400.0;
125 preimage[2] = (B[0] - orig[0]) * scalex / 200.0;
126 }
128 /* set perspective origin to first point of path */
129 tmat[0][3] = orig[0];
130 tmat[1][3] = orig[1];
132 /**
133 g_print ("preimage[1]: %8.2f\n", preimage[1][0].valueAt(0));
134 g_print ("preimage[2]: %8.2f\n", preimage[2][0].valueAt(0));
135 **/
137 Piecewise<SBasis> res[3];
138 for (int j = 0; j < 3; ++j) {
139 res[j] =
140 preimage[0] * tmat[j][0]
141 + preimage[1] * tmat[j][1]
142 + preimage[2] * tmat[j][2]
143 + tmat[j][3];
144 }
145 D2<Piecewise<SBasis> > result(divide(res[0],res[2], 3),
146 divide(res[1],res[2], 3));
148 Piecewise<D2<SBasis> > output = sectionize(result);
150 return output;
151 }
153 /* ######################## */
155 } //namespace LivePathEffect
156 } /* namespace Inkscape */
158 /*
159 Local Variables:
160 mode:c++
161 c-file-style:"stroustrup"
162 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
163 indent-tabs-mode:nil
164 fill-column:99
165 End:
166 */
167 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :