Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sbasis.h
Go to the documentation of this file.
1/*
4 * Authors:
5 * Nathan Hurst <njh@mail.csse.monash.edu.au>
6 * Michael Sloan <mgsloan@gmail.com>
7 *
8 * Copyright (C) 2006-2007 authors
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it either under the terms of the GNU Lesser General Public
12 * License version 2.1 as published by the Free Software Foundation
13 * (the "LGPL") or, at your option, under the terms of the Mozilla
14 * Public License Version 1.1 (the "MPL"). If you do not alter this
15 * notice, a recipient may use your version of this file under either
16 * the MPL or the LGPL.
17 *
18 * You should have received a copy of the LGPL along with this library
19 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * You should have received a copy of the MPL along with this library
22 * in the file COPYING-MPL-1.1
23 *
24 * The contents of this file are subject to the Mozilla Public License
25 * Version 1.1 (the "License"); you may not use this file except in
26 * compliance with the License. You may obtain a copy of the License at
27 * http://www.mozilla.org/MPL/
28 *
29 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
30 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
31 * the specific language governing rights and limitations.
32 */
33
34#ifndef LIB2GEOM_SEEN_SBASIS_H
35#define LIB2GEOM_SEEN_SBASIS_H
36#include <cassert>
37#include <iostream>
38#include <utility>
39#include <vector>
40
41#include <2geom/linear.h>
42#include <2geom/interval.h>
43#include <2geom/utils.h>
44#include <2geom/exception.h>
45
46//#define USE_SBASISN 1
47
48
49#if defined(USE_SBASIS_OF)
50
51#include "sbasis-of.h"
52
53#elif defined(USE_SBASISN)
54
55#include "sbasisN.h"
56namespace Geom{
57
58/*** An empty SBasis is identically 0. */
59class SBasis : public SBasisN<1>;
60
61};
62#else
63
64namespace Geom {
65
70class SBasis {
71 std::vector<Linear> d;
72 void push_back(Linear const&l) { d.push_back(l); }
73
74public:
75 // As part of our migration away from SBasis isa vector we provide this minimal set of vector interface methods.
76 size_t size() const {return d.size();}
77 typedef std::vector<Linear>::iterator iterator;
78 typedef std::vector<Linear>::const_iterator const_iterator;
79 Linear operator[](unsigned i) const {
80 return d[i];
81 }
82 Linear& operator[](unsigned i) { return d.at(i); }
83 const_iterator begin() const { return d.begin();}
84 const_iterator end() const { return d.end();}
85 iterator begin() { return d.begin();}
86 iterator end() { return d.end();}
87 bool empty() const { return d.size() == 1 && d[0][0] == 0 && d[0][1] == 0; }
88 Linear &back() {return d.back();}
89 Linear const &back() const {return d.back();}
90 void pop_back() {
91 if (d.size() > 1) {
92 d.pop_back();
93 } else {
94 d[0][0] = 0;
95 d[0][1] = 0;
96 }
97 }
98 void resize(unsigned n) { d.resize(std::max<unsigned>(n, 1));}
99 void resize(unsigned n, Linear const& l) { d.resize(std::max<unsigned>(n, 1), l);}
100 void reserve(unsigned n) { d.reserve(n);}
101 void clear() {
102 d.resize(1);
103 d[0][0] = 0;
104 d[0][1] = 0;
105 }
106 void insert(iterator before, const_iterator src_begin, const_iterator src_end) { d.insert(before, src_begin, src_end);}
107 Linear& at(unsigned i) { return d.at(i);}
108 //void insert(Linear* before, int& n, Linear const &l) { d.insert(std::vector<Linear>::iterator(before), n, l);}
109 bool operator==(SBasis const&B) const { return d == B.d;}
110 bool operator!=(SBasis const&B) const { return d != B.d;}
111
113 : d(1, Linear(0, 0))
114 {}
115 explicit SBasis(double a)
116 : d(1, Linear(a, a))
117 {}
118 explicit SBasis(double a, double b)
119 : d(1, Linear(a, b))
120 {}
121 SBasis(SBasis const &a)
122 : d(a.d)
123 {}
124 SBasis(std::vector<Linear> ls)
125 : d(std::move(ls))
126 {}
127 SBasis(Linear const &bo)
128 : d(1, bo)
129 {}
131 : d(1, bo ? *bo : Linear(0, 0))
132 {}
133 explicit SBasis(size_t n, Linear const&l) : d(n, l) {}
134
135 SBasis(Coord c0, Coord c1, Coord c2, Coord c3)
136 : d(2)
137 {
138 d[0][0] = c0;
139 d[1][0] = c1;
140 d[1][1] = c2;
141 d[0][1] = c3;
142 }
143 SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5)
144 : d(3)
145 {
146 d[0][0] = c0;
147 d[1][0] = c1;
148 d[2][0] = c2;
149 d[2][1] = c3;
150 d[1][1] = c4;
151 d[0][1] = c5;
152 }
153 SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5,
154 Coord c6, Coord c7)
155 : d(4)
156 {
157 d[0][0] = c0;
158 d[1][0] = c1;
159 d[2][0] = c2;
160 d[3][0] = c3;
161 d[3][1] = c4;
162 d[2][1] = c5;
163 d[1][1] = c6;
164 d[0][1] = c7;
165 }
166 SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5,
167 Coord c6, Coord c7, Coord c8, Coord c9)
168 : d(5)
169 {
170 d[0][0] = c0;
171 d[1][0] = c1;
172 d[2][0] = c2;
173 d[3][0] = c3;
174 d[4][0] = c4;
175 d[4][1] = c5;
176 d[3][1] = c6;
177 d[2][1] = c7;
178 d[1][1] = c8;
179 d[0][1] = c9;
180 }
181
182 // construct from a sequence of coefficients
183 template <typename Iter>
184 SBasis(Iter first, Iter last) {
185 assert(std::distance(first, last) % 2 == 0);
186 assert(std::distance(first, last) >= 2);
187 for (; first != last; ++first) {
188 --last;
189 push_back(Linear(*first, *last));
190 }
191 }
192
193 //IMPL: FragmentConcept
194 typedef double output_type;
195 inline bool isZero(double eps=EPSILON) const {
196 assert(size() > 0);
197 for(unsigned i = 0; i < size(); i++) {
198 if(!(*this)[i].isZero(eps)) return false;
199 }
200 return true;
201 }
202 inline bool isConstant(double eps=EPSILON) const {
203 assert(size() > 0);
204 if(!(*this)[0].isConstant(eps)) return false;
205 for (unsigned i = 1; i < size(); i++) {
206 if(!(*this)[i].isZero(eps)) return false;
207 }
208 return true;
209 }
210
211 bool isFinite() const;
212 inline Coord at0() const { return (*this)[0][0]; }
213 inline Coord &at0() { return (*this)[0][0]; }
214 inline Coord at1() const { return (*this)[0][1]; }
215 inline Coord &at1() { return (*this)[0][1]; }
216
217 int degreesOfFreedom() const { return size()*2;}
218
219 double valueAt(double t) const {
220 assert(size() > 0);
221 double s = t*(1-t);
222 double p0 = 0, p1 = 0;
223 for(unsigned k = size(); k > 0; k--) {
224 const Linear &lin = (*this)[k-1];
225 p0 = p0*s + lin[0];
226 p1 = p1*s + lin[1];
227 }
228 return (1-t)*p0 + t*p1;
229 }
230 //double valueAndDerivative(double t, double &der) const {
231 //}
232 double operator()(double t) const {
233 return valueAt(t);
234 }
235
236 std::vector<double> valueAndDerivatives(double t, unsigned n) const;
237
238 SBasis toSBasis() const { return SBasis(*this); }
239
240 double tailError(unsigned tail) const;
241
242// compute f(g)
243 SBasis operator()(SBasis const & g) const;
244
245//MUTATOR PRISON
246 //remove extra zeros
247 void normalize() {
248 while(size() > 1 && back().isZero(0))
249 pop_back();
250 }
251
252 void truncate(unsigned k) { if(k < size()) resize(std::max<size_t>(k, 1)); }
253private:
254 void derive(); // in place version
255};
256
257//TODO: figure out how to stick this in linear, while not adding an sbasis dep
258inline SBasis Linear::toSBasis() const { return SBasis(*this); }
259
260//implemented in sbasis-roots.cpp
262OptInterval bounds_fast(SBasis const &a, int order = 0);
263OptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0);
264
271inline SBasis reverse(SBasis const &a) {
272 SBasis result(a.size(), Linear());
273
274 for(unsigned k = 0; k < a.size(); k++)
275 result[k] = reverse(a[k]);
276 return result;
277}
278
279//IMPL: ScalableConcept
280inline SBasis operator-(const SBasis& p) {
281 if(p.isZero()) return SBasis();
282 SBasis result(p.size(), Linear());
283
284 for(unsigned i = 0; i < p.size(); i++) {
285 result[i] = -p[i];
286 }
287 return result;
288}
289SBasis operator*(SBasis const &a, double k);
290inline SBasis operator*(double k, SBasis const &a) { return a*k; }
291inline SBasis operator/(SBasis const &a, double k) { return a*(1./k); }
292SBasis& operator*=(SBasis& a, double b);
293inline SBasis& operator/=(SBasis& a, double b) { return (a*=(1./b)); }
294
295//IMPL: AddableConcept
296SBasis operator+(const SBasis& a, const SBasis& b);
297SBasis operator-(const SBasis& a, const SBasis& b);
298SBasis& operator+=(SBasis& a, const SBasis& b);
299SBasis& operator-=(SBasis& a, const SBasis& b);
300
301//TODO: remove?
302/*inline SBasis operator+(const SBasis & a, Linear const & b) {
303 if(b.isZero()) return a;
304 if(a.isZero()) return b;
305 SBasis result(a);
306 result[0] += b;
307 return result;
308}
309inline SBasis operator-(const SBasis & a, Linear const & b) {
310 if(b.isZero()) return a;
311 SBasis result(a);
312 result[0] -= b;
313 return result;
314}
315inline SBasis& operator+=(SBasis& a, const Linear& b) {
316 if(a.isZero())
317 a.push_back(b);
318 else
319 a[0] += b;
320 return a;
321}
322inline SBasis& operator-=(SBasis& a, const Linear& b) {
323 if(a.isZero())
324 a.push_back(-b);
325 else
326 a[0] -= b;
327 return a;
328 }*/
329
330//IMPL: OffsetableConcept
331inline SBasis operator+(const SBasis & a, double b) {
332 if(a.isZero()) return Linear(b, b);
333 SBasis result(a);
334 result[0] += b;
335 return result;
336}
337inline SBasis operator-(const SBasis & a, double b) {
338 if(a.isZero()) return Linear(-b, -b);
339 SBasis result(a);
340 result[0] -= b;
341 return result;
342}
343inline SBasis& operator+=(SBasis& a, double b) {
344 if(a.isZero())
345 a = SBasis(Linear(b,b));
346 else
347 a[0] += b;
348 return a;
349}
350inline SBasis& operator-=(SBasis& a, double b) {
351 if(a.isZero())
352 a = SBasis(Linear(-b,-b));
353 else
354 a[0] -= b;
355 return a;
356}
357
358SBasis shift(SBasis const &a, int sh);
359SBasis shift(Linear const &a, int sh);
360
361inline SBasis truncate(SBasis const &a, unsigned terms) {
362 SBasis c;
363 c.insert(c.begin(), a.begin(), a.begin() + std::min(terms, (unsigned)a.size()));
364 return c;
365}
366
367SBasis multiply(SBasis const &a, SBasis const &b);
368// This performs a multiply and accumulate operation in about the same time as multiply. return a*b + c
369SBasis multiply_add(SBasis const &a, SBasis const &b, SBasis c);
370
371SBasis integral(SBasis const &c);
372SBasis derivative(SBasis const &a);
373
374SBasis sqrt(SBasis const &a, int k);
375
376// return a kth order approx to 1/a)
377SBasis reciprocal(Linear const &a, int k);
378SBasis divide(SBasis const &a, SBasis const &b, int k);
379
380inline SBasis operator*(SBasis const & a, SBasis const & b) {
381 return multiply(a, b);
382}
383
384inline SBasis& operator*=(SBasis& a, SBasis const & b) {
385 a = multiply(a, b);
386 return a;
387}
388
395inline unsigned
396valuation(SBasis const &a, double tol=0){
397 unsigned val=0;
398 while( val<a.size() &&
399 fabs(a[val][0])<tol &&
400 fabs(a[val][1])<tol )
401 val++;
402 return val;
403}
404
405// a(b(t))
406SBasis compose(SBasis const &a, SBasis const &b);
407SBasis compose(SBasis const &a, SBasis const &b, unsigned k);
408SBasis inverse(SBasis a, int k);
409//compose_inverse(f,g)=compose(f,inverse(g)), but is numerically more stable in some good cases...
410//TODO: requires g(0)=0 & g(1)=1 atm. generalization should be obvious.
411SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, double tol=1e-3);
412
419SBasis portion(const SBasis &t, double from, double to);
420inline SBasis portion(const SBasis &t, Interval const &ivl) { return portion(t, ivl.min(), ivl.max()); }
421
422// compute f(g)
423inline SBasis
424SBasis::operator()(SBasis const & g) const {
425 return compose(*this, g);
426}
427
428inline std::ostream &operator<< (std::ostream &out_file, const Linear &bo) {
429 out_file << "{" << bo[0] << ", " << bo[1] << "}";
430 return out_file;
431}
432
433inline std::ostream &operator<< (std::ostream &out_file, const SBasis & p) {
434 for(unsigned i = 0; i < p.size(); i++) {
435 if (i != 0) {
436 out_file << " + ";
437 }
438 out_file << p[i] << "s^" << i;
439 }
440 return out_file;
441}
442
443// These are deprecated, use sbasis-math.h versions if possible
444SBasis sin(Linear bo, int k);
445SBasis cos(Linear bo, int k);
446
447std::vector<double> roots(SBasis const & s);
448std::vector<double> roots(SBasis const & s, Interval const inside);
449std::vector<std::vector<double> > multi_roots(SBasis const &f,
450 std::vector<double> const &levels,
451 double htol=1e-7,
452 double vtol=1e-7,
453 double a=0,
454 double b=1);
455
456//--------- Levelset like functions -----------------------------------------------------
457
468std::vector<Interval> level_set (SBasis const &f,
469 double level,
470 double vtol = 1e-5,
471 double a=0.,
472 double b=1.,
473 double tol = 1e-5);
474
483std::vector<Interval> level_set (SBasis const &f,
484 Interval const &level,
485 double a=0.,
486 double b=1.,
487 double tol = 1e-5);
488
497std::vector<std::vector<Interval> > level_sets (SBasis const &f,
498 std::vector<double> const &levels,
499 double a=0.,
500 double b=1.,
501 double vtol = 1e-5,
502 double tol = 1e-5);
503
511std::vector<std::vector<Interval> > level_sets (SBasis const &f,
512 std::vector<Interval> const &levels,
513 double a=0.,
514 double b=1.,
515 double tol = 1e-5);
516
517}
518#endif
519
520/*
521 Local Variables:
522 mode:c++
523 c-file-style:"stroustrup"
524 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
525 indent-tabs-mode:nil
526 fill-column:99
527 End:
528*/
529// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
530#endif
Defines the different types of exceptions that 2geom can throw.
Various utility functions.
constexpr C min() const
constexpr C max() const
Range of real numbers that is never empty.
Definition interval.h:59
SBasisOf< double > toSBasis() const
Definition sbasis-of.h:186
Function that interpolates linearly between two values.
Definition linear.h:55
Range of real numbers that can be empty.
Definition interval.h:199
double operator()(double t) const
Definition sbasis-of.h:114
Polynomial in symmetric power basis.
Definition sbasis.h:70
size_t size() const
Definition sbasis.h:76
Linear & operator[](unsigned i)
Definition sbasis.h:82
const_iterator end() const
Definition sbasis.h:84
SBasis(SBasis const &a)
Definition sbasis.h:121
bool isZero(double eps=EPSILON) const
Definition sbasis.h:195
SBasis toSBasis() const
Definition sbasis.h:238
Linear const & back() const
Definition sbasis.h:89
Linear & back()
Definition sbasis.h:88
void push_back(Linear const &l)
Definition sbasis.h:72
SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5)
Definition sbasis.h:143
SBasis(Linear *bo)
Definition sbasis.h:130
SBasis(double a)
Definition sbasis.h:115
Coord & at0()
Definition sbasis.h:213
SBasis(size_t n, Linear const &l)
Definition sbasis.h:133
int degreesOfFreedom() const
Definition sbasis.h:217
void normalize()
Definition sbasis.h:247
void reserve(unsigned n)
Definition sbasis.h:100
Linear & at(unsigned i)
Definition sbasis.h:107
Coord at1() const
Definition sbasis.h:214
void insert(iterator before, const_iterator src_begin, const_iterator src_end)
Definition sbasis.h:106
iterator begin()
Definition sbasis.h:85
SBasis(double a, double b)
Definition sbasis.h:118
double output_type
Definition sbasis.h:194
std::vector< Linear > d
Definition sbasis.h:71
const_iterator begin() const
Definition sbasis.h:83
SBasis(Iter first, Iter last)
Definition sbasis.h:184
Coord & at1()
Definition sbasis.h:215
std::vector< Linear >::const_iterator const_iterator
Definition sbasis.h:78
SBasis(Coord c0, Coord c1, Coord c2, Coord c3)
Definition sbasis.h:135
void resize(unsigned n)
Definition sbasis.h:98
SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5, Coord c6, Coord c7)
Definition sbasis.h:153
unsigned valuation(SBasis const &a, double tol=0)
Returns the degree of the first non zero coefficient.
Definition sbasis.h:396
std::vector< Linear >::iterator iterator
Definition sbasis.h:77
bool empty() const
Definition sbasis.h:87
void clear()
Definition sbasis.h:101
void resize(unsigned n, Linear const &l)
Definition sbasis.h:99
void pop_back()
Definition sbasis.h:90
SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5, Coord c6, Coord c7, Coord c8, Coord c9)
Definition sbasis.h:166
SBasis portion(const SBasis &t, double from, double to)
Returns the sbasis on domain [0,1] that was t on [from, to].
Definition sbasis.cpp:475
Coord at0() const
Definition sbasis.h:212
iterator end()
Definition sbasis.h:86
double valueAt(double t) const
Definition sbasis.h:219
bool operator==(SBasis const &B) const
Definition sbasis.h:109
bool operator!=(SBasis const &B) const
Definition sbasis.h:110
SBasis reverse(SBasis const &a)
Returns a function which reverses the domain of a.
Definition sbasis.h:271
Linear operator[](unsigned i) const
Definition sbasis.h:79
SBasis(Linear const &bo)
Definition sbasis.h:127
SBasis(std::vector< Linear > ls)
Definition sbasis.h:124
bool isConstant(double eps=EPSILON) const
Definition sbasis.h:202
void truncate(unsigned k)
Definition sbasis.h:252
double operator()(double t) const
Definition sbasis.h:232
Css & result
Geom::IntPoint size
double c[8][4]
const unsigned order
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
Simple closed interval class.
Linear fragment function class.
Various utility functions.
Definition affine.h:22
SBasisN< n > cos(LinearN< n > bo, int k)
Geom::SBasisOf< double > SBasis
Definition sbasis-of.h:54
std::vector< std::vector< Interval > > level_sets(D2< SBasis > const &f, std::vector< Rect > regions)
OptInterval bounds_exact(Bezier const &b)
Definition bezier.cpp:310
SBasisN< n > divide(SBasisN< n > const &a, SBasisN< n > const &b, int k)
OptInterval bounds_local(Bezier const &b, OptInterval const &i)
Definition bezier.cpp:320
SBasisN< n > compose_inverse(SBasisN< n > const &f, SBasisN< n > const &g, unsigned order=2, double tol=1e-3)
SBasisN< n > inverse(SBasisN< n > a, int k)
Bezier multiply(Bezier const &f, Bezier const &g)
Definition bezier.h:337
SBasisN< n > reciprocal(LinearN< n > const &a, int k)
D2< T > operator+=(D2< T > &a, D2< T > const &b)
Definition d2.h:219
D2< T > operator/(D2< T > const &a, Point const &b)
Definition d2.h:258
D2< T > operator-(D2< T > const &a, D2< T > const &b)
Definition d2.h:209
D2< T > operator*=(D2< T > &a, Point const &b)
Definition d2.h:268
SBasisN< n > sqrt(SBasisN< n > const &a, int k)
SBasisOf< T > shift(SBasisOf< T > const &a, int sh)
Definition sbasis-of.h:435
Bezier operator*(Bezier const &f, Bezier const &g)
Definition bezier.cpp:221
D2< T > operator-=(D2< T > &a, D2< T > const &b)
Definition d2.h:228
D2< T > compose(D2< T > const &a, T const &b)
Definition d2.h:405
std::vector< double > roots(SBasis const &s)
SBasisOf< T > multiply_add(SBasisOf< T > const &a, SBasisOf< T > const &b, SBasisOf< T > c)
Definition sbasis-of.h:463
Bezier integral(Bezier const &a)
Definition bezier.cpp:294
Bezier derivative(Bezier const &a)
Definition bezier.cpp:282
D2< T > operator+(D2< T > const &a, D2< T > const &b)
Definition d2.h:199
std::vector< std::vector< double > > multi_roots(SBasis const &f, std::vector< double > const &levels, double htol=1e-7, double vtol=1e-7, double a=0, double b=1)
OptInterval bounds_fast(Bezier const &b)
Definition bezier.cpp:305
SBasisN< n > sin(LinearN< n > bo, int k)
std::vector< Interval > level_set(D2< SBasis > const &f, Rect region)
D2< T > operator/=(D2< T > &a, Point const &b)
Definition d2.h:277
STL namespace.
void resize()
Definition resize.cpp:80
Defines S-power basis function class with coefficient in arbitrary ring.
Multi-dimensional symmetric power basis function.