index 49569d4b52d854ceb5a00566478f25e23b3e08a7..2d6bbeb220195989120af857c2a96b6f610beb7d 100644 (file)
#include "sp-item.h"
#include "sp-path.h"
#include "sp-item-group.h"
-#include "display/curve.h"
-#include <libnr/n-art-bpath.h>
-#include <libnr/nr-matrix-fns.h>
-#include "libnr/n-art-bpath-2geom.h"
#include "svg/svg.h"
#include "ui/widget/scalar.h"
The first step is to re-parametrize B by its arc length: this is the parametrization in which a point p on B is located by its distance s from start. One obtains a new map s --> U(s) = (a'(s),b'(s)), that still describes the same path B, but where the distance along B from start to
U(s) is s itself.
-We also need a unit normal to the path. This can be obtained by computing a unit tangent vector, and rotate it by 90°. Call this normal vector N(s).
+We also need a unit normal to the path. This can be obtained by computing a unit tangent vector, and rotate it by 90�. Call this normal vector N(s).
The basic deformation associated to B is then given by:
LPEBendPath::LPEBendPath(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
- bend_path(_("Bend path"), _("Path along which to bend the original path"), "bendpath", &wr, this, "M0,0 L1,0"),
- prop_scale(_("Width"), _("Width of the path"), "prop_scale", &wr, this, 1),
- scale_y_rel(_("Width in units of length"), _("Scale the width of the path in units of its length"), "scale_y_rel", &wr, this, false),
- vertical_pattern(_("Original path is vertical"), _("Rotates the original 90 degrees, before bending it along the bend path"), "vertical", &wr, this, false)
+ bend_path(_("Bend path:"), _("Path along which to bend the original path"), "bendpath", &wr, this, "M0,0 L1,0"),
+ prop_scale(_("_Width:"), _("Width of the path"), "prop_scale", &wr, this, 1),
+ scale_y_rel(_("W_idth in units of length"), _("Scale the width of the path in units of its length"), "scale_y_rel", &wr, this, false),
+ vertical_pattern(_("_Original path is vertical"), _("Rotates the original 90 degrees, before bending it along the bend path"), "vertical", &wr, this, false)
{
registerParameter( dynamic_cast<Parameter *>(&bend_path) );
registerParameter( dynamic_cast<Parameter *>(&prop_scale) );
prop_scale.param_set_increments(0.01, 0.10);
concatenate_before_pwd2 = true;
-
- groupSpecialBehavior = false;
}
LPEBendPath::~LPEBendPath()
void
LPEBendPath::doBeforeEffect (SPLPEItem *lpeitem)
{
- if(SP_IS_GROUP(lpeitem))
- {
- groupSpecialBehavior = true;
-
- using namespace Geom;
- Piecewise<D2<SBasis> > pwd2;
- std::vector<Geom::Path> temppath;
-
- recursive_original_bbox(SP_GROUP(lpeitem), pwd2, temppath);
-
- for (unsigned int i=0; i < temppath.size(); i++) {
- pwd2.concat( temppath[i].toPwSb() );
- }
-
- D2<Piecewise<SBasis> > d2pw = make_cuts_independant(pwd2);
- boundingbox_X = bounds_exact(d2pw[0]);
- boundingbox_Y = bounds_exact(d2pw[1]);
- }
-
+ // get the item bounding box
+ original_bbox(lpeitem);
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
@@ -110,25 +87,27 @@ LPEBendPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */
- Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(Piecewise<D2<SBasis> >(bend_path.get_pwd2()),2,.1);
- uskeleton = remove_short_cuts(uskeleton,.01);
- Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
- n = force_continuity(remove_short_cuts(n,.1));
+ if (bend_path.changed) {
+ uskeleton = arc_length_parametrization(Piecewise<D2<SBasis> >(bend_path.get_pwd2()),2,.1);
+ uskeleton = remove_short_cuts(uskeleton,.01);
+ n = rot90(derivative(uskeleton));
+ n = force_continuity(remove_short_cuts(n,.1));
+
+ bend_path.changed = false;
+ }
- D2<Piecewise<SBasis> > patternd2 = make_cuts_independant(pwd2_in);
+ D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pwd2_in);
Piecewise<SBasis> x = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[1]) : Piecewise<SBasis>(patternd2[0]);
Piecewise<SBasis> y = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[0]) : Piecewise<SBasis>(patternd2[1]);
-//We use the group bounding box size or the path bbox size to translate well x and y
- if(groupSpecialBehavior == false)
- {
- boundingbox_X = bounds_exact(x);
- boundingbox_Y = bounds_exact(y);
- }
- x-= boundingbox_X.min();
- y-= boundingbox_Y.middle();
+ Interval bboxHorizontal = vertical_pattern.get_value() ? boundingbox_Y : boundingbox_X;
+ Interval bboxVertical = vertical_pattern.get_value() ? boundingbox_X : boundingbox_Y;
+
+ //We use the group bounding box size or the path bbox size to translate well x and y
+ x-= bboxHorizontal.min();
+ y-= bboxVertical.middle();
- double scaling = uskeleton.cuts.back()/boundingbox_X.extent();
+ double scaling = uskeleton.cuts.back()/bboxHorizontal.extent();
if (scaling != 1.0) {
x*=scaling;
@@ -148,50 +127,21 @@ LPEBendPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
void
LPEBendPath::resetDefaults(SPItem * item)
{
- if (SP_IS_PATH(item) || SP_IS_GROUP(item))
- {
- // set the bend path to run horizontally in the middle of the bounding box of the original path
- using namespace Geom;
- Piecewise<D2<SBasis> > pwd2;
- std::vector<Geom::Path> temppath;
-
- if (SP_IS_PATH(item))
- {
- //TODO : this won't work well with LPE stacking
- temppath = SVGD_to_2GeomPath( SP_OBJECT_REPR(item)->attribute("inkscape:original-d"));
- }
- else if (SP_IS_GROUP(item))
- {
- recursive_original_bbox(SP_GROUP(item), pwd2, temppath);
- }
-
- for (unsigned int i=0; i < temppath.size(); i++) {
- pwd2.concat( temppath[i].toPwSb() );
- }
-
- D2<Piecewise<SBasis> > d2pw = make_cuts_independant(pwd2);
- boundingbox_X = bounds_exact(d2pw[0]);
- boundingbox_Y = bounds_exact(d2pw[1]);
-
- Point start(boundingbox_X.min(), (boundingbox_Y.max()+boundingbox_Y.min())/2);
- Point end(boundingbox_X.max(), (boundingbox_Y.max()+boundingbox_Y.min())/2);
-
- if ( Geom::are_near(start,end) ) {
- end += Point(1.,0.);
- }
-
- Geom::Path path;
- path.start( start );
- path.appendNew<Geom::LineSegment>( end );
- bend_path.param_set_and_write_new_value( path.toPwSb() );
- }
-}
+ Effect::resetDefaults(item);
-void
-LPEBendPath::transform_multiply(Geom::Matrix const& postmul, bool set)
-{
- // TODO: implement correct transformation instead of this default behavior
- Effect::transform_multiply(postmul, set);
+ original_bbox(SP_LPE_ITEM(item));
+
+ Geom::Point start(boundingbox_X.min(), (boundingbox_Y.max()+boundingbox_Y.min())/2);
+ Geom::Point end(boundingbox_X.max(), (boundingbox_Y.max()+boundingbox_Y.min())/2);
+
+ if ( Geom::are_near(start,end) ) {
+ end += Geom::Point(1.,0.);
+ }
+
+ Geom::Path path;
+ path.start( start );
+ path.appendNew<Geom::LineSegment>( end );
+ bend_path.set_new_value( path.toPwSb(), true );
}