File: bezier_polynomial.qbk

package info (click to toggle)
scipy 1.16.0-1exp7
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 234,820 kB
  • sloc: cpp: 503,145; python: 344,611; ansic: 195,638; javascript: 89,566; fortran: 56,210; cs: 3,081; f90: 1,150; sh: 848; makefile: 785; pascal: 284; csh: 135; lisp: 134; xml: 56; perl: 51
file content (175 lines) | stat: -rw-r--r-- 6,775 bytes parent folder | download | duplicates (9)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
[/
  Copyright 2021 Nick Thompson, John Maddock

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt).
]

[section:bezier_polynomial Bezier Polynomials]

[heading Synopsis]

``
#include <boost/math/interpolators/bezier_polynomials.hpp>

namespace boost::math::interpolators {

    template<RandomAccessContainer>
    class bezier_polynomial
    {
    public:
        using Point = typename RandomAccessContainer::value_type;
        using Real = typename Point::value_type;
        using Z = typename RandomAccessContainer::size_type;

        bezier_polynomial(RandomAccessContainer&& control_points);

        inline Point operator()(Real t) const;

        inline Point prime(Real t) const;

        void edit_control_point(Point cont & p, Z index);

        RandomAccessContainer const & control_points() const;

        friend std::ostream& operator<<(std::ostream& out, bezier_polynomial<RandomAccessContainer> const & bp);
    };

}
``

[heading Description]

B[eacute]zier polynomials are curves smooth curves which approximate a set of control points.
They are commonly used in computer-aided geometric design.
A basic usage is demonstrated below:

    std::vector<std::array<double, 3>> control_points(4);
    control_points[0] = {0,0,0};
    control_points[1] = {1,0,0};
    control_points[2] = {0,1,0};
    control_points[3] = {0,0,1};
    auto bp = bezier_polynomial(std::move(control_points));
    // Interpolate at t = 0.1:
    std::array<double, 3> point = bp(0.1);

The support of the interpolant is [0,1], and an error message will be written if attempting to evaluate the polynomial outside of these bounds.
At least two points must be passed; creating a polynomial of degree 1.

Control points may be modified via `edit_control_point`, for example:

    std::array<double, 3> endpoint{0,1,1};
    bp.edit_control_point(endpoint, 3);

This replaces the last control point with `endpoint`.

Tangents are computed with the `.prime` member function, and the control points may be referenced with the `.control_points` member function.

The overloaded operator /<</ is disappointing: The control points are simply printed.
Rendering the Bezier and its convex hull seems to be the best "print" statement for it, but this is essentially impossible in modern terminals.

[heading Caveats]

Do not confuse the Bezier polynomial with a Bezier spline.
A Bezier spline has a fixed polynomial order and subdivides the curve into low-order polynomial segments.
/This is not a spline!/
Passing /n/ control points to the `bezier_polynomial` class creates a polynomial of degree n-1, whereas a Bezier spline has a fixed order independent of the number of control points.

Requires C++17 and support for threadlocal storage.


[heading Performance]

The following performance numbers were generated for evaluating the Bezier-polynomial.
The evaluation of the interpolant is [bigo](/N/^2), as expected from de Casteljau's algorithm.


    Run on (16 X 2300 MHz CPU s)
    CPU Caches:
    L1 Data 32 KiB (x8)
    L1 Instruction 32 KiB (x8)
    L2 Unified 256 KiB (x8)
    L3 Unified 16384 KiB (x1)
    ---------------------------------------------------------
    Benchmark                              Time           CPU
    ---------------------------------------------------------
    BezierPolynomial<double>/2        9.07 ns         9.06 ns
    BezierPolynomial<double>/3        13.2 ns         13.1 ns
    BezierPolynomial<double>/4        17.5 ns         17.5 ns
    BezierPolynomial<double>/5        21.7 ns         21.7 ns
    BezierPolynomial<double>/6        27.4 ns         27.4 ns
    BezierPolynomial<double>/7        32.4 ns         32.3 ns
    BezierPolynomial<double>/8        40.4 ns         40.4 ns
    BezierPolynomial<double>/9        51.9 ns         51.8 ns
    BezierPolynomial<double>/10       65.9 ns         65.9 ns
    BezierPolynomial<double>/11       79.1 ns         79.1 ns
    BezierPolynomial<double>/12       83.0 ns         82.9 ns
    BezierPolynomial<double>/13        108 ns          108 ns
    BezierPolynomial<double>/14        119 ns          119 ns
    BezierPolynomial<double>/15        140 ns          140 ns
    BezierPolynomial<double>/16        137 ns          137 ns
    BezierPolynomial<double>/17        151 ns          151 ns
    BezierPolynomial<double>/18        171 ns          171 ns
    BezierPolynomial<double>/19        194 ns          193 ns
    BezierPolynomial<double>/20        213 ns          213 ns
    BezierPolynomial<double>/21        220 ns          220 ns
    BezierPolynomial<double>/22        260 ns          260 ns
    BezierPolynomial<double>/23        266 ns          266 ns
    BezierPolynomial<double>/24        293 ns          292 ns
    BezierPolynomial<double>/25        319 ns          319 ns
    BezierPolynomial<double>/26        336 ns          335 ns
    BezierPolynomial<double>/27        370 ns          370 ns
    BezierPolynomial<double>/28        429 ns          429 ns
    BezierPolynomial<double>/29        443 ns          443 ns
    BezierPolynomial<double>/30        421 ns          421 ns
    BezierPolynomial<double>_BigO       0.52 N^2        0.51 N^2  

The Casteljau recurrence is indeed quadratic in the number of control points, and is chosen for numerical stability.
See /Bezier and B-spline Techniques/, section 2.3 for a method to Hornerize the Berstein polynomials and perhaps produce speedups.


[heading Point types]

The `Point` type must satisfy certain conceptual requirements which are discussed in the documentation of the Catmull-Rom curve.
However, we reiterate them here:

    template<class Real>
    class mypoint3d
    {
    public:
        // Must define a value_type:
        typedef Real value_type;

        // Regular constructor--need not be of this form.
        mypoint3d(Real x, Real y, Real z) {m_vec[0] = x; m_vec[1] = y; m_vec[2] = z; }

        // Must define a default constructor:
        mypoint3d() {}

        // Must define array access:
        Real operator[](size_t i) const
        {
            return m_vec[i];
        }

        // Must define array element assignment:
        Real& operator[](size_t i)
        {
            return m_vec[i];
        }

    private:
        std::array<Real, 3> m_vec;
    };

These conditions are satisfied by both `std::array` and `std::vector`.


[heading References]

* Rainer Kress, ['Numerical Analysis], Springer, 1998
* David Salomon, ['Curves and Surfaces for Computer Graphics], Springer, 2005
* Prautzsch, Hartmut, Wolfgang Boehm, and Marco Paluszny. ['Bézier and B-spline techniques]. Springer Science & Business Media, 2002.

[endsect] [/section:bezier_polynomials Bezier Polynomials]