diff options
| -rw-r--r-- | src/live_effects/lpe-copy_rotate.cpp | 142 | ||||
| -rw-r--r-- | src/live_effects/lpe-copy_rotate.h | 8 |
2 files changed, 110 insertions, 40 deletions
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index 51787e292..3428ba8b3 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -17,11 +17,15 @@ #include "live_effects/lpe-copy_rotate.h" #include "sp-shape.h" #include "display/curve.h" - +#include <2geom/path.h> +#include <2geom/path-intersection.h> +#include <2geom/sbasis-to-bezier.h> #include <2geom/path.h> #include <2geom/transforms.h> #include <2geom/d2-sbasis.h> #include <2geom/angle.h> +#include <2geom/line.h> +#include <cmath> #include "knot-holder-entity.h" #include "knotholder.h" @@ -38,27 +42,40 @@ public: virtual Geom::Point knot_get() const; }; +class KnotHolderEntityRotationAngle : public LPEKnotHolderEntity { +public: + KnotHolderEntityRotationAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; +}; + +class KnotHolderEntityOrigin : public LPEKnotHolderEntity { +public: + KnotHolderEntityOrigin(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; +}; } // namespace CR LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : Effect(lpeobject), + origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this, "Adjust the origin of the rotation"), starting_angle(_("Starting:"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0), rotation_angle(_("Rotation angle:"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 30.0), num_copies(_("Number of copies:"), _("Number of copies of the original path"), "num_copies", &wr, this, 5), copiesTo360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copiesTo360", &wr, this, true), - origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this, "Adjust the origin of the rotation"), - dist_angle_handle(100) + dist_angle_handle(100.0) { show_orig_path = true; _provides_knotholder_entities = true; // register all your parameters here, so Inkscape knows which parameters this effect has: - registerParameter( dynamic_cast<Parameter *>(&copiesTo360) ); - registerParameter( dynamic_cast<Parameter *>(&starting_angle) ); - registerParameter( dynamic_cast<Parameter *>(&rotation_angle) ); - registerParameter( dynamic_cast<Parameter *>(&num_copies) ); - registerParameter( dynamic_cast<Parameter *>(&origin) ); + registerParameter(&copiesTo360); + registerParameter(&starting_angle); + registerParameter(&rotation_angle); + registerParameter(&num_copies); + registerParameter(&origin); num_copies.param_make_integer(true); num_copies.param_set_range(0, 1000); @@ -73,47 +90,57 @@ void LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); - Point A(boundingbox_X.min(), boundingbox_Y.middle()); - Point B(boundingbox_X.max(), boundingbox_Y.middle()); - Point C(boundingbox_X.middle(), boundingbox_Y.middle()); + A = Point(boundingbox_X.min(), boundingbox_Y.middle()); + B = Point(boundingbox_X.middle(), boundingbox_Y.middle()); origin.param_setValue(A); - - dir = unit_vector(B - A); dist_angle_handle = L2(B - A); + dir = unit_vector(B - A); } -Geom::Piecewise<Geom::D2<Geom::SBasis> > -LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) + +void +LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem) { using namespace Geom; - + original_bbox(lpeitem); + if(copiesTo360 ){ + rotation_angle.param_set_value(360.0/(double)num_copies); + } + A = Point(boundingbox_X.min(), boundingbox_Y.middle()); + B = Point(boundingbox_X.middle(), boundingbox_Y.middle()); + dir = unit_vector(B - A); // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) start_pos = origin + dir * Rotate(-deg_to_rad(starting_angle)) * dist_angle_handle; - double rotation_angle_end = rotation_angle; - if(copiesTo360){ - rotation_angle_end = 360.0/(double)num_copies; + rot_pos = origin + dir * Rotate(-deg_to_rad(rotation_angle+starting_angle)) * dist_angle_handle; + if(copiesTo360 ){ + rot_pos = origin; } - rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle_end)) * dist_angle_handle; + SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); + item->apply_to_clippath(item); + item->apply_to_mask(item); - A = pwd2_in.firstValue(); - B = pwd2_in.lastValue(); - dir = unit_vector(B - A); +} - Piecewise<D2<SBasis> > output; +Geom::Piecewise<Geom::D2<Geom::SBasis> > +LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) +{ + using namespace Geom; + + if(num_copies == 1){ + return pwd2_in; + } + + Piecewise<D2<SBasis> > output; Affine pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle)); for (int i = 0; i < num_copies; ++i) { - // I first suspected the minus sign to be a bug in 2geom but it is - // likely due to SVG's choice of coordinate system orientation (max) - Rotate rot(-deg_to_rad(rotation_angle_end * i)); + Rotate rot(-deg_to_rad(rotation_angle * i)); Affine t = pre * rot * Translate(origin); output.concat(pwd2_in * t); } - return output; } @@ -121,12 +148,13 @@ void LPECopyRotate::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) { using namespace Geom; - - Path path(start_pos); - path.appendNew<LineSegment>((Geom::Point) origin); - path.appendNew<LineSegment>(rot_pos); - PathVector pathv; - pathv.push_back(path); + hp_vec.clear(); + Geom::Path hp; + hp.start(start_pos); + hp.appendNew<Geom::LineSegment>((Geom::Point)origin); + hp.appendNew<Geom::LineSegment>(origin + dir * Rotate(-deg_to_rad(rotation_angle+starting_angle)) * dist_angle_handle); + Geom::PathVector pathv; + pathv.push_back(hp); hp_vec.push_back(pathv); } @@ -135,9 +163,22 @@ void LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *des { KnotHolderEntity *e = new CR::KnotHolderEntityStartingAngle(this); e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the starting angle") ); + _("Adjust the starting angle")); knotholder->add(e); } + { + KnotHolderEntity *e = new CR::KnotHolderEntityRotationAngle(this); + e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("Adjust the rotation angle")); + knotholder->add(e); + } +} + +void +LPECopyRotate::resetDefaults(SPItem const* item) +{ + Effect::resetDefaults(item); + original_bbox(SP_LPE_ITEM(item)); }; namespace CR { @@ -164,6 +205,26 @@ KnotHolderEntityStartingAngle::knot_set(Geom::Point const &p, Geom::Point const sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); } +void +KnotHolderEntityRotationAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +{ + LPECopyRotate* lpe = dynamic_cast<LPECopyRotate *>(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + // I first suspected the minus sign to be a bug in 2geom but it is + // likely due to SVG's choice of coordinate system orientation (max) + lpe->rotation_angle.param_set_value(rad_to_deg(-angle_between(lpe->dir, s - lpe->origin)) - lpe->starting_angle); + if (state & GDK_SHIFT_MASK) { + lpe->dist_angle_handle = L2(lpe->B - lpe->A); + } else { + lpe->dist_angle_handle = L2(p - lpe->origin); + } + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); +} + Geom::Point KnotHolderEntityStartingAngle::knot_get() const { @@ -171,9 +232,14 @@ KnotHolderEntityStartingAngle::knot_get() const return lpe->start_pos; } -} // namespace CR - +Geom::Point +KnotHolderEntityRotationAngle::knot_get() const +{ + LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect); + return lpe->rot_pos; +} +} // namespace CR /* ######################## */ diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h index 123c92cdd..9392026a7 100644 --- a/src/live_effects/lpe-copy_rotate.h +++ b/src/live_effects/lpe-copy_rotate.h @@ -36,21 +36,25 @@ public: virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in); + virtual void doBeforeEffect (SPLPEItem const* lpeitem); + + virtual void resetDefaults(SPItem const* item); + /* the knotholder entity classes must be declared friends */ friend class CR::KnotHolderEntityStartingAngle; + friend class CR::KnotHolderEntityRotationAngle; void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); private: + PointParam origin; ScalarParam starting_angle; ScalarParam rotation_angle; ScalarParam num_copies; BoolParam copiesTo360; - PointParam origin; - Geom::Point A; Geom::Point B; Geom::Point dir; |
