summaryrefslogtreecommitdiffstats
path: root/src/live_effects/lpe-curvestitch.cpp
blob: 8eb35087e547e6c438361a1294a68a2227a5b307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#define INKSCAPE_LPE_EXPRESSION_CPP
/** \file
 * SVG <skeleton> 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 <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 stroked, whatever, think of good text here."), "strokepath", &wr, this, "M0,0 L1,0"),
    nrofpaths(_("Nr of paths"), _("The number of paths that will be generated."), "count", &wr, this, 5),
    startpoint_variation(_("Startpoint variation"), _("..."), "startpoint_variation", &wr, this, 0),
    endpoint_variation(_("Endpoint variation"), _("..."), "endpoint_variation", &wr, this, 0),
    prop_scale(_("Scale ratio"), _("Ratio between scaling in the x and y direction of the original path"), "prop_scale", &wr, this, 1),
    scale_y(_("Scale stroke y"), _("Scale the height of the stroke path with its length"), "scale_stroke_y", &wr, this, false)
{
    registerParameter( dynamic_cast<Parameter *>(&nrofpaths) );
    registerParameter( dynamic_cast<Parameter *>(&startpoint_variation) );
    registerParameter( dynamic_cast<Parameter *>(&endpoint_variation) );
    registerParameter( dynamic_cast<Parameter *>(&strokepath) );
    registerParameter( dynamic_cast<Parameter *>(&prop_scale) );
    registerParameter( dynamic_cast<Parameter *>(&scale_y) );

    nrofpaths.param_make_integer();
    nrofpaths.param_set_range(2, NR_HUGE);

//    startpoint_variation.param_set_range(-NR_HUGE, 1);
//    endpoint_variation.param_set_range(-1, NR_HUGE);
}

LPECurveStitch::~LPECurveStitch()
{

}

std::vector<Geom::Path>
LPECurveStitch::doEffect (std::vector<Geom::Path> & path_in)
{
    if (path_in.size() >= 2) {
        startpoint_variation.resetRandomizer();
        endpoint_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 (nrofpaths);

        // do this for all permutations if there are more than 2 paths? realllly cool!
        Piecewise<D2<SBasis> > A = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[0].toPwSb()),2,.1);
        Piecewise<D2<SBasis> > B = arc_length_parametrization(Piecewise<D2<SBasis> >(path_in[1].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();
        for (int i = 0; i < nrofpaths; i++) {
            Point start = A(tA);
            Point end = B(tB);
            if (startpoint_variation.get_value() != 0)
                start = start + startpoint_variation * (end - start);
            if (endpoint_variation.get_value() != 0)
                end = end + endpoint_variation * (end - start);
    
            Matrix transform;
            transform.setXAxis( (end-start) / scaling );
            gdouble scaling_y = scale_y.get_value() ? (L2(end-start)/scaling)*prop_scale : 1.0;
            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?
            std::vector<Path> result = Geom::path_from_piecewise(pwd2_out, LPE_CONVERSION_TOLERANCE);
            path_out[i] = result[0];
            tA += incrementA;
            tB += incrementB;
        }

        return path_out;
    } else {
        return path_in;
    }
}

} //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 :