Code

Connector tool: make connectors avoid the convex hull of shapes.
[inkscape.git] / src / live_effects / lpe-lattice.cpp
1 #define INKSCAPE_LPE_LATTICE_CPP
2 /** \file
3  * LPE <lattice> implementation
4  
5  */
6 /*
7  * Authors:
8  *   Johan Engelen <j.b.c.engelen@utwente.nl>
9  *   Steren Giannini
10  *   NoĆ© Falzon
11  *   Victor Navez
12 *
13 * Copyright (C) 2007-2008 Authors 
14  *
15  * Released under GNU GPL, read the file 'COPYING' for more information
16  */
18 #include "live_effects/lpe-lattice.h"
20 #include "sp-shape.h"
21 #include "sp-item.h"
22 #include "sp-path.h"
23 #include "display/curve.h"
24 #include "svg/svg.h"
25 #include "nodepath.h"
27 #include <2geom/sbasis.h>
28 #include <2geom/sbasis-2d.h>
29 #include <2geom/sbasis-geometric.h>
30 #include <2geom/bezier-to-sbasis.h>
31 #include <2geom/sbasis-to-bezier.h>
32 #include <2geom/d2.h>
33 #include <2geom/piecewise.h>
34 #include <2geom/transforms.h>
36 #include "desktop.h" // TODO: should be factored out (see below)
38 using namespace Geom;
40 namespace Inkscape {
41 namespace LivePathEffect {
43 LPELattice::LPELattice(LivePathEffectObject *lpeobject) :
44     Effect(lpeobject),
45     
46     // initialise your parameters here:
47     grid_point0(_("Control handle 0"), _("Control handle 0"), "gridpoint0", &wr, this),
48     grid_point1(_("Control handle 1"), _("Control handle 1"), "gridpoint1", &wr, this),
49     grid_point2(_("Control handle 2"), _("Control handle 2"), "gridpoint2", &wr, this),
50     grid_point3(_("Control handle 3"), _("Control handle 3"), "gridpoint3", &wr, this),
51     grid_point4(_("Control handle 4"), _("Control handle 4"), "gridpoint4", &wr, this),
52     grid_point5(_("Control handle 5"), _("Control handle 5"), "gridpoint5", &wr, this),
53     grid_point6(_("Control handle 6"), _("Control handle 6"), "gridpoint6", &wr, this),
54     grid_point7(_("Control handle 7"), _("Control handle 7"), "gridpoint7", &wr, this),
55     grid_point8(_("Control handle 8"), _("Control handle 8"), "gridpoint8", &wr, this),
56     grid_point9(_("Control handle 9"), _("Control handle 9"), "gridpoint9", &wr, this),
57     grid_point10(_("Control handle 10"), _("Control handle 10"), "gridpoint10", &wr, this),
58     grid_point11(_("Control handle 11"), _("Control handle 11"), "gridpoint11", &wr, this),
59     grid_point12(_("Control handle 12"), _("Control handle 12"), "gridpoint12", &wr, this),
60     grid_point13(_("Control handle 13"), _("Control handle 13"), "gridpoint13", &wr, this),
61     grid_point14(_("Control handle 14"), _("Control handle 14"), "gridpoint14", &wr, this),
62     grid_point15(_("Control handle 15"), _("Control handle 15"), "gridpoint15", &wr, this)
63     
64 {
65     // register all your parameters here, so Inkscape knows which parameters this effect has:
66     registerParameter( dynamic_cast<Parameter *>(&grid_point0) );
67     registerParameter( dynamic_cast<Parameter *>(&grid_point1) );
68     registerParameter( dynamic_cast<Parameter *>(&grid_point2) );
69     registerParameter( dynamic_cast<Parameter *>(&grid_point3) );
70     registerParameter( dynamic_cast<Parameter *>(&grid_point4) );
71     registerParameter( dynamic_cast<Parameter *>(&grid_point5) );
72     registerParameter( dynamic_cast<Parameter *>(&grid_point6) );
73     registerParameter( dynamic_cast<Parameter *>(&grid_point7) );
74     registerParameter( dynamic_cast<Parameter *>(&grid_point8) );
75     registerParameter( dynamic_cast<Parameter *>(&grid_point9) );
76     registerParameter( dynamic_cast<Parameter *>(&grid_point10) );
77     registerParameter( dynamic_cast<Parameter *>(&grid_point11) );
78     registerParameter( dynamic_cast<Parameter *>(&grid_point12) );
79     registerParameter( dynamic_cast<Parameter *>(&grid_point13) );
80     registerParameter( dynamic_cast<Parameter *>(&grid_point14) );
81     registerParameter( dynamic_cast<Parameter *>(&grid_point15) );
83     
84 }
86 LPELattice::~LPELattice()
87 {
89 }
92 Geom::Piecewise<Geom::D2<Geom::SBasis> >
93 LPELattice::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
94 {
95     D2<SBasis2d> sb2;
96     
97     //Initialisation of the sb2
98     for(unsigned dim = 0; dim < 2; dim++) {
99         sb2[dim].us = 2;
100         sb2[dim].vs = 2;
101         const int depth = sb2[dim].us*sb2[dim].vs;
102         sb2[dim].resize(depth, Linear2d(0));
103     }
105     //Grouping the point params in a convenient vector
106     std::vector<Geom::Point *> handles(16);
107     
108     handles[0] = &grid_point0;
109     handles[1] = &grid_point1;
110     handles[2] = &grid_point2;
111     handles[3] = &grid_point3;
112     handles[4] = &grid_point4;
113     handles[5] = &grid_point5;
114     handles[6] = &grid_point6;
115     handles[7] = &grid_point7;
116     handles[8] = &grid_point8;
117     handles[9] = &grid_point9;
118     handles[10] = &grid_point10;
119     handles[11] = &grid_point11;
120     handles[12] = &grid_point12;
121     handles[13] = &grid_point13;
122     handles[14] = &grid_point14;
123     handles[15] = &grid_point15;
125     Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
126       
127     double width = boundingbox_X.extent();
128     double height = boundingbox_Y.extent();
130     //numbering is based on 4 rectangles.
131     for(unsigned dim = 0; dim < 2; dim++) {
132         Geom::Point dir(0,0);
133         dir[dim] = 1;
134         for(unsigned vi = 0; vi < sb2[dim].vs; vi++) {
135             for(unsigned ui = 0; ui < sb2[dim].us; ui++) {
136                 for(unsigned iv = 0; iv < 2; iv++) {
137                     for(unsigned iu = 0; iu < 2; iu++) {
138                         unsigned corner = iu + 2*iv;
139                         unsigned i = ui + vi*sb2[dim].us;
140                         
141                         //This is the offset from the Upperleft point
142                         Geom::Point base(   (ui + iu*(3-2*ui))*width/3.,
143                                             (vi + iv*(3-2*vi))*height/3.);
144                        
145                         //Special action for corners
146                         if(vi == 0 && ui == 0) {
147                             base = Geom::Point(0,0);
148                         }
149                         
150                         // i = Upperleft corner of the considerated rectangle
151                         // corner = actual corner of the rectangle
152                         // origin = Upperleft point
153                         double dl = dot((*handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
154                         sb2[dim][i][corner] = dl/( dim ? height : width )*pow(4.0,ui+vi);
155                     }
156                 }
157             }
158         }
159     }
160    
161     Piecewise<D2<SBasis> >  output;
162     output.push_cut(0.);
163     for(unsigned i = 0; i < pwd2_in.size(); i++) {
164         D2<SBasis> B = pwd2_in[i];
165         B -= origin;   
166         B*= 1/width;
167         //Here comes the magic
168         D2<SBasis> tB = compose_each(sb2,B);
169         tB = tB * width + origin;
171         output.push(tB,i+1);
172     }
174     return output;
177 void
178 LPELattice::doBeforeEffect (SPLPEItem *lpeitem)
180     original_bbox(lpeitem);
183 void
184 LPELattice::resetDefaults(SPItem * item)
186     Effect::resetDefaults(item);
188     original_bbox(SP_LPE_ITEM(item), false);
189     
190     // place the 16 control points
191     grid_point0[Geom::X] = boundingbox_X.min();
192     grid_point0[Geom::Y] = boundingbox_Y.min();
193     
194     grid_point1[Geom::X] = boundingbox_X.max();
195     grid_point1[Geom::Y] = boundingbox_Y.min();
196     
197     grid_point2[Geom::X] = boundingbox_X.min();
198     grid_point2[Geom::Y] = boundingbox_Y.max();
199     
200     grid_point3[Geom::X] = boundingbox_X.max();
201     grid_point3[Geom::Y] = boundingbox_Y.max();
202     
203     grid_point4[Geom::X] = 1.0/3*boundingbox_X.max()+2.0/3*boundingbox_X.min();
204     grid_point4[Geom::Y] = boundingbox_Y.min();
205     
206     grid_point5[Geom::X] = 2.0/3*boundingbox_X.max()+1.0/3*boundingbox_X.min();
207     grid_point5[Geom::Y] = boundingbox_Y.min();
208     
209     grid_point6[Geom::X] = 1.0/3*boundingbox_X.max()+2.0/3*boundingbox_X.min();
210     grid_point6[Geom::Y] = boundingbox_Y.max();
211     
212     grid_point7[Geom::X] = 2.0/3*boundingbox_X.max()+1.0/3*boundingbox_X.min();
213     grid_point7[Geom::Y] = boundingbox_Y.max();
214     
215     grid_point8[Geom::X] = boundingbox_X.min();
216     grid_point8[Geom::Y] = 1.0/3*boundingbox_Y.max()+2.0/3*boundingbox_Y.min();     
218     grid_point9[Geom::X] = boundingbox_X.max();
219     grid_point9[Geom::Y] = 1.0/3*boundingbox_Y.max()+2.0/3*boundingbox_Y.min();
220         
221     grid_point10[Geom::X] = boundingbox_X.min();
222     grid_point10[Geom::Y] = 2.0/3*boundingbox_Y.max()+1.0/3*boundingbox_Y.min();  
223     
224     grid_point11[Geom::X] = boundingbox_X.max();
225     grid_point11[Geom::Y] = 2.0/3*boundingbox_Y.max()+1.0/3*boundingbox_Y.min();  
226     
227     grid_point12[Geom::X] = 1.0/3*boundingbox_X.max()+2.0/3*boundingbox_X.min();
228     grid_point12[Geom::Y] = 1.0/3*boundingbox_Y.max()+2.0/3*boundingbox_Y.min();
229     
230     grid_point13[Geom::X] = 2.0/3*boundingbox_X.max()+1.0/3*boundingbox_X.min();
231     grid_point13[Geom::Y] = 1.0/3*boundingbox_Y.max()+2.0/3*boundingbox_Y.min();
232     
233     grid_point14[Geom::X] = 1.0/3*boundingbox_X.max()+2.0/3*boundingbox_X.min();
234     grid_point14[Geom::Y] = 2.0/3*boundingbox_Y.max()+1.0/3*boundingbox_Y.min();
235     
236     grid_point15[Geom::X] = 2.0/3*boundingbox_X.max()+1.0/3*boundingbox_X.min();
237     grid_point15[Geom::Y] = 2.0/3*boundingbox_Y.max()+1.0/3*boundingbox_Y.min();
240 /**
241 void
242 LPELattice::addHelperPathsImpl(SPLPEItem *lpeitem, SPDesktop *desktop)
244     SPCurve *c = new SPCurve ();
245     c->moveto(grid_point0);
246     c->lineto(grid_point4);
247     c->lineto(grid_point5);
248     c->lineto(grid_point1);
250     c->moveto(grid_point8);
251     c->lineto(grid_point12);
252     c->lineto(grid_point13);
253     c->lineto(grid_point9);
255     c->moveto(grid_point10);
256     c->lineto(grid_point14);
257     c->lineto(grid_point15);
258     c->lineto(grid_point11);
260     c->moveto(grid_point2);
261     c->lineto(grid_point6);
262     c->lineto(grid_point7);
263     c->lineto(grid_point3);
266     c->moveto(grid_point0);
267     c->lineto(grid_point8);
268     c->lineto(grid_point10);
269     c->lineto(grid_point2);
271     c->moveto(grid_point4);
272     c->lineto(grid_point12);
273     c->lineto(grid_point14);
274     c->lineto(grid_point6);
276     c->moveto(grid_point5);
277     c->lineto(grid_point13);
278     c->lineto(grid_point15);
279     c->lineto(grid_point7);
281     c->moveto(grid_point1);
282     c->lineto(grid_point9);
283     c->lineto(grid_point11);
284     c->lineto(grid_point3);
286     // TODO: factor this out (and remove the #include of desktop.h above)
287     SPCanvasItem *canvasitem = sp_nodepath_generate_helperpath(desktop, c, SP_ITEM(lpeitem), 0x009000ff);
288     Inkscape::Display::TemporaryItem* tmpitem = desktop->add_temporary_canvasitem (canvasitem, 0);
289     lpeitem->lpe_helperpaths.push_back(tmpitem);
291     c->unref();
293 **/
295 /* ######################## */
297 } //namespace LivePathEffect
298 } /* namespace Inkscape */
300 /*
301   Local Variables:
302   mode:c++
303   c-file-style:"stroustrup"
304   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
305   indent-tabs-mode:nil
306   fill-column:99
307   End:
308 */
309 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :