vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
basis_sample.cc
Go to the documentation of this file.
1/************************************************************************/
2/* */
3/* vspline - a set of generic tools for creation and evaluation */
4/* of uniform b-splines */
5/* */
6/* Copyright 2017 - 2023 by Kay F. Jahnke */
7/* */
8/* Permission is hereby granted, free of charge, to any person */
9/* obtaining a copy of this software and associated documentation */
10/* files (the "Software"), to deal in the Software without */
11/* restriction, including without limitation the rights to use, */
12/* copy, modify, merge, publish, distribute, sublicense, and/or */
13/* sell copies of the Software, and to permit persons to whom the */
14/* Software is furnished to do so, subject to the following */
15/* conditions: */
16/* */
17/* The above copyright notice and this permission notice shall be */
18/* included in all copies or substantial portions of the */
19/* Software. */
20/* */
21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
23/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
24/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
25/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
26/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
27/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
28/* OTHER DEALINGS IN THE SOFTWARE. */
29/* */
30/************************************************************************/
31
32/// basis_sample.cc - access to the b-spline basis functions
33
34/// Calculate a set of equally-spaced samples of a b-spline basis function
35/// This program takes four parameters on the command line:
36/// - the spline's degree
37/// - x0, the location of the initial sample
38/// - step, the distance from one sample to the next
39/// - normalize - if not zero, result will be normalized
40/// These values are fed to 'sample_basis' (see below), which starts by
41/// calculating the initial sample and then goes 'both ways' to add more
42/// samples. The (optionally normalized) samples are echoed to std::cout.
43/// example: basis_sample 3 .05 .25 1
44
45/// vspline offers access to the b-spline basis functions via a helper
46/// object 'basis_functor'. A good part of the calculation of the basis
47/// function's value can be done beforehand and only depends on the
48/// degree of the basis function. The basis_functor object performs
49/// these calculations once when it's created, subsequent evaluations
50/// are relatively fast and rely on the initially generated state.
51/// For this example, we use long double values - this example is
52/// not about speed, but rather about providing precise values.
53/// The basis_functor object can also evaluate vectorized data,
54/// but in this example we'll only use it's scalar form.
55
56
57#include <deque>
58#include <vector>
59#include <iostream>
60#include <iomanip>
61#include <vspline/vspline.h>
62
63/// 'sample_basis' returns a vector of samples of the basis function
64/// if we have the basis function b(x), it returns these values:
65/// bf ( x - x0 + step * k ) for all k E N,
66/// wherever they are greater than zero. So for X0 = 0 and step = 1,
67/// we get the ordinary unit-spaced sampling of the basis function,
68/// with x0 != 0 and step == 1 a set of weights as it might be
69/// applied to a set of coefficients to evaluate a b-spline, and
70/// with step != 1, we get a set of values which follow the shape
71/// of the basis function with more or less sample points than the
72/// 'normal' unit-spaced sampling. What's surprising is that these
73/// non-unit-step samplings (when multiplied with the step width)
74/// also are (often very) close to a partition of unity.
75
77
78std::vector<long double> sample_basis ( bf_type bfunc ,
79 long double x0 ,
80 long double step ,
81 bool normalize = false )
82{
83 auto y = bfunc ( x0 ) ;
84 auto sum = y ;
85
86 assert ( y > 0 ) ;
87
88 std::deque<long double> accu ;
89 accu.push_back ( y ) ;
90
91 for ( int k = 1 ; ; k++ )
92 {
93 y = bfunc ( x0 - k * step ) ;
94 if ( y <= 0 )
95 break ;
96 accu.push_front ( y ) ;
97 sum += y ;
98 }
99 for ( int k = 1 ; ; k++ )
100 {
101 y = bfunc ( x0 + k * step ) ;
102 if ( y <= 0 )
103 break ;
104 accu.push_back ( y ) ;
105 sum += y ;
106 }
107
108 size_t sz = accu.size() ;
109 std::vector < long double > result ( sz ) ;
110
111 if ( normalize )
112 {
113 for ( size_t i = 0 ; i < sz ; i++ )
114 result[i] = accu[i] / sum ;
115 }
116 else
117 {
118 for ( size_t i = 0 ; i < sz ; i++ )
119 result[i] = accu[i] ;
120 }
121
122 return result ;
123}
124
125int main ( int argc, char * argv[] )
126{
127 if ( argc != 5 )
128 {
129 std::cerr
130 << "use: basis_sample degree(int) x0(float) step(float) normalize(0/1)"
131 << std::endl ;
132 exit ( -1 ) ;
133 }
134
135 int degree = std::atoi ( argv[1] ) ;
136 auto bfunc = bf_type ( degree ) ;
137 auto x0 = std::atof ( argv[2] ) ;
138 auto step = std::atof ( argv[3] ) ;
139 bool normalize = std::atoi ( argv[4] ) ;
140
141 auto sample = sample_basis ( bfunc , x0 , step , normalize ) ;
142
143 std::cout << std::fixed << std::showpoint
144 << std::setprecision
145 (std::numeric_limits<long double>::max_digits10) ;
146
147 for ( auto & e : sample )
148 std::cout << e << std::endl ;
149}
int main(int argc, char *argv[])
vspline::basis_functor< long double > bf_type
basis_sample.cc - access to the b-spline basis functions
Definition: basis_sample.cc:76
std::vector< long double > sample_basis(bf_type bfunc, long double x0, long double step, bool normalize=false)
Definition: basis_sample.cc:78
basis_functor is an object producing the b-spline basis function value for given arguments,...
Definition: basis.h:402
includes all headers from vspline (most of them indirectly)