~inkscape.dev/inkscape/trunk

« back to all changes in this revision

Viewing changes to src/live_effects/lpe-copy_rotate.cpp

  • Committer: Jabiertxof
  • Date: 2015-01-20 23:05:32 UTC
  • Revision ID: jtx@jtx.marker.es-20150120230532-2036916vype8u2e0
Fix wrong knots in rotate curves LPE

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include "live_effects/lpe-copy_rotate.h"
18
18
#include "sp-shape.h"
19
19
#include "display/curve.h"
20
 
 
 
20
#include <2geom/path.h>
 
21
#include <2geom/path-intersection.h>
 
22
#include <2geom/sbasis-to-bezier.h>
21
23
#include <2geom/path.h>
22
24
#include <2geom/transforms.h>
23
25
#include <2geom/d2-sbasis.h>
24
26
#include <2geom/angle.h>
 
27
#include <2geom/line.h>
 
28
#include <cmath>
25
29
 
26
30
#include "knot-holder-entity.h"
27
31
#include "knotholder.h"
38
42
    virtual Geom::Point knot_get() const;
39
43
};
40
44
 
 
45
class KnotHolderEntityRotationAngle : public LPEKnotHolderEntity {
 
46
public:
 
47
    KnotHolderEntityRotationAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {};
 
48
    virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
 
49
    virtual Geom::Point knot_get() const;
 
50
};
 
51
 
 
52
class KnotHolderEntityOrigin : public LPEKnotHolderEntity {
 
53
public:
 
54
    KnotHolderEntityOrigin(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {};
 
55
    virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
 
56
    virtual Geom::Point knot_get() const;
 
57
};
41
58
 
42
59
} // namespace CR
43
60
 
44
61
LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
45
62
    Effect(lpeobject),
 
63
    origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this, "Adjust the origin of the rotation"),
46
64
    starting_angle(_("Starting:"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0),
47
65
    rotation_angle(_("Rotation angle:"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 30.0),
48
66
    num_copies(_("Number of copies:"), _("Number of copies of the original path"), "num_copies", &wr, this, 5),
49
67
    copiesTo360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copiesTo360", &wr, this, true),
50
 
    origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this, "Adjust the origin of the rotation"),
51
 
    dist_angle_handle(100)
 
68
    dist_angle_handle(100.0)
52
69
{
53
70
    show_orig_path = true;
54
71
    _provides_knotholder_entities = true;
55
72
 
56
73
    // register all your parameters here, so Inkscape knows which parameters this effect has:
57
 
    registerParameter( dynamic_cast<Parameter *>(&copiesTo360) );
58
 
    registerParameter( dynamic_cast<Parameter *>(&starting_angle) );
59
 
    registerParameter( dynamic_cast<Parameter *>(&rotation_angle) );
60
 
    registerParameter( dynamic_cast<Parameter *>(&num_copies) );
61
 
    registerParameter( dynamic_cast<Parameter *>(&origin) );
 
74
    registerParameter(&copiesTo360);
 
75
    registerParameter(&starting_angle);
 
76
    registerParameter(&rotation_angle);
 
77
    registerParameter(&num_copies);
 
78
    registerParameter(&origin);
62
79
 
63
80
    num_copies.param_make_integer(true);
64
81
    num_copies.param_set_range(0, 1000);
73
90
LPECopyRotate::doOnApply(SPLPEItem const* lpeitem)
74
91
{
75
92
    using namespace Geom;
76
 
 
77
93
    original_bbox(lpeitem);
78
94
 
79
 
    Point A(boundingbox_X.min(), boundingbox_Y.middle());
80
 
    Point B(boundingbox_X.max(), boundingbox_Y.middle());
81
 
    Point C(boundingbox_X.middle(), boundingbox_Y.middle());
 
95
    A = Point(boundingbox_X.min(), boundingbox_Y.middle());
 
96
    B = Point(boundingbox_X.middle(), boundingbox_Y.middle());
82
97
    origin.param_setValue(A);
83
 
 
84
 
    dir = unit_vector(B - A);
85
98
    dist_angle_handle = L2(B - A);
86
 
}
 
99
    dir = unit_vector(B - A);
 
100
}
 
101
 
 
102
 
 
103
void
 
104
LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem)
 
105
{
 
106
    using namespace Geom;
 
107
    original_bbox(lpeitem);
 
108
    if(copiesTo360 ){
 
109
        rotation_angle.param_set_value(360.0/(double)num_copies);
 
110
    } 
 
111
    A = Point(boundingbox_X.min(), boundingbox_Y.middle());
 
112
    B = Point(boundingbox_X.middle(), boundingbox_Y.middle());
 
113
    dir = unit_vector(B - A);
 
114
    // I first suspected the minus sign to be a bug in 2geom but it is
 
115
    // likely due to SVG's choice of coordinate system orientation (max)
 
116
    start_pos = origin + dir * Rotate(-deg_to_rad(starting_angle)) * dist_angle_handle;
 
117
    rot_pos = origin + dir * Rotate(-deg_to_rad(rotation_angle+starting_angle)) * dist_angle_handle;
 
118
    if(copiesTo360 ){
 
119
        rot_pos = origin;
 
120
    }
 
121
    SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
 
122
    item->apply_to_clippath(item);
 
123
    item->apply_to_mask(item);
 
124
 
 
125
}
 
126
 
87
127
 
88
128
Geom::Piecewise<Geom::D2<Geom::SBasis> >
89
129
LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
90
130
{
91
131
    using namespace Geom;
92
132
 
93
 
    // I first suspected the minus sign to be a bug in 2geom but it is
94
 
    // likely due to SVG's choice of coordinate system orientation (max)
95
 
    start_pos = origin + dir * Rotate(-deg_to_rad(starting_angle)) * dist_angle_handle;
96
 
    double rotation_angle_end = rotation_angle;
97
 
    if(copiesTo360){
98
 
        rotation_angle_end = 360.0/(double)num_copies;
 
133
    if(num_copies == 1){
 
134
        return pwd2_in;
99
135
    }
100
 
    rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle_end)) * dist_angle_handle;
101
 
 
102
 
    A = pwd2_in.firstValue();
103
 
    B = pwd2_in.lastValue();
104
 
    dir = unit_vector(B - A);
105
136
 
106
137
    Piecewise<D2<SBasis> > output;
107
 
 
108
138
    Affine pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle));
109
139
    for (int i = 0; i < num_copies; ++i) {
110
 
        // I first suspected the minus sign to be a bug in 2geom but it is
111
 
        // likely due to SVG's choice of coordinate system orientation (max)
112
 
        Rotate rot(-deg_to_rad(rotation_angle_end * i));
 
140
        Rotate rot(-deg_to_rad(rotation_angle * i));
113
141
        Affine t = pre * rot * Translate(origin);
114
142
        output.concat(pwd2_in * t);
115
143
    }
116
 
 
117
144
    return output;
118
145
}
119
146
 
121
148
LPECopyRotate::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
122
149
{
123
150
    using namespace Geom;
124
 
 
125
 
    Path path(start_pos);
126
 
    path.appendNew<LineSegment>((Geom::Point) origin);
127
 
    path.appendNew<LineSegment>(rot_pos);
128
 
    PathVector pathv;
129
 
    pathv.push_back(path);
 
151
    hp_vec.clear();
 
152
    Geom::Path hp;
 
153
    hp.start(start_pos);
 
154
    hp.appendNew<Geom::LineSegment>((Geom::Point)origin);
 
155
    hp.appendNew<Geom::LineSegment>(origin + dir * Rotate(-deg_to_rad(rotation_angle+starting_angle)) * dist_angle_handle);
 
156
    Geom::PathVector pathv;
 
157
    pathv.push_back(hp);
130
158
    hp_vec.push_back(pathv);
131
159
}
132
160
 
135
163
    {
136
164
        KnotHolderEntity *e = new CR::KnotHolderEntityStartingAngle(this);
137
165
        e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
138
 
                   _("Adjust the starting angle") );
139
 
        knotholder->add(e);
140
 
    }
 
166
                   _("Adjust the starting angle"));
 
167
        knotholder->add(e);
 
168
    }
 
169
    {
 
170
        KnotHolderEntity *e = new CR::KnotHolderEntityRotationAngle(this);
 
171
        e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
 
172
                   _("Adjust the rotation angle"));
 
173
        knotholder->add(e);
 
174
    }
 
175
}
 
176
 
 
177
void
 
178
LPECopyRotate::resetDefaults(SPItem const* item)
 
179
{
 
180
    Effect::resetDefaults(item);
 
181
    original_bbox(SP_LPE_ITEM(item));
141
182
};
142
183
 
143
184
namespace CR {
164
205
    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
165
206
}
166
207
 
 
208
void
 
209
KnotHolderEntityRotationAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
 
210
{
 
211
    LPECopyRotate* lpe = dynamic_cast<LPECopyRotate *>(_effect);
 
212
 
 
213
    Geom::Point const s = snap_knot_position(p, state);
 
214
 
 
215
    // I first suspected the minus sign to be a bug in 2geom but it is
 
216
    // likely due to SVG's choice of coordinate system orientation (max)
 
217
    lpe->rotation_angle.param_set_value(rad_to_deg(-angle_between(lpe->dir, s - lpe->origin)) - lpe->starting_angle);
 
218
    if (state & GDK_SHIFT_MASK) {
 
219
        lpe->dist_angle_handle = L2(lpe->B - lpe->A);
 
220
    } else {
 
221
        lpe->dist_angle_handle = L2(p - lpe->origin);
 
222
    }
 
223
 
 
224
    // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
 
225
    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
 
226
}
 
227
 
167
228
Geom::Point
168
229
KnotHolderEntityStartingAngle::knot_get() const
169
230
{
171
232
    return lpe->start_pos;
172
233
}
173
234
 
 
235
Geom::Point
 
236
KnotHolderEntityRotationAngle::knot_get() const
 
237
{
 
238
    LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect);
 
239
    return lpe->rot_pos;
 
240
}
 
241
 
174
242
} // namespace CR
175
243
 
176
 
 
177
 
 
178
244
/* ######################## */
179
245
 
180
246
} //namespace LivePathEffect