KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bezier_curves.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef BEZIER_CURVES_H
21#define BEZIER_CURVES_H
22
23#include <vector>
24#include <math/vector2d.h>
25
26template <typename T> class ELLIPSE;
27
34{
35public:
36 BEZIER_POLY( const VECTOR2I& aStart, const VECTOR2I& aCtrl1,
37 const VECTOR2I& aCtrl2, const VECTOR2I& aEnd );
38
39 BEZIER_POLY( const std::vector<VECTOR2I>& aControlPoints );
40
41 BEZIER_POLY( const std::vector<VECTOR2D>& aControlPoints )
42 : m_ctrlPts( aControlPoints )
43 {
44 m_minSegLen = 0.0;
45 }
46
53 void GetPoly( std::vector<VECTOR2I>& aOutput, int aMaxError = 10 );
54 void GetPoly( std::vector<VECTOR2D>& aOutput, double aMaxError = 10.0 );
55
56private:
57
58 void getQuadPoly( std::vector<VECTOR2D>& aOutput, double aMaxError );
59 void getCubicPoly( std::vector<VECTOR2D>& aOutput, double aMaxError );
60
61 int findInflectionPoints( double& aT1, double& aT2 );
63
65
66 void subdivide( double aT, BEZIER_POLY& aLeft, BEZIER_POLY& aRight );
67 void recursiveSegmentation( std::vector<VECTOR2D>& aOutput, double aMaxError );
68
69 void cubicParabolicApprox( std::vector<VECTOR2D>& aOutput, double aMaxError );
70
71 bool isNaN() const;
72
73 bool isFlat( double aMaxError ) const;
74
75 VECTOR2D eval( double t );
76
78
80 std::vector<VECTOR2D> m_ctrlPts;
81};
82
83
84// TODO: Refactor BEZIER_POLY to use BEZIER
85
89template <typename NumericType>
90class BEZIER
91{
92public:
93 BEZIER() = default;
94
95 constexpr BEZIER( const VECTOR2<NumericType>& aStart, const VECTOR2<NumericType>& aC1,
96 const VECTOR2<NumericType>& aC2, const VECTOR2<NumericType>& aEnd ) :
97 Start( aStart ), C1( aC1 ), C2( aC2 ), End( aEnd )
98 {
99 }
100
110 constexpr VECTOR2<NumericType> PointAt( double aT ) const
111 {
112 const double t2 = aT * aT;
113 const double t3 = t2 * aT;
114 const double t_m1 = 1.0 - aT;
115 const double t_m1_2 = t_m1 * t_m1;
116 const double t_m1_3 = t_m1_2 * t_m1;
117
118 return ( t_m1_3 * Start ) + ( 3.0 * aT * t_m1_2 * C1 ) + ( 3.0 * t2 * t_m1 * C2 )
119 + ( t3 * End );
120 }
121
129 constexpr void Split( double aT, BEZIER& aLeft, BEZIER& aRight ) const
130 {
131 const VECTOR2<NumericType> startC1 = Start + aT * ( C1 - Start );
132 const VECTOR2<NumericType> c1C2 = C1 + aT * ( C2 - C1 );
133 const VECTOR2<NumericType> c2End = C2 + aT * ( End - C2 );
134 const VECTOR2<NumericType> leftC2 = startC1 + aT * ( c1C2 - startC1 );
135 const VECTOR2<NumericType> rightC1 = c1C2 + aT * ( c2End - c1C2 );
136 const VECTOR2<NumericType> shared = leftC2 + aT * ( rightC1 - leftC2 );
137
138 aLeft = BEZIER( Start, startC1, leftC2, shared );
139 aRight = BEZIER( shared, rightC1, c2End, End );
140 }
141
145 constexpr BEZIER SubCurve( double aT0, double aT1 ) const
146 {
147 double t0 = aT0;
148 double t1 = aT1;
149
150 if( t0 < 0.0 )
151 t0 = 0.0;
152 else if( t0 > 1.0 )
153 t0 = 1.0;
154
155 if( t1 < 0.0 )
156 t1 = 0.0;
157 else if( t1 > 1.0 )
158 t1 = 1.0;
159
160 if( t1 <= t0 )
161 {
162 const VECTOR2<NumericType> point = PointAt( t0 );
163 return BEZIER( point, point, point, point );
164 }
165
166 if( t0 == 0.0 && t1 == 1.0 )
167 return *this;
168
169 BEZIER left;
171
172 if( t0 == 0.0 )
173 {
174 Split( t1, left, right );
175 return left;
176 }
177
178 if( t1 == 1.0 )
179 {
180 Split( t0, left, right );
181 return right;
182 }
183
184 Split( t1, left, right );
185
186 BEZIER unused;
187 BEZIER subCurve;
188 left.Split( t0 / t1, unused, subCurve );
189
190 return subCurve;
191 }
192
197};
198
202template<typename T>
203void TransformEllipseToBeziers( const ELLIPSE<T>& aEllipse, std::vector<BEZIER<T>>& aBeziers );
204
205#endif // BEZIER_CURVES_H
void TransformEllipseToBeziers(const ELLIPSE< T > &aEllipse, std::vector< BEZIER< T > > &aBeziers)
Transforms an ellipse or elliptical arc into a set of quadratic Bezier curves that approximate it.
Bezier curves to polygon converter.
void recursiveSegmentation(std::vector< VECTOR2D > &aOutput, double aMaxError)
void getQuadPoly(std::vector< VECTOR2D > &aOutput, double aMaxError)
int numberOfInflectionPoints()
double thirdControlPointDeviation()
void cubicParabolicApprox(std::vector< VECTOR2D > &aOutput, double aMaxError)
double m_minSegLen
Control points.
void getCubicPoly(std::vector< VECTOR2D > &aOutput, double aMaxError)
BEZIER_POLY(const VECTOR2I &aStart, const VECTOR2I &aCtrl1, const VECTOR2I &aCtrl2, const VECTOR2I &aEnd)
void subdivide(double aT, BEZIER_POLY &aLeft, BEZIER_POLY &aRight)
bool isFlat(double aMaxError) const
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
int findInflectionPoints(double &aT1, double &aT2)
bool isNaN() const
VECTOR2D eval(double t)
BEZIER_POLY(const std::vector< VECTOR2D > &aControlPoints)
std::vector< VECTOR2D > m_ctrlPts
Generic cubic Bezier representation.
VECTOR2< NumericType > Start
constexpr BEZIER SubCurve(double aT0, double aT1) const
Extract a sub-curve from aT0 to aT1 using de Casteljau subdivision.
VECTOR2< NumericType > C1
BEZIER()=default
VECTOR2< NumericType > C2
constexpr void Split(double aT, BEZIER &aLeft, BEZIER &aRight) const
Split the Bezier curve into two curves at aT using de Casteljau subdivision.
VECTOR2< NumericType > End
constexpr VECTOR2< NumericType > PointAt(double aT) const
Evaluate the Bezier curve at a given t value.
constexpr BEZIER(const VECTOR2< NumericType > &aStart, const VECTOR2< NumericType > &aC1, const VECTOR2< NumericType > &aC2, const VECTOR2< NumericType > &aEnd)
Plain ellipse / elliptical-arc data.
Definition ellipse.h:32
Define a general 2D-vector/point.
Definition vector2d.h:67
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682