Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
bezier-curve.h
Go to the documentation of this file.
1/*
5 * Authors:
6 * MenTaLguY <mental@rydia.net>
7 * Marco Cecchetti <mrcekets at gmail.com>
8 * Krzysztof KosiƄski <tweenk.pl@gmail.com>
9 *
10 * Copyright 2007-2011 Authors
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it either under the terms of the GNU Lesser General Public
14 * License version 2.1 as published by the Free Software Foundation
15 * (the "LGPL") or, at your option, under the terms of the Mozilla
16 * Public License Version 1.1 (the "MPL"). If you do not alter this
17 * notice, a recipient may use your version of this file under either
18 * the MPL or the LGPL.
19 *
20 * You should have received a copy of the LGPL along with this library
21 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * You should have received a copy of the MPL along with this library
24 * in the file COPYING-MPL-1.1
25 *
26 * The contents of this file are subject to the Mozilla Public License
27 * Version 1.1 (the "License"); you may not use this file except in
28 * compliance with the License. You may obtain a copy of the License at
29 * http://www.mozilla.org/MPL/
30 *
31 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
32 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
33 * the specific language governing rights and limitations.
34 */
35
36#ifndef LIB2GEOM_SEEN_BEZIER_CURVE_H
37#define LIB2GEOM_SEEN_BEZIER_CURVE_H
38
39#include <2geom/curve.h>
40#include <2geom/sbasis-curve.h> // for non-native winding method
41#include <2geom/bezier.h>
42#include <2geom/transforms.h>
43
44namespace Geom
45{
46
47class BezierCurve : public Curve {
48protected:
51 BezierCurve(Bezier const &x, Bezier const &y) : inner(x, y) {}
52 BezierCurve(std::vector<Point> const &pts);
53
54public:
55 explicit BezierCurve(D2<Bezier> const &b) : inner(b) {}
56
59
61 unsigned order() const { return inner[X].order(); }
63 unsigned size() const { return inner[X].order() + 1; }
67 Point controlPoint(unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
68 Point operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
71 std::vector<Point> controlPoints() const { return bezier_points(inner); }
72 D2<Bezier> const &fragment() const { return inner; }
73
77 void setPoint(unsigned ix, Point const &v) {
78 inner[X][ix] = v[X];
79 inner[Y][ix] = v[Y];
80 }
85 virtual void setPoints(std::vector<Point> const &ps) {
86 // must be virtual, because HLineSegment will need to redefine it
87 if (ps.size() != order() + 1)
88 THROW_LOGICALERROR("BezierCurve::setPoints: incorrect number of points in vector");
89 for(unsigned i = 0; i <= order(); i++) {
90 setPoint(i, ps[i]);
91 }
92 }
94
97
101 static BezierCurve *create(std::vector<Point> const &pts);
103
104 // implementation of virtual methods goes here
105 Point initialPoint() const override { return inner.at0(); }
106 Point finalPoint() const override { return inner.at1(); }
107 bool isDegenerate() const override;
108 bool isLineSegment() const override;
109 void setInitial(Point const &v) override { setPoint(0, v); }
110 void setFinal(Point const &v) override { setPoint(order(), v); }
111 Rect boundsFast() const override { return *bounds_fast(inner); }
112 Rect boundsExact() const override { return *bounds_exact(inner); }
113 void expandToTransformed(Rect &bbox, Affine const &transform) const override;
114 OptRect boundsLocal(OptInterval const &i, unsigned deg) const override {
115 if (!i) return OptRect();
116 if(i->min() == 0 && i->max() == 1) return boundsFast();
117 if(deg == 0) return bounds_local(inner, i);
118 // TODO: UUUUUUGGGLLY
119 if(deg == 1 && order() > 1) return OptRect(bounds_local(Geom::derivative(inner[X]), i),
121 return OptRect();
122 }
123 Curve *duplicate() const override {
124 return new BezierCurve(*this);
125 }
126
127 Curve *portion(Coord f, Coord t) const override;
128
129 Curve *reverse() const override {
130 return new BezierCurve(Geom::reverse(inner));
131 }
132
133 using Curve::operator*=;
134 void operator*=(Translate const &tr) override {
135 for (unsigned i = 0; i < size(); ++i) {
136 inner[X][i] += tr[X];
137 inner[Y][i] += tr[Y];
138 }
139 }
140 void operator*=(Scale const &s) override {
141 for (unsigned i = 0; i < size(); ++i) {
142 inner[X][i] *= s[X];
143 inner[Y][i] *= s[Y];
144 }
145 }
146 void operator*=(Affine const &m) override {
147 for (unsigned i = 0; i < size(); ++i) {
148 setPoint(i, controlPoint(i) * m);
149 }
150 }
151
152 Curve *derivative() const override {
154 }
155 int degreesOfFreedom() const override {
156 return 2 * (order() + 1);
157 }
158 std::vector<Coord> roots(Coord v, Dim2 d) const override {
159 return (inner[d] - v).roots();
160 }
161 Coord nearestTime(Point const &p, Coord from = 0, Coord to = 1) const override;
162 Coord length(Coord tolerance) const override;
163 std::vector<CurveIntersection> intersect(Curve const &other, Coord eps = EPSILON) const override;
164 Point pointAt(Coord t) const override { return inner.pointAt(t); }
165 std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const override {
166 return inner.valueAndDerivatives(t, n);
167 }
168 Coord valueAt(Coord t, Dim2 d) const override { return inner[d].valueAt(t); }
169 D2<SBasis> toSBasis() const override {return inner.toSBasis(); }
170 bool isNear(Curve const &c, Coord precision) const override;
171 void feed(PathSink &sink, bool) const override;
172 std::vector<Coord> timesWithRadiusOfCurvature(double radius) const;
173
174protected:
175 bool _equalTo(Curve const &c) const override;
176};
177
178template <unsigned degree>
180 : public BezierCurve
181{
182 template <unsigned required_degree>
184
185public:
188
192
194 explicit BezierCurveN(D2<Bezier > const &x) {
195 inner = x;
196 }
197
200 inner = D2<Bezier > (x,y);
201 }
202
204 BezierCurveN(std::vector<Point> const &points) {
205 unsigned ord = points.size() - 1;
206 if (ord != degree) THROW_LOGICALERROR("BezierCurve<degree> does not match number of points");
207 for (unsigned d = 0; d < 2; ++d) {
208 inner[d] = Bezier(Bezier::Order(ord));
209 for(unsigned i = 0; i <= ord; i++)
210 inner[d][i] = points[i][d];
211 }
212 }
213
216 assert_degree<1>(this);
217 for(unsigned d = 0; d < 2; d++)
218 inner[d] = Bezier(c0[d], c1[d]);
219 }
220
223 assert_degree<2>(this);
224 for(unsigned d = 0; d < 2; d++)
225 inner[d] = Bezier(c0[d], c1[d], c2[d]);
226 }
227
230 assert_degree<3>(this);
231 for(unsigned d = 0; d < 2; d++)
232 inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
233 }
234
235 // default copy
236 // default assign
237
239
245 std::pair<BezierCurveN, BezierCurveN> subdivide(Coord t) const {
246 std::pair<Bezier, Bezier> sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
247 return std::make_pair(
248 BezierCurveN(sx.first, sy.first),
249 BezierCurveN(sx.second, sy.second));
250 }
251
252 bool isDegenerate() const override {
254 }
255
256 bool isLineSegment() const override {
257 if constexpr (degree == 1) {
258 return true;
259 } else {
261 }
262 }
263
264 Curve *duplicate() const override {
265 return new BezierCurveN(*this);
266 }
267 Curve *portion(Coord f, Coord t) const override {
268 if (degree == 1) {
269 return new BezierCurveN<1>(pointAt(f), pointAt(t));
270 } else {
271 return new BezierCurveN(Geom::portion(inner, f, t));
272 }
273 }
274 Curve *reverse() const override {
275 if (degree == 1) {
276 return new BezierCurveN<1>(finalPoint(), initialPoint());
277 } else {
278 return new BezierCurveN(Geom::reverse(inner));
279 }
280 }
281 Curve *derivative() const override;
282
283 Coord nearestTime(Point const &p, Coord from = 0, Coord to = 1) const override {
284 return BezierCurve::nearestTime(p, from, to);
285 }
286 std::vector<CurveIntersection> intersect(Curve const &other, Coord eps = EPSILON) const override {
287 // call super. this is implemented only to allow specializations
288 return BezierCurve::intersect(other, eps);
289 }
290 int winding(Point const &p) const override {
291 return Curve::winding(p);
292 }
293 void feed(PathSink &sink, bool moveto_initial) const override {
294 // call super. this is implemented only to allow specializations
295 BezierCurve::feed(sink, moveto_initial);
296 }
297 void expandToTransformed(Rect &bbox, Affine const &transform) const override {
298 // call super. this is implemented only to allow specializations
300 }
301};
302
303// BezierCurveN<0> is meaningless; specialize it out
304template<> class BezierCurveN<0> : public BezierCurveN<1> { private: BezierCurveN();};
305
311
315
319
320template <unsigned degree>
321inline
325
326// optimized specializations
327template <> inline bool BezierCurveN<1>::isDegenerate() const {
328 return inner[X][0] == inner[X][1] && inner[Y][0] == inner[Y][1];
329}
330template <> inline bool BezierCurveN<1>::isLineSegment() const { return true; }
333template <> std::vector<CurveIntersection> BezierCurveN<1>::intersect(Curve const &, Coord) const;
334template <> std::vector<CurveIntersection> BezierCurveN<2>::intersect(Curve const &, Coord) const;
335template <> std::vector<CurveIntersection> BezierCurveN<3>::intersect(Curve const &, Coord) const;
336template <> int BezierCurveN<1>::winding(Point const &) const;
337template <> void BezierCurveN<1>::feed(PathSink &sink, bool moveto_initial) const;
338template <> void BezierCurveN<2>::feed(PathSink &sink, bool moveto_initial) const;
339template <> void BezierCurveN<3>::feed(PathSink &sink, bool moveto_initial) const;
340template <> void BezierCurveN<1>::expandToTransformed(Rect &bbox, Affine const &transform) const;
341template <> void BezierCurveN<2>::expandToTransformed(Rect &bbox, Affine const &transform) const;
342template <> void BezierCurveN<3>::expandToTransformed(Rect &bbox, Affine const &transform) const;
343
344inline Point middle_point(LineSegment const& _segment) {
345 return ( _segment.initialPoint() + _segment.finalPoint() ) / 2;
346}
347
348inline Coord length(LineSegment const& seg) {
349 return distance(seg.initialPoint(), seg.finalPoint());
350}
351
352Coord bezier_length(std::vector<Point> const &points, Coord tolerance = 0.01);
353Coord bezier_length(Point p0, Point p1, Point p2, Coord tolerance = 0.01);
354Coord bezier_length(Point p0, Point p1, Point p2, Point p3, Coord tolerance = 0.01);
355
356} // end namespace Geom
357
358#endif // LIB2GEOM_SEEN_BEZIER_CURVE_H
359
360/*
361 Local Variables:
362 mode:c++
363 c-file-style:"stroustrup"
364 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
365 indent-tabs-mode:nil
366 fill-column:99
367 End:
368*/
369// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Abstract curve type.
pair< double, double > Point
Definition parser.cpp:7
Bernstein-Bezier polynomial.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Bezier curve with compile-time specified order.
bool isDegenerate() const override
Check whether the curve has exactly zero length.
std::pair< BezierCurveN, BezierCurveN > subdivide(Coord t) const
Divide a Bezier curve into two curves.
BezierCurveN(Point c0, Point c1)
Construct a linear segment from its endpoints.
Curve * portion(Coord f, Coord t) const override
Create a curve that corresponds to a part of this curve.
Curve * duplicate() const override
Create an exact copy of this curve.
void feed(PathSink &sink, bool moveto_initial) const override
Feed the curve to a PathSink.
BezierCurveN(Point c0, Point c1, Point c2)
Construct a quadratic Bezier curve from its control points.
BezierCurveN(D2< Bezier > const &x)
Construct from 2D Bezier polynomial.
std::vector< CurveIntersection > intersect(Curve const &other, Coord eps=EPSILON) const override
Compute intersections with another curve.
BezierCurveN(Bezier x, Bezier y)
Construct from two 1D Bezier polynomials of the same order.
int winding(Point const &p) const override
Compute the partial winding number of this curve.
static void assert_degree(BezierCurveN< required_degree > const *)
Coord nearestTime(Point const &p, Coord from=0, Coord to=1) const override
Compute a time value at which the curve comes closest to a specified point.
bool isLineSegment() const override
Return false if there are at least 3 distinct control points, true otherwise.
Curve * derivative() const override
Create a derivative of this curve.
BezierCurveN()
Construct a Bezier curve of the specified order with all points zero.
void expandToTransformed(Rect &bbox, Affine const &transform) const override
Expand the given rectangle to include the transformed curve, assuming it already contains its initial...
BezierCurveN(Point c0, Point c1, Point c2, Point c3)
Construct a cubic Bezier curve from its control points.
Curve * reverse() const override
Create a reversed version of this curve.
BezierCurveN(std::vector< Point > const &points)
Construct a Bezier curve from a vector of its control points.
Two-dimensional Bezier curve of arbitrary order.
Curve * duplicate() const override
Create an exact copy of this curve.
bool isLineSegment() const override
Return false if there are at least 3 distinct control points, true otherwise.
OptRect boundsLocal(OptInterval const &i, unsigned deg) const override
BezierCurve(D2< Bezier > const &b)
bool isDegenerate() const override
Check whether the curve has exactly zero length.
Rect boundsExact() const override
Compute the curve's exact bounding box.
void setInitial(Point const &v) override
Change the starting point of the curve.
std::vector< Coord > timesWithRadiusOfCurvature(double radius) const
Computes the times where the radius of curvature of the bezier curve equals the given radius.
Rect boundsFast() const override
Quickly compute the curve's approximate bounding box.
void operator*=(Scale const &s) override
void operator*=(Translate const &tr) override
D2< Bezier > inner
D2< SBasis > toSBasis() const override
Convert the curve to a symmetric power basis polynomial.
unsigned size() const
Get the number of control points.
Curve * derivative() const override
Create a derivative of this curve.
D2< Bezier > const & fragment() const
Coord length(Coord tolerance) const override
Compute the arc length of this curve.
bool _equalTo(Curve const &c) const override
Coord nearestTime(Point const &p, Coord from=0, Coord to=1) const override
Compute a time value at which the curve comes closest to a specified point.
void operator*=(Affine const &m) override
virtual void setPoints(std::vector< Point > const &ps)
Set new control points.
Coord valueAt(Coord t, Dim2 d) const override
Evaluate one of the coordinates at the specified time value.
Point finalPoint() const override
Retrieve the end of the curve.
bool isNear(Curve const &c, Coord precision) const override
Test whether two curves are approximately the same.
Point pointAt(Coord t) const override
Evaluate the curve at a specified time value.
void feed(PathSink &sink, bool) const override
Feed the curve to a PathSink.
Point initialPoint() const override
Retrieve the start of the curve.
BezierCurve(Bezier const &x, Bezier const &y)
void setFinal(Point const &v) override
Change the ending point of the curve.
std::vector< CurveIntersection > intersect(Curve const &other, Coord eps=EPSILON) const override
Compute intersections with another curve.
int degreesOfFreedom() const override
Return the number of independent parameters required to represent all variations of this curve.
Curve * reverse() const override
Create a reversed version of this curve.
std::vector< Coord > roots(Coord v, Dim2 d) const override
Computes time values at which the curve intersects an axis-aligned line.
void setPoint(unsigned ix, Point const &v)
Modify a control point.
Point controlPoint(unsigned ix) const
Access control points of the curve.
std::vector< Point > controlPoints() const
Get the control points.
Point operator[](unsigned ix) const
Curve * portion(Coord f, Coord t) const override
Create a curve that corresponds to a part of this curve.
unsigned order() const
Get the order of the Bezier curve.
void expandToTransformed(Rect &bbox, Affine const &transform) const override
Expand the given rectangle to include the transformed curve, assuming it already contains its initial...
std::vector< Point > pointAndDerivatives(Coord t, unsigned n) const override
Evaluate the curve and its derivatives.
Polynomial in Bernstein-Bezier basis.
Definition bezier.h:126
Abstract continuous curve on a plane defined on [0,1].
Definition curve.h:78
virtual int winding(Point const &p) const
Compute the partial winding number of this curve.
Definition curve.cpp:61
void transform(Affine const &m)
Transform this curve by an affine transformation.
Definition curve.h:193
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
Range of real numbers that can be empty.
Definition interval.h:199
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Callback interface for processing path data.
Definition path-sink.h:56
Two-dimensional point that doubles as a vector.
Definition point.h:66
Axis aligned, non-empty rectangle.
Definition rect.h:92
Scaling from the origin.
Definition transforms.h:150
Translation by a vector.
Definition transforms.h:115
double inner(valarray< double > const &x, valarray< double > const &y)
double c[8][4]
BezierCurveN< 3 > CubicBezier
Cubic (order 3) Bezier curve.
BezierCurveN< 1 > LineSegment
Line segment.
BezierCurveN< 2 > QuadraticBezier
Quadratic (order 2) Bezier curve.
Dim2
2D axis enumeration (X or Y).
Definition coord.h:48
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
constexpr Coord EPSILON
Default "acceptably small" value.
Definition coord.h:84
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Various utility functions.
Definition affine.h:22
Coord length(LineSegment const &seg)
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
std::vector< Point > bezier_points(const D2< Bezier > &a)
Definition bezier.h:352
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
Coord bezier_length(std::vector< Point > const &points, Coord tolerance=0.01)
Compute the length of a bezier curve given by a vector of its control points.
Bezier portion(const Bezier &a, double from, double to)
Definition bezier.cpp:250
Bezier derivative(Bezier const &a)
Definition bezier.cpp:282
OptInterval bounds_fast(Bezier const &b)
Definition bezier.cpp:305
Point middle_point(LineSegment const &_segment)
Symmetric power basis curve.
size_t degree
std::unique_ptr< Toolbar >(* create)()
Definition toolbars.cpp:56
Affine transformation classes.