Code

fixing wrong includes
[inkscape.git] / src / live_effects / lpe-curvestitch.cpp
index a0a473fe7fdcbdcc6fecabf24685d34a5235d789..e72f1aac15026d7b57f63ca547c997f329b7849a 100644 (file)
-#define INKSCAPE_LPE_EXPRESSION_CPP\r
-/** \file\r
- * SVG <skeleton> implementation, used as an example for a base starting class\r
- * when implementing new LivePathEffects.\r
- *\r
- */\r
-/*\r
- * Authors:\r
- *   Johan Engelen\r
-*\r
-* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#include "live_effects/lpe-curvestitch.h"\r
-#include "display/curve.h"\r
-#include <libnr/n-art-bpath.h>\r
-\r
-#include <2geom/path.h>\r
-#include <2geom/piecewise.h>\r
-#include <2geom/sbasis.h>\r
-#include <2geom/sbasis-geometric.h>\r
-#include <2geom/bezier-to-sbasis.h>\r
-#include <2geom/sbasis-to-bezier.h>\r
-#include <2geom/d2.h>\r
-#include <2geom/matrix.h>\r
-\r
-\r
-#include "ui/widget/scalar.h"\r
-#include "libnr/nr-values.h"\r
-\r
-namespace Inkscape {\r
-namespace LivePathEffect {\r
-\r
-using namespace Geom;\r
-\r
-LPECurveStitch::LPECurveStitch(LivePathEffectObject *lpeobject) :\r
-    Effect(lpeobject),\r
-    strokepath(_("Stroke path"), _("The path that will be stroked, whatever, think of good text here."), "strokepath", &wr, this, "M0,0 L1,0"),\r
-    nrofpaths(_("Nr of paths"), _("The number of paths that will be generated."), "count", &wr, this, 5),\r
-    startpoint_variation(_("Startpoint variation"), _("..."), "startpoint_variation", &wr, this, 0),\r
-    endpoint_variation(_("Endpoint variation"), _("..."), "endpoint_variation", &wr, this, 0),\r
-    scale_y(_("Scale stroke y"), _("Scale the height of the stroke path with its length"), "scale_stroke_y", &wr, this, false)\r
-{\r
-    registerParameter( dynamic_cast<Parameter *>(&nrofpaths) );\r
-    registerParameter( dynamic_cast<Parameter *>(&startpoint_variation) );\r
-    registerParameter( dynamic_cast<Parameter *>(&endpoint_variation) );\r
-    registerParameter( dynamic_cast<Parameter *>(&strokepath) );\r
-    registerParameter( dynamic_cast<Parameter *>(&scale_y) );\r
-\r
-    nrofpaths.param_make_integer();\r
-    nrofpaths.param_set_range(2, NR_HUGE);\r
-\r
-//    startpoint_variation.param_set_range(-NR_HUGE, 1);\r
-//    endpoint_variation.param_set_range(-1, NR_HUGE);\r
-}\r
-\r
-LPECurveStitch::~LPECurveStitch()\r
-{\r
-\r
-}\r
-\r
-std::vector<Geom::Path>\r
-LPECurveStitch::doEffect (std::vector<Geom::Path> & path_in)\r
-{\r
-    if (path_in.size() >= 2) {\r
-        startpoint_variation.resetRandomizer();\r
-        endpoint_variation.resetRandomizer();\r
-\r
-        D2<Piecewise<SBasis> > stroke = make_cuts_independant(strokepath);\r
-        Interval bndsStroke = bounds_exact(stroke[0]);\r
-        gdouble scaling = bndsStroke.max() - bndsStroke.min();\r
-        Interval bndsStrokeY = bounds_exact(stroke[1]);\r
-        Point stroke_origin(bndsStroke.min(), (bndsStrokeY.max()+bndsStrokeY.min())/2);\r
-\r
-        std::vector<Geom::Path> path_out (nrofpaths);\r
-\r
-        // do this for all permutations if there are more than 2 paths? realllly cool!\r
-        Piecewise<D2<SBasis> > A = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[0].toPwSb()),2,.1);\r
-        Piecewise<D2<SBasis> > B = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[1].toPwSb()),2,.1);\r
-        Interval bndsA = A.domain();\r
-        Interval bndsB = B.domain();\r
-        gdouble incrementA = (bndsA.max()-bndsA.min()) / (nrofpaths-1);\r
-        gdouble incrementB = (bndsB.max()-bndsB.min()) / (nrofpaths-1);\r
-        gdouble tA = bndsA.min();\r
-        gdouble tB = bndsB.min();\r
-        for (int i = 0; i < nrofpaths; i++) {\r
-            Point start = A(tA);\r
-            Point end = B(tB);\r
-            if (startpoint_variation.get_value() != 0)\r
-                start = start + startpoint_variation * (end - start);\r
-            if (endpoint_variation.get_value() != 0)\r
-                end = end + endpoint_variation * (end - start);\r
-    \r
-            Matrix transform;\r
-            transform.setXAxis( (end-start) / scaling );\r
-            gdouble scaling_y = scale_y.get_value() ? L2(end-start)/scaling : 1.0;\r
-            transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y);\r
-            transform.setTranslation( start );\r
-            Piecewise<D2<SBasis> > pwd2_out = (strokepath-stroke_origin) * transform;\r
-            // add stuff to one big pw<d2<sbasis> > and then outside the loop convert to path?\r
-            std::vector<Path> result = Geom::path_from_piecewise(pwd2_out, LPE_CONVERSION_TOLERANCE);\r
-            path_out[i] = result[0];\r
-            tA += incrementA;\r
-            tB += incrementB;\r
-        }\r
-\r
-        return path_out;\r
-    } else {\r
-        return path_in;\r
-    }\r
-}\r
-\r
-} //namespace LivePathEffect\r
-} /* namespace Inkscape */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+#define INKSCAPE_LPE_CURVESTITCH_CPP
+/** \file
+ * LPE Curve Stitching implementation, used as an example for a base starting class
+ * when implementing new LivePathEffects.
+ *
+ */
+/*
+ * Authors:
+ *   Johan Engelen
+*
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-curvestitch.h"
+#include "display/curve.h"
+#include <libnr/n-art-bpath.h>
+#include "sp-item.h"
+#include "sp-path.h"
+#include "live_effects/n-art-bpath-2geom.h"
+#include "xml/repr.h"
+
+#include <2geom/path.h>
+#include <2geom/piecewise.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/d2.h>
+#include <2geom/matrix.h>
+
+
+#include "ui/widget/scalar.h"
+#include "libnr/nr-values.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+using namespace Geom;
+
+LPECurveStitch::LPECurveStitch(LivePathEffectObject *lpeobject) :
+    Effect(lpeobject),
+    strokepath(_("Stroke path"), _("The path that will be used as stitch."), "strokepath", &wr, this, "M0,0 L1,0"),
+    nrofpaths(_("Number of paths"), _("The number of paths that will be generated."), "count", &wr, this, 5),
+    startpoint_edge_variation(_("Start edge variance"), _("The amount of random jitter to move the start points of the stitches inside & outside the guide path"), "startpoint_edge_variation", &wr, this, 0),
+    startpoint_spacing_variation(_("Start spacing variance"), _("The amount of random shifting to move the start points of the stitches back & forth along the guide path"), "startpoint_spacing_variation", &wr, this, 0),
+    endpoint_edge_variation(_("End edge variance"), _("The amount of randomness that moves the end points of the stitches inside & outside the guide path"), "endpoint_edge_variation", &wr, this, 0),
+    endpoint_spacing_variation(_("End spacing variance"), _("The amount of random shifting to move the end points of the stitches back & forth along the guide path"), "endpoint_spacing_variation", &wr, this, 0),
+    prop_scale(_("Scale width"), _("Scaling of the width of the stroke path"), "prop_scale", &wr, this, 1),
+    scale_y_rel(_("Scale width relative"), _("Scale the width of the stroke path relative to its length"), "scale_y_rel", &wr, this, false)
+{
+    registerParameter( dynamic_cast<Parameter *>(&nrofpaths) );
+    registerParameter( dynamic_cast<Parameter *>(&startpoint_edge_variation) );
+    registerParameter( dynamic_cast<Parameter *>(&startpoint_spacing_variation) );
+    registerParameter( dynamic_cast<Parameter *>(&endpoint_edge_variation) );
+    registerParameter( dynamic_cast<Parameter *>(&endpoint_spacing_variation) );
+    registerParameter( dynamic_cast<Parameter *>(&strokepath) );
+    registerParameter( dynamic_cast<Parameter *>(&prop_scale) );
+    registerParameter( dynamic_cast<Parameter *>(&scale_y_rel) );
+
+    nrofpaths.param_make_integer();
+    nrofpaths.param_set_range(2, NR_HUGE);
+
+    prop_scale.param_set_digits(3);
+    prop_scale.param_set_increments(0.01, 0.10);
+}
+
+LPECurveStitch::~LPECurveStitch()
+{
+
+}
+
+std::vector<Geom::Path>
+LPECurveStitch::doEffect_path (std::vector<Geom::Path> & path_in)
+{
+    if (path_in.size() >= 2) {
+        startpoint_edge_variation.resetRandomizer();
+        endpoint_edge_variation.resetRandomizer();
+        startpoint_spacing_variation.resetRandomizer();
+        endpoint_spacing_variation.resetRandomizer();
+
+        D2<Piecewise<SBasis> > stroke = make_cuts_independant(strokepath);
+        Interval bndsStroke = bounds_exact(stroke[0]);
+        gdouble scaling = bndsStroke.max() - bndsStroke.min();
+        Interval bndsStrokeY = bounds_exact(stroke[1]);
+        Point stroke_origin(bndsStroke.min(), (bndsStrokeY.max()+bndsStrokeY.min())/2);
+
+        std::vector<Geom::Path> path_out;
+
+        // do this for all permutations (ii,jj) if there are more than 2 paths? realllly cool!
+        for (int ii = 0   ; ii < path_in.size() - 1; ii++)
+        for (int jj = ii+1; jj < path_in.size(); jj++)
+        {
+            Piecewise<D2<SBasis> > A = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[ii].toPwSb()),2,.1);
+            Piecewise<D2<SBasis> > B = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[jj].toPwSb()),2,.1);
+            Interval bndsA = A.domain();
+            Interval bndsB = B.domain();
+            gdouble incrementA = (bndsA.max()-bndsA.min()) / (nrofpaths-1);
+            gdouble incrementB = (bndsB.max()-bndsB.min()) / (nrofpaths-1);
+            gdouble tA = bndsA.min();
+            gdouble tB = bndsB.min();
+            gdouble tAclean = tA; // the tA without spacing_variation
+            gdouble tBclean = tB; // the tB without spacing_variation
+
+            for (int i = 0; i < nrofpaths; i++) {
+                Point start = A(tA);
+                Point end = B(tB);
+                if (startpoint_edge_variation.get_value() != 0)
+                    start = start + (startpoint_edge_variation - startpoint_edge_variation.get_value()/2) * (end - start);
+                if (endpoint_edge_variation.get_value() != 0)
+                    end = end + (endpoint_edge_variation - endpoint_edge_variation.get_value()/2)* (end - start);
+        
+                if (!Geom::are_near(start,end)) {
+                    gdouble scaling_y = 1.0;
+                    if (scale_y_rel.get_value()) {
+                        scaling_y = (L2(end-start)/scaling)*prop_scale;
+                    } else {
+                        scaling_y = prop_scale;
+                    }
+
+                    Matrix transform;
+                    transform.setXAxis( (end-start) / scaling );
+                    transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y);
+                    transform.setTranslation( start );
+                    Piecewise<D2<SBasis> > pwd2_out = (strokepath-stroke_origin) * transform;
+
+                    // add stuff to one big pw<d2<sbasis> > and then outside the loop convert to path?
+                    // No: this way, the separate result paths are kept separate which might come in handy some time!
+                    std::vector<Geom::Path> result = Geom::path_from_piecewise(pwd2_out, LPE_CONVERSION_TOLERANCE);
+                    path_out.push_back(result[0]);
+                }
+                gdouble svA = startpoint_spacing_variation - startpoint_spacing_variation.get_value()/2;
+                gdouble svB = endpoint_spacing_variation - endpoint_spacing_variation.get_value()/2;
+                tAclean += incrementA;
+                tBclean += incrementB;
+                tA = tAclean + incrementA * svA;
+                tB = tBclean + incrementB * svB;
+                if (tA > bndsA.max())
+                    tA = bndsA.max();
+                if (tB > bndsB.max())
+                    tB = bndsB.max();
+            }
+        }
+
+        return path_out;
+    } else {
+        return path_in;
+    }
+}
+
+void
+LPECurveStitch::resetDefaults(SPItem * item)
+{
+    if (!SP_IS_PATH(item)) return;
+
+    using namespace Geom;
+
+    // set the stroke path to run horizontally in the middle of the bounding box of the original path
+    Piecewise<D2<SBasis> > pwd2;
+    std::vector<Geom::Path> temppath = SVGD_to_2GeomPath( SP_OBJECT_REPR(item)->attribute("inkscape:original-d"));
+    for (unsigned int i=0; i < temppath.size(); i++) {
+        pwd2.concat( temppath[i].toPwSb() );
+    }
+
+    D2<Piecewise<SBasis> > d2pw = make_cuts_independant(pwd2);
+    Interval bndsX = bounds_exact(d2pw[0]);
+    Interval bndsY = bounds_exact(d2pw[1]);
+    Point start(bndsX.min(), (bndsY.max()+bndsY.min())/2);
+    Point end(bndsX.max(), (bndsY.max()+bndsY.min())/2);
+
+    if ( !Geom::are_near(start,end) ) {
+        Geom::Path path;
+        path.start( start );
+        path.appendNew<Geom::LineSegment>( end );
+        strokepath.param_set_and_write_new_value( path.toPwSb() );
+    } else {
+        // bounding box is too small to make decent path. set to default default. :-)
+        strokepath.param_set_and_write_default();
+    }
+}
+
+void
+LPECurveStitch::transform_multiply(Geom::Matrix const& postmul, bool set)
+{
+    // only take translations into account
+    if (postmul.isTranslation()) {
+        strokepath.param_transform_multiply(postmul, set);
+    } else if (!scale_y_rel.get_value()) {
+  // this basically means that for this transformation, the result should be the same as normal scaling the result path
+  // don't know how to do this yet.
+//        Geom::Matrix new_postmul;
+        //new_postmul.setIdentity();
+//        new_postmul.setTranslation(postmul.translation());
+//        Effect::transform_multiply(new_postmul, set);
+    }
+}
+
+} //namespace LivePathEffect
+} /* namespace Inkscape */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :