Code

Connector tool: make connectors avoid the convex hull of shapes.
[inkscape.git] / src / live_effects / lpe-tangent_to_curve.cpp
index 65948837fc3fb745f3738c5e0af9689e6cd6208f..b43fd8b36788a43210b65e13692a0d0392657628 100644 (file)
@@ -19,7 +19,6 @@
 //        There must be a more convenient way to achieve this.
 #include "sp-path.h"
 #include "display/curve.h"
-#include "libnr/n-art-bpath-2geom.h"
 
 #include <2geom/path.h>
 #include <2geom/transforms.h>
 namespace Inkscape {
 namespace LivePathEffect {
 
-/* FIXME: We should arguably make these member functions of LPETangentToCurve.
-          Is there an easy way to register member functions with knotholder?
- */
-NR::Point attach_pt_get(SPItem *item) {
-    Inkscape::LivePathEffect::LPETangentToCurve *lpe =
-        (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
-    return lpe->ptA;
-}
-
-void attach_pt_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {
-    Inkscape::LivePathEffect::LPETangentToCurve *lpe =
-        (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
-    using namespace Geom;
-
-    // FIXME: There must be a better way of converting the path's SPCurve* to pwd2.
-    SPCurve *curve = sp_path_get_curve_for_edit (SP_PATH(item));
-    const NArtBpath *bpath = curve->get_bpath();
-    Piecewise<D2<SBasis> > pwd2;
-    std::vector<Geom::Path> pathv = BPath_to_2GeomPath(bpath);
-    for (unsigned int i=0; i < pathv.size(); i++) {
-        pwd2.concat(pathv[i].toPwSb());
-    }
-
-    double t0 = nearest_point(p.to_2geom(), pwd2);
-    lpe->t_attach.param_set_value(t0);
-
-    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
-
-NR::Point left_end_get(SPItem *item) {
-    Inkscape::LivePathEffect::LPETangentToCurve *lpe =
-        (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
-    return lpe->C;
-}
+namespace TtC {
 
-NR::Point right_end_get(SPItem *item) {
-    Inkscape::LivePathEffect::LPETangentToCurve *lpe =
-        (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
-    return lpe->D;
-}
-
-void left_end_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {
-    Inkscape::LivePathEffect::LPETangentToCurve *lpe =
-        (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
-    double lambda = Geom::nearest_point(p.to_2geom(), lpe->ptA, lpe->derivA);
-    lpe->length_left.param_set_value(-lambda);
-
-    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
+class KnotHolderEntityAttachPt : public LPEKnotHolderEntity
+{
+public:
+    virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+    virtual Geom::Point knot_get();
+};
 
-void right_end_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {
-    Inkscape::LivePathEffect::LPETangentToCurve *lpe =
-        (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
+class KnotHolderEntityLeftEnd : public LPEKnotHolderEntity
+{
+public:
+    virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+    virtual Geom::Point knot_get();
+};
 
-    double lambda = Geom::nearest_point(p.to_2geom(), lpe->ptA, lpe->derivA);
-    lpe->length_right.param_set_value(lambda);
+class KnotHolderEntityRightEnd : public LPEKnotHolderEntity
+{
+public:
+    virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+    virtual Geom::Point knot_get();
+};
 
-    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
+} // namespace TtC
 
 LPETangentToCurve::LPETangentToCurve(LivePathEffectObject *lpeobject) :
     Effect(lpeobject),
+    angle(_("Angle"), _("Additional angle between tangent and curve"), "angle", &wr, this, 0.0),
     t_attach(_("Location along curve"), _("Location of the point of attachment along the curve (between 0.0 and number-of-segments)"), "t_attach", &wr, this, 0.5),
     length_left(_("Length left"), _("Specifies the left end of the tangent"), "length-left", &wr, this, 150),
-    length_right(_("Length right"), _("Specifies the right end of the tangent"), "length-right", &wr, this, 150),
-    angle(_("Angle"), _("Additional angle between tangent and curve"), "angle", &wr, this, 0.0)
+    length_right(_("Length right"), _("Specifies the right end of the tangent"), "length-right", &wr, this, 150)
 {
+    show_orig_path = true;
+
+    registerParameter( dynamic_cast<Parameter *>(&angle) );
     registerParameter( dynamic_cast<Parameter *>(&t_attach) );
     registerParameter( dynamic_cast<Parameter *>(&length_left) );
     registerParameter( dynamic_cast<Parameter *>(&length_right) );
-    registerParameter( dynamic_cast<Parameter *>(&angle) );
-    registerKnotHolderHandle(attach_pt_set, attach_pt_get);
-    registerKnotHolderHandle(left_end_set, left_end_get);
-    registerKnotHolderHandle(right_end_set, right_end_get);
+
+    registerKnotHolderHandle(new TtC::KnotHolderEntityAttachPt(), _("Adjust the point of attachment of the tangent"));
+    registerKnotHolderHandle(new TtC::KnotHolderEntityLeftEnd(), _("Adjust the \"left\" end of the tangent"));
+    registerKnotHolderHandle(new TtC::KnotHolderEntityRightEnd(), _("Adjust the \"right\" end of the tangent"));
 }
 
 LPETangentToCurve::~LPETangentToCurve()
@@ -133,6 +95,93 @@ LPETangentToCurve::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const
     return output;
 }
 
+namespace TtC {
+
+// TODO: make this more generic
+static LPETangentToCurve *
+get_effect(SPItem *item)
+{
+    Effect *effect = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item));
+    if (effect->effectType() != TANGENT_TO_CURVE) {
+        g_print ("Warning: Effect is not of type LPETangentToCurve!\n");
+        return NULL;
+    }
+    return static_cast<LPETangentToCurve *>(effect);
+}
+
+void
+KnotHolderEntityAttachPt::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/)
+{
+    using namespace Geom;
+
+    LPETangentToCurve* lpe = get_effect(item);
+
+    Geom::Point const s = snap_knot_position(p);
+
+    // FIXME: There must be a better way of converting the path's SPCurve* to pwd2.
+    SPCurve *curve = sp_path_get_curve_for_edit (SP_PATH(item));
+    Geom::PathVector pathv = curve->get_pathvector();
+    Piecewise<D2<SBasis> > pwd2;
+    for (unsigned int i=0; i < pathv.size(); i++) {
+        pwd2.concat(pathv[i].toPwSb());
+    }
+
+    double t0 = nearest_point(s, pwd2);
+    lpe->t_attach.param_set_value(t0);
+
+    // 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);
+}
+
+void
+KnotHolderEntityLeftEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/)
+{
+    LPETangentToCurve *lpe = get_effect(item);
+
+    Geom::Point const s = snap_knot_position(p);
+
+    double lambda = Geom::nearest_point(s, lpe->ptA, lpe->derivA);
+    lpe->length_left.param_set_value(-lambda);
+
+    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
+}
+
+void
+KnotHolderEntityRightEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/)
+{
+    LPETangentToCurve *lpe = get_effect(item);
+    
+    Geom::Point const s = snap_knot_position(p);
+
+    double lambda = Geom::nearest_point(s, lpe->ptA, lpe->derivA);
+    lpe->length_right.param_set_value(lambda);
+
+    sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
+}
+
+Geom::Point
+KnotHolderEntityAttachPt::knot_get()
+{
+    LPETangentToCurve* lpe = get_effect(item);
+    return lpe->ptA;
+}
+
+Geom::Point
+KnotHolderEntityLeftEnd::knot_get()
+{
+    LPETangentToCurve *lpe = get_effect(item);
+    return lpe->C;
+}
+
+Geom::Point
+KnotHolderEntityRightEnd::knot_get()
+{
+    LPETangentToCurve *lpe = get_effect(item);
+    return lpe->D;
+}
+
+} // namespace TtC
+
 } //namespace LivePathEffect
 } /* namespace Inkscape */