Inkscape
Vector Graphics Editor
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages Concepts
bezier.h
Go to the documentation of this file.
1/*
5 * Authors:
6 * MenTaLguY <mental@rydia.net>
7 * Michael Sloan <mgsloan@gmail.com>
8 * Nathan Hurst <njh@njhurst.com>
9 * Krzysztof Kosiński <tweenk.pl@gmail.com>
10 *
11 * Copyright 2007-2015 Authors
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it either under the terms of the GNU Lesser General Public
15 * License version 2.1 as published by the Free Software Foundation
16 * (the "LGPL") or, at your option, under the terms of the Mozilla
17 * Public License Version 1.1 (the "MPL"). If you do not alter this
18 * notice, a recipient may use your version of this file under either
19 * the MPL or the LGPL.
20 *
21 * You should have received a copy of the LGPL along with this library
22 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * You should have received a copy of the MPL along with this library
25 * in the file COPYING-MPL-1.1
26 *
27 * The contents of this file are subject to the Mozilla Public License
28 * Version 1.1 (the "License"); you may not use this file except in
29 * compliance with the License. You may obtain a copy of the License at
30 * http://www.mozilla.org/MPL/
31 *
32 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
33 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
34 * the specific language governing rights and limitations.
35 *
36 */
37
38#ifndef LIB2GEOM_SEEN_BEZIER_H
39#define LIB2GEOM_SEEN_BEZIER_H
40
41#include <algorithm>
42#include <valarray>
43#include <2geom/coord.h>
44#include <2geom/d2.h>
45#include <2geom/math-utils.h>
46
47namespace Geom {
48
54template <typename T>
55inline T bernstein_value_at(double t, T const *c_, unsigned n) {
56 double u = 1.0 - t;
57 double bc = 1;
58 double tn = 1;
59 T tmp = c_[0]*u;
60 for(unsigned i=1; i<n; i++){
61 tn = tn*t;
62 bc = bc*(n-i+1)/i;
63 tmp = (tmp + tn*bc*c_[i])*u;
64 }
65 return (tmp + tn*t*c_[n]);
66}
67
77template <typename T>
78inline T casteljau_subdivision(double t, T const *v, T *left, T *right, unsigned order) {
79 // The Horner-like scheme gives very slightly different results, but we need
80 // the result of subdivision to match exactly with Bezier's valueAt function.
81 T val = bernstein_value_at(t, v, order);
82
83 if (!left && !right) {
84 return val;
85 }
86
87 if (!right) {
88 if (left != v) {
89 std::copy(v, v + order + 1, left);
90 }
91 for (std::size_t i = order; i > 0; --i) {
92 for (std::size_t j = i; j <= order; ++j) {
93 left[j] = lerp(t, left[j-1], left[j]);
94 }
95 }
96 left[order] = val;
97 return left[order];
98 }
99
100 if (right != v) {
101 std::copy(v, v + order + 1, right);
102 }
103 for (std::size_t i = 1; i <= order; ++i) {
104 if (left) {
105 left[i-1] = right[0];
106 }
107 for (std::size_t j = i; j > 0; --j) {
108 right[j-1] = lerp(t, right[j-1], right[j]);
109 }
110 }
111 right[0] = val;
112 if (left) {
113 left[order] = right[0];
114 }
115 return right[0];
116}
117
123 : boost::arithmetic< Bezier, double
124 , boost::additive< Bezier
125 > >
126{
127private:
128 std::valarray<Coord> c_;
129
130 friend Bezier portion(const Bezier & a, Coord from, Coord to);
131 friend OptInterval bounds_fast(Bezier const & b);
132 friend Bezier derivative(const Bezier & a);
133 friend class Bernstein;
134
135 void
136 find_bezier_roots(std::vector<double> & solutions,
137 double l, double r) const;
138
139protected:
140 Bezier(Coord const c[], unsigned ord)
141 : c_(c, ord+1)
142 {}
143
144public:
145 unsigned order() const { return c_.size()-1;}
146 unsigned degree() const { return order(); }
147 unsigned size() const { return c_.size();}
148
150 Bezier(const Bezier& b) :c_(b.c_) {}
151 Bezier &operator=(Bezier const &other) {
152 if ( c_.size() != other.c_.size() ) {
153 c_.resize(other.c_.size());
154 }
155 c_ = other.c_;
156 return *this;
157 }
158
159 bool operator==(Bezier const &other) const
160 {
161 if (degree() != other.degree()) {
162 return false;
163 }
164
165 for (size_t i = 0; i < c_.size(); i++) {
166 if (c_[i] != other.c_[i]) {
167 return false;
168 }
169 }
170 return true;
171 }
172
173 bool operator!=(Bezier const &other) const
174 {
175 return !(*this == other);
176 }
177
178 struct Order {
179 unsigned order;
180 explicit Order(Bezier const &b) : order(b.order()) {}
181 explicit Order(unsigned o) : order(o) {}
182 operator unsigned() const { return order; }
183 };
184
185 //Construct an arbitrary order bezier
186 Bezier(Order ord) : c_(0., ord.order+1) {
187 assert(ord.order == order());
188 }
189
192 explicit Bezier(Coord c0) : c_(0., 1) {
193 c_[0] = c0;
194 }
195 Bezier(Coord c0, Coord c1) : c_(0., 2) {
196 c_[0] = c0; c_[1] = c1;
197 }
198 Bezier(Coord c0, Coord c1, Coord c2) : c_(0., 3) {
199 c_[0] = c0; c_[1] = c1; c_[2] = c2;
200 }
201 Bezier(Coord c0, Coord c1, Coord c2, Coord c3) : c_(0., 4) {
202 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3;
203 }
204 Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4) : c_(0., 5) {
205 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
206 }
207 Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
208 Coord c5) : c_(0., 6) {
209 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
210 c_[5] = c5;
211 }
212 Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
213 Coord c5, Coord c6) : c_(0., 7) {
214 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
215 c_[5] = c5; c_[6] = c6;
216 }
217 Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
218 Coord c5, Coord c6, Coord c7) : c_(0., 8) {
219 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
220 c_[5] = c5; c_[6] = c6; c_[7] = c7;
221 }
222 Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
223 Coord c5, Coord c6, Coord c7, Coord c8) : c_(0., 9) {
224 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
225 c_[5] = c5; c_[6] = c6; c_[7] = c7; c_[8] = c8;
226 }
227 Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
228 Coord c5, Coord c6, Coord c7, Coord c8, Coord c9) : c_(0., 10) {
229 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
230 c_[5] = c5; c_[6] = c6; c_[7] = c7; c_[8] = c8; c_[9] = c9;
231 }
232
233 template <typename Iter>
234 Bezier(Iter first, Iter last) {
235 c_.resize(std::distance(first, last));
236 for (std::size_t i = 0; first != last; ++first, ++i) {
237 c_[i] = *first;
238 }
239 }
240 Bezier(std::vector<Coord> const &vec)
241 : c_(&vec[0], vec.size())
242 {}
244
245 void resize (unsigned int n, Coord v = 0) {
246 c_.resize (n, v);
247 }
248 void clear() {
249 c_.resize(0);
250 }
251
252 //IMPL: FragmentConcept
254 bool isZero(double eps=EPSILON) const {
255 for(unsigned i = 0; i <= order(); i++) {
256 if( ! are_near(c_[i], 0., eps) ) return false;
257 }
258 return true;
259 }
260 bool isConstant(double eps=EPSILON) const {
261 for(unsigned i = 1; i <= order(); i++) {
262 if( ! are_near(c_[i], c_[0], eps) ) return false;
263 }
264 return true;
265 }
266 bool isFinite() const {
267 for(unsigned i = 0; i <= order(); i++) {
268 if(!std::isfinite(c_[i])) return false;
269 }
270 return true;
271 }
272 Coord at0() const { return c_[0]; }
273 Coord &at0() { return c_[0]; }
274 Coord at1() const { return c_[order()]; }
275 Coord &at1() { return c_[order()]; }
276
277 Coord valueAt(double t) const {
278 return bernstein_value_at(t, &c_[0], order());
279 }
280 Coord operator()(double t) const { return valueAt(t); }
281
282 SBasis toSBasis() const;
283
284 Coord &operator[](unsigned ix) { return c_[ix]; }
285 Coord const &operator[](unsigned ix) const { return c_[ix]; }
286
287 void setCoeff(unsigned ix, double val) { c_[ix] = val; }
288
289 // The size of the returned vector equals n_derivs+1.
290 std::vector<Coord> valueAndDerivatives(Coord t, unsigned n_derivs) const;
291
292 void subdivide(Coord t, Bezier *left, Bezier *right) const;
293 std::pair<Bezier, Bezier> subdivide(Coord t) const;
294
295 std::vector<Coord> roots() const;
296 std::vector<Coord> roots(Interval const &ivl) const;
297
298 Bezier forward_difference(unsigned k) const;
299 Bezier elevate_degree() const;
300 Bezier reduce_degree() const;
301 Bezier elevate_to_degree(unsigned newDegree) const;
302 Bezier deflate() const;
303
304 // basic arithmetic operators
305 Bezier &operator+=(double v) {
306 c_ += v;
307 return *this;
308 }
309 Bezier &operator-=(double v) {
310 c_ -= v;
311 return *this;
312 }
313 Bezier &operator*=(double v) {
314 c_ *= v;
315 return *this;
316 }
317 Bezier &operator/=(double v) {
318 c_ /= v;
319 return *this;
320 }
321 Bezier &operator+=(Bezier const &other);
322 Bezier &operator-=(Bezier const &other);
323
326 {
328 result.c_ = -c_;
329 return result;
330 }
331};
332
333
334void bezier_to_sbasis(SBasis &sb, Bezier const &bz);
335
336Bezier operator*(Bezier const &f, Bezier const &g);
337inline Bezier multiply(Bezier const &f, Bezier const &g) {
338 Bezier result = f * g;
339 return result;
340}
341
342inline Bezier reverse(const Bezier & a) {
344 for(unsigned i = 0; i <= a.order(); i++)
345 result[i] = a[a.order() - i];
346 return result;
347}
348
349Bezier portion(const Bezier & a, double from, double to);
350
351// XXX Todo: how to handle differing orders
352inline std::vector<Point> bezier_points(const D2<Bezier > & a) {
353 std::vector<Point> result;
354 for(unsigned i = 0; i <= a[0].order(); i++) {
355 Point p;
356 for(unsigned d = 0; d < 2; d++) p[d] = a[d][i];
357 result.push_back(p);
358 }
359 return result;
360}
361
362Bezier derivative(Bezier const &a);
363Bezier integral(Bezier const &a);
364OptInterval bounds_fast(Bezier const &b);
365OptInterval bounds_exact(Bezier const &b);
366OptInterval bounds_local(Bezier const &b, OptInterval const &i);
367
369void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2);
370void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2, Coord x3);
371
372inline std::ostream &operator<< (std::ostream &os, const Bezier & b) {
373 os << "Bezier(";
374 for(unsigned i = 0; i < b.order(); i++) {
375 os << format_coord_nice(b[i]) << ", ";
376 }
377 os << format_coord_nice(b[b.order()]) << ")";
378 return os;
379}
380
381} // namespace Geom
382
383#endif // LIB2GEOM_SEEN_BEZIER_H
384
385/*
386 Local Variables:
387 mode:c++
388 c-file-style:"stroustrup"
389 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
390 indent-tabs-mode:nil
391 fill-column:99
392 End:
393*/
394// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Polynomial in Bernstein-Bezier basis.
Definition bezier.h:126
Bezier deflate() const
Definition bezier.cpp:176
Bezier & operator*=(double v)
Definition bezier.h:313
void resize(unsigned int n, Coord v=0)
Definition bezier.h:245
Bezier(Order ord)
Definition bezier.h:186
std::vector< Coord > valueAndDerivatives(Coord t, unsigned n_derivs) const
Definition bezier.cpp:51
friend class Bernstein
Definition bezier.h:133
Coord & at1()
Definition bezier.h:275
friend OptInterval bounds_fast(Bezier const &b)
Definition bezier.cpp:305
Bezier elevate_to_degree(unsigned newDegree) const
Definition bezier.cpp:167
unsigned degree() const
Definition bezier.h:146
void subdivide(Coord t, Bezier *left, Bezier *right) const
Definition bezier.cpp:79
Bezier(Coord c0)
Definition bezier.h:192
Bezier forward_difference(unsigned k) const
Definition bezier.cpp:121
void find_bezier_roots(std::vector< double > &solutions, double l, double r) const
Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5, Coord c6)
Definition bezier.h:212
void clear()
Definition bezier.h:248
std::vector< Coord > roots() const
Definition bezier.cpp:105
Coord const & operator[](unsigned ix) const
Definition bezier.h:285
Bezier(std::vector< Coord > const &vec)
Definition bezier.h:240
Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5, Coord c6, Coord c7, Coord c8, Coord c9)
Definition bezier.h:227
Bezier(const Bezier &b)
Definition bezier.h:150
Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5, Coord c6, Coord c7)
Definition bezier.h:217
Bezier reduce_degree() const
Definition bezier.cpp:150
friend Bezier derivative(const Bezier &a)
Definition bezier.cpp:282
Coord operator()(double t) const
Definition bezier.h:280
Bezier elevate_degree() const
Definition bezier.cpp:138
bool isFinite() const
Definition bezier.h:266
bool operator!=(Bezier const &other) const
Definition bezier.h:173
Bezier operator-() const
Unary minus.
Definition bezier.h:325
Bezier(Coord c0, Coord c1)
Definition bezier.h:195
Bezier(Coord c0, Coord c1, Coord c2, Coord c3)
Definition bezier.h:201
bool isZero(double eps=EPSILON) const
Definition bezier.h:254
Bezier & operator+=(double v)
Definition bezier.h:305
unsigned size() const
Definition bezier.h:147
Coord at0() const
Definition bezier.h:272
Bezier & operator=(Bezier const &other)
Definition bezier.h:151
SBasis toSBasis() const
Definition bezier.cpp:187
std::valarray< Coord > c_
Definition bezier.h:128
Bezier(Coord c0, Coord c1, Coord c2)
Definition bezier.h:198
bool isConstant(double eps=EPSILON) const
Definition bezier.h:260
Coord & at0()
Definition bezier.h:273
unsigned order() const
Definition bezier.h:145
Bezier & operator/=(double v)
Definition bezier.h:317
Bezier(Coord const c[], unsigned ord)
Definition bezier.h:140
Coord output_type
Definition bezier.h:253
Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5, Coord c6, Coord c7, Coord c8)
Definition bezier.h:222
Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5)
Definition bezier.h:207
Coord valueAt(double t) const
Definition bezier.h:277
void setCoeff(unsigned ix, double val)
Definition bezier.h:287
Bezier(Iter first, Iter last)
Definition bezier.h:234
Bezier & operator-=(double v)
Definition bezier.h:309
Coord & operator[](unsigned ix)
Definition bezier.h:284
Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4)
Definition bezier.h:204
bool operator==(Bezier const &other) const
Definition bezier.h:159
friend Bezier portion(const Bezier &a, Coord from, Coord to)
Definition bezier.cpp:250
Coord at1() const
Definition bezier.h:274
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
Range of real numbers that is never empty.
Definition interval.h:59
Range of real numbers that can be empty.
Definition interval.h:199
Two-dimensional point that doubles as a vector.
Definition point.h:66
Polynomial in symmetric power basis.
Definition sbasis.h:70
Integral and real coordinate types and some basic utilities.
Css & result
double c[8][4]
Lifts one dimensional objects into 2D.
const unsigned order
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
Definition coord.h:97
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
constexpr Coord EPSILON
Default "acceptably small" value.
Definition coord.h:84
Low level math functions and compatibility wrappers.
Various utility functions.
Definition affine.h:22
OptInterval bounds_exact(Bezier const &b)
Definition bezier.cpp:310
Bezier reverse(const Bezier &a)
Definition bezier.h:342
OptInterval bounds_local(Bezier const &b, OptInterval const &i)
Definition bezier.cpp:320
T casteljau_subdivision(double t, T const *v, T *left, T *right, unsigned order)
Perform Casteljau subdivision of a Bezier polynomial.
Definition bezier.h:78
std::vector< Point > bezier_points(const D2< Bezier > &a)
Definition bezier.h:352
Bezier multiply(Bezier const &f, Bezier const &g)
Definition bezier.h:337
Bezier operator*(Bezier const &f, Bezier const &g)
Definition bezier.cpp:221
std::string format_coord_nice(Coord x)
Definition coord.cpp:89
Bezier portion(const Bezier &a, double from, double to)
Definition bezier.cpp:250
Bezier integral(Bezier const &a)
Definition bezier.cpp:294
Bezier derivative(Bezier const &a)
Definition bezier.cpp:282
T bernstein_value_at(double t, T const *c_, unsigned n)
Compute the value of a Bernstein-Bezier polynomial.
Definition bezier.h:55
OptInterval bounds_fast(Bezier const &b)
Definition bezier.cpp:305
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2)
Expand an interval to the image of a Bézier-Bernstein polynomial, assuming it already contains the in...
Definition bezier.cpp:347
SBasis bezier_to_sbasis(Coord const *handles, unsigned order)
std::vector< double > & solutions
Order(Bezier const &b)
Definition bezier.h:180
Order(unsigned o)
Definition bezier.h:181