~ubuntu-branches/ubuntu/quantal/zaz/quantal

« back to all changes in this revision

Viewing changes to src/bezier.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Miriam Ruiz
  • Date: 2009-08-31 20:08:58 UTC
  • Revision ID: james.westby@ubuntu.com-20090831200858-54lcmcrna6dwk3wr
Tags: upstream-0.2.9+dfsg1
ImportĀ upstreamĀ versionĀ 0.2.9+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Zaz
 
3
 * Copyright (C) Remigiusz Dybka 2009 <remigiusz.dybka@gmail.com>
 
4
 *
 
5
 Zaz is free software: you can redistribute it and/or modify it
 
6
 under the terms of the GNU General Public License as published by the
 
7
 Free Software Foundation, either version 3 of the License, or
 
8
 (at your option) any later version.
 
9
 
 
10
 Zaz is distributed in the hope that it will be useful, but
 
11
 WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
13
 See the GNU General Public License for more details.
 
14
 
 
15
 You should have received a copy of the GNU General Public License along
 
16
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include "bezier.h"
 
20
 
 
21
#define MIDP(a, b, t) XY(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t)
 
22
 
 
23
std::vector<XY> Bezier::Generate(int steps)
 
24
{
 
25
    double stepping = 1.0 / (double)steps;
 
26
 
 
27
    std::vector<XY> ret;
 
28
    std::vector<BezierPoint>::iterator iter;
 
29
    std::vector<BezierPoint>::iterator iter2;
 
30
 
 
31
    bool first = true;
 
32
    for (iter = points.begin(), iter2 = points.begin(), ++iter2; iter2 != points.end(); ++iter, ++iter2)
 
33
    {
 
34
        XY p0(iter->x, iter->y);
 
35
        XY p1(iter->cx, iter->cy);
 
36
        XY p2(iter2->cx, iter2->cy);
 
37
        XY p3(iter2->x, iter2->y);
 
38
 
 
39
        // if not first point, the controls for in p1 are inverse
 
40
 
 
41
        if (!first)
 
42
        {
 
43
            p1 = XY((iter->x - iter->cx) + iter->x,
 
44
                    (iter->y - iter->cy) + iter->y);
 
45
        }
 
46
        first = false;
 
47
 
 
48
        for (double t = 0; t < 1.0; t+= stepping)
 
49
        {
 
50
            XY l1 = MIDP(p0, p1, t);
 
51
            XY l2 = MIDP(p1, p2, t);
 
52
            XY l3 = MIDP(p2, p3, t);
 
53
 
 
54
            XY m1 = MIDP(l1, l2, t);
 
55
            XY m2 = MIDP(l2, l3, t);
 
56
 
 
57
            ret.push_back(MIDP(m1, m2, t));
 
58
        }
 
59
 
 
60
        ret.push_back(XY(iter2->x, iter2->y));
 
61
    }
 
62
 
 
63
    return ret;
 
64
}
 
65
 
 
66
double veclen(XY a, XY b)
 
67
{
 
68
    return sqrt(pow(fabs(b.x - a.x), 2.0) + pow(fabs(b.y - a.y), 2.0));
 
69
}
 
70
 
 
71
std::vector<XY> Bezier::GenerateUniform(double step)
 
