Code

add LPE extrude. it's not finished yet!
authorjohanengelen <johanengelen@users.sourceforge.net>
Mon, 23 Nov 2009 20:36:50 +0000 (20:36 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Mon, 23 Nov 2009 20:36:50 +0000 (20:36 +0000)
src/live_effects/effect-enum.h
src/live_effects/effect.cpp
src/live_effects/lpe-extrude.cpp [new file with mode: 0644]
src/live_effects/lpe-extrude.h [new file with mode: 0644]

index 1911c6e20c034423062bdfe897a40a11425a084e..6f1004ae587767a70cf852e6e636c94bb290a14b 100644 (file)
@@ -47,6 +47,7 @@ enum EffectType {
     DOEFFECTSTACK_TEST,
     DYNASTROKE,
     RECURSIVE_SKELETON,
+    EXTRUDE,
     INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan)
 };
 
index 1d001b31a339e87659424b2052549369fb5a791f..04549622eb3c28b8313c0de5c223ca83e86e1b98 100644 (file)
@@ -74,6 +74,7 @@
 #include "live_effects/lpe-path_length.h"
 #include "live_effects/lpe-line_segment.h"
 #include "live_effects/lpe-recursiveskeleton.h"
+#include "live_effects/lpe-extrude.h"
 
 
 namespace Inkscape {
@@ -90,6 +91,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
     {CIRCLE_WITH_RADIUS,    N_("Circle (by center and radius)"),   "circle_with_radius"},
     {CIRCLE_3PTS,           N_("Circle by 3 points"),      "circle_3pts"},
     {DYNASTROKE,            N_("Dynamic stroke"),          "dynastroke"},
+    {EXTRUDE,               N_("Extrude"),                 "extrude"},
     {LATTICE,               N_("Lattice Deformation"),     "lattice"},
     {LINE_SEGMENT,          N_("Line Segment"),            "line_segment"},
     {MIRROR_SYMMETRY,       N_("Mirror symmetry"),         "mirror_symmetry"},
@@ -232,6 +234,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
         case RECURSIVE_SKELETON:
             neweffect = static_cast<Effect*> ( new LPERecursiveSkeleton(lpeobj) );
             break;
+        case EXTRUDE:
+            neweffect = static_cast<Effect*> ( new LPEExtrude(lpeobj) );
+            break;
         default:
             g_warning("LivePathEffect::Effect::New   called with invalid patheffect type (%d)", lpenr);
             neweffect = NULL;
diff --git a/src/live_effects/lpe-extrude.cpp b/src/live_effects/lpe-extrude.cpp
new file mode 100644 (file)
index 0000000..93ab60f
--- /dev/null
@@ -0,0 +1,145 @@
+#define INKSCAPE_LPE_EXTRUDE_CPP
+/** \file
+ * @brief LPE effect for extruding paths (making them "3D").
+ *
+ */
+/* Authors:
+ *   Johan Engelen <j.b.c.engelen@utwente.nl>
+ *
+ * Copyright (C) 2009 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-extrude.h"
+
+#include <2geom/path.h>
+#include <2geom/piecewise.h>
+#include <2geom/transforms.h>
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPEExtrude::LPEExtrude(LivePathEffectObject *lpeobject) :
+    Effect(lpeobject),
+    extrude_vector(_("Direction"), _("Defines the direction and magnitude of the extrusion"), "extrude_vector", &wr, this, Geom::Point(-10,10))
+{
+    show_orig_path = true;
+    concatenate_before_pwd2 = false;
+
+    registerParameter( dynamic_cast<Parameter *>(&extrude_vector) );
+}
+
+LPEExtrude::~LPEExtrude()
+{
+
+}
+
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> >
+LPEExtrude::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
+{
+    using namespace Geom;
+
+    // generate connecting lines (the 'sides' of the extrusion)
+    Path path(Point(0.,0.));
+    path.appendNew<Geom::LineSegment>( extrude_vector.getVector() );
+    Piecewise<D2<SBasis> > connector = path.toPwSb();
+
+    switch( 1 ) {
+    case 0: {
+        Piecewise<D2<SBasis> > pwd2_out = pwd2_in;
+        // generate extrusion bottom: (just a copy of original path, displaced a bit)
+        pwd2_out.concat( pwd2_in + extrude_vector.getVector() );
+
+        // connecting lines should be put at start and end of path if it is not closed
+        // it is not possible to check whether a piecewise<T> path is closed, 
+        // so we check whether start and end are close
+        if ( ! are_near(pwd2_in.firstValue(), pwd2_in.lastValue()) ) {
+            pwd2_out.concat( connector + pwd2_in.firstValue() );
+            pwd2_out.concat( connector + pwd2_in.lastValue() );
+        }
+        // connecting lines should be put at cusps
+        Piecewise<D2<SBasis> > deriv = derivative(pwd2_in);
+        std::vector<double> cusps; // = roots(deriv);
+        for (unsigned i = 0; i < cusps.size() ; ++i) {
+            pwd2_out.concat( connector + pwd2_in.valueAt(cusps[i]) );
+        }
+        // connecting lines should be put where the tangent of the path equals the extrude_vector in direction
+        std::vector<double> rts = roots(dot(deriv, rot90(extrude_vector.getVector())));
+        for (unsigned i = 0; i < rts.size() ; ++i) {
+            pwd2_out.concat( connector + pwd2_in.valueAt(rts[i]) );
+        }
+        return pwd2_out;
+    }
+
+    case 1: {
+        Piecewise<D2<SBasis> > pwd2_out;
+        bool closed_path = are_near(pwd2_in.firstValue(), pwd2_in.lastValue());
+        // split input path in pieces between points where deriv == vector
+        Piecewise<D2<SBasis> > deriv = derivative(pwd2_in);
+        std::vector<double> rts = roots(dot(deriv, rot90(extrude_vector.getVector())));
+        double portion_t = 0.;
+        for (unsigned i = 0; i < rts.size() ; ++i) {
+            Piecewise<D2<SBasis> > cut = portion(pwd2_in, portion_t, rts[i] );
+            portion_t = rts[i];
+            if (closed_path && i == 0) {
+                // if the path is closed, skip the first cut and add it to the last cut later
+                continue;
+            }
+            Piecewise<D2<SBasis> > part = cut;
+            part.continuousConcat(connector + cut.lastValue());
+            part.continuousConcat(reverse(cut) + extrude_vector.getVector());
+            part.continuousConcat(reverse(connector) + cut.firstValue());
+            pwd2_out.concat( part );
+        }
+        if (closed_path) {
+            Piecewise<D2<SBasis> > cut = portion(pwd2_in, portion_t, pwd2_in.domain().max() );
+            cut.continuousConcat(portion(pwd2_in, pwd2_in.domain().min(), rts[0] ));
+            Piecewise<D2<SBasis> > part = cut;
+            part.continuousConcat(connector + cut.lastValue());
+            part.continuousConcat(reverse(cut) + extrude_vector.getVector());
+            part.continuousConcat(reverse(connector) + cut.firstValue());
+            pwd2_out.concat( part );
+        } else if (!are_near(portion_t, pwd2_in.domain().max())) {
+            Piecewise<D2<SBasis> > cut = portion(pwd2_in, portion_t, pwd2_in.domain().max() );
+            Piecewise<D2<SBasis> > part = cut;
+            part.continuousConcat(connector + cut.lastValue());
+            part.continuousConcat(reverse(cut) + extrude_vector.getVector());
+            part.continuousConcat(reverse(connector) + cut.firstValue());
+            pwd2_out.concat( part );
+        }
+        return pwd2_out;
+    }
+    }
+}
+
+void
+LPEExtrude::resetDefaults(SPItem * item)
+{
+    Effect::resetDefaults(item);
+
+    using namespace Geom;
+
+    Geom::OptRect bbox = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX);
+    if (bbox) {
+        Interval boundingbox_X = (*bbox)[Geom::X];
+        Interval boundingbox_Y = (*bbox)[Geom::Y];
+        extrude_vector.set_and_write_new_values( Geom::Point(boundingbox_X.middle(), boundingbox_Y.middle()), 
+                                                 (boundingbox_X.extent() + boundingbox_Y.extent())*Geom::Point(-0.05,0.2) );
+    }
+}
+
+} //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:encoding=utf-8:textwidth=99 :
diff --git a/src/live_effects/lpe-extrude.h b/src/live_effects/lpe-extrude.h
new file mode 100644 (file)
index 0000000..b704aa8
--- /dev/null
@@ -0,0 +1,52 @@
+/** @file
+ * @brief LPE effect for extruding paths (making them "3D").
+ */
+/* Authors:
+ *   Johan Engelen <j.b.c.engelen@utwente.nl>
+ *
+ * Copyright (C) 2009 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_LPE_EXTRUDE_H
+#define INKSCAPE_LPE_EXTRUDE_H
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/vector.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPEExtrude : public Effect {
+public:
+    LPEExtrude(LivePathEffectObject *lpeobject);
+    virtual ~LPEExtrude();
+
+    virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+
+    virtual void resetDefaults(SPItem * item);
+
+private:
+    VectorParam extrude_vector;
+
+    LPEExtrude(const LPEExtrude&);
+    LPEExtrude& operator=(const LPEExtrude&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
+
+/*
+  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:encoding=utf-8:textwidth=99 :