72
{
 
73
    std::vector<XY> ret;
 
74
    std::vector<BezierPoint>::iterator iter;
 
75
    std::vector<BezierPoint>::iterator iter2;
 
76
 
 
77
    bool first = true;
 
78
    for (iter = points.begin(), iter2 = points.begin(), ++iter2; iter2 != points.end(); ++iter, ++iter2)
 
79
    {
 
80
        XY p0(iter->x, iter->y);
 
81
        XY p1(iter->cx, iter->cy);
 
82
        XY p2(iter2->cx, iter2->cy);
 
83
        XY p3(iter2->x, iter2->y);
 
84
 
 
85
        // if not first point, the controls for in p1 are inverse
 
86
        if (!first)
 
87
        {
 
88
            p1 = XY((iter->x - iter->cx) + iter->x,
 
89
                    (iter->y - iter->cy) + iter->y);
 
90
        }
 
91
        first = false;
 
92
 
 
93
 
 
94
        double stepping = 0.01 / (((veclen(p1, p0) +
 
95
                                    veclen(p2, p1) +
 
96
                                    veclen(p3, p2)) / 3.0) / step);
 
97
 
 
98
        XY lp = p0;
 
99
        for (double t = 0; t < 1.0; t+= stepping)
 
100
        {
 
101
            XY l1 = MIDP(p0, p1, t);
 
102
            XY l2 = MIDP(p1, p2, t);
 
103
            XY l3 = MIDP(p2, p3, t);
 
104
 
 
105
            XY m1 = MIDP(l1, l2, t);
 
106
            XY m2 = MIDP(l2, l3, t);
 
107
 
 
108
            XY np = MIDP(m1, m2, t);
 
109
 
 
110
            double len = veclen(np, lp);
 
111
            if (len >= step)
 
112
            {
 
113
                ret.push_back(np);
 
114
                lp = np;
 
115
            }
 
116
        }
 
117
 
 
118
        ret.push_back(XY(iter2->x, iter2->y));
 
119
    }
 
120
 
 
121
    return ret;
 
122
}
 
123
 
 
124
std::vector<XY> Bezier::GenerateBalls(double dist, int steps)
 
125
{
 
126
    std::vector<XY> ret;
 
127
    std::vector<BezierPoint>::iterator iter;
 
128
    std::vector<BezierPoint>::iterator iter2;
 
129
 
 
130
    bool first = true;
 
131
    bool firstDist = true;
 
132
    int s = 0;
 
133
    for (iter = points.begin(), iter2 = points.begin(), ++iter2; iter2 != points.end(); ++iter, ++iter2)
 
134
    {
 
135
        XY p0(iter->x, iter->y);
 
136
        XY p1(iter->cx, iter->cy);
 
137
        XY p2(iter2->cx, iter2->cy);
 
138
        XY p3(iter2->x, iter2->y);
 
139
 
 
140
        // if not first point, the controls for in p1 are inverse
 
141
        if (!first)
 
142
        {
 
143
            p1 = XY((iter->x - iter->cx) + iter->x,
 
144
                    (iter->y - iter->cy) + iter->y);
 
145
        }
 
146
 
 
147
 
 
148
 
 
149
        double step = dist / (double)steps;
 
150
        double stepping = 0.01 / (((veclen(p1, p0) +
 
151
                                    veclen(p2, p1) +
 
152
                                    veclen(p3, p2)) / 3.0) / step);
 
153
 
 
154
        XY lp = p0;
 
155
        first = false;
 
156
 
 
157
        for (double t = 0; t < 1.0; t+= stepping)
 
158
        {
 
159
            XY l1 = MIDP(p0, p1, t);
 
160
            XY l2 = MIDP(p1, p2, t);
 
161
            XY l3 = MIDP(p2, p3, t);
 
162
 
 
163
            XY m1 = MIDP(l1, l2, t);
 
164
            XY m2 = MIDP(l2, l3, t);
 
165
 
 
166
            XY np = MIDP(m1, m2, t);
 
167
 
 
168
            if ((firstDist) && (s <= dist * steps))
 
169
            {
 
170
                if (veclen(lp, np) >= step)
 
171
                {
 
172
                    ret.push_back(np);
 
173
                    lp = np;
 
174
                    ++s;
 
175
                }
 
176
            }
 
177
            else
 
178
            {
 
179
                double len = veclen(np, ret[s - steps]);
 
180
                if (len >= dist)
 
181
                {
 
182
                    ret.push_back(np);
 
183
                    ++s;
 
184
                    lp = np;
 
185
                }
 
186
            }
 
187
        }
 
188
 
 
189
        firstDist = false;
 
190
 
 
191
        ret.push_back(XY(iter2->x, iter2->y));
 
192
    }
 
193
 
 
194
    return ret;
 
195
}