diff --git a/src/2geom/sbasis.h b/src/2geom/sbasis.h
index a27d4bfcee4512c1a58b3a4a4cffdd43d021dde7..d7390c64d822b51eac3e1c7827bb124c0f33c069 100644 (file)
--- a/src/2geom/sbasis.h
+++ b/src/2geom/sbasis.h
-/*
- * sbasis.h - S-power basis function class
+/**
+ * \file
+ * \brief Defines S-power basis function class
*
* Authors:
* Nathan Hurst <njh@mail.csse.monash.edu.au>
#include <cassert>
#include <iostream>
-#include "linear.h"
-#include "interval.h"
+#include <2geom/linear.h>
+#include <2geom/interval.h>
+#include <2geom/utils.h>
+#include <2geom/exception.h>
+
+//#define USE_SBASISN 1
+
+
+#if defined(USE_SBASIS_OF)
+
+#include "sbasis-of.h"
-namespace Geom {
+#elif defined(USE_SBASISN)
+
+#include "sbasisN.h"
+namespace Geom{
/*** An empty SBasis is identically 0. */
-class SBasis : public std::vector<Linear>{
+class SBasis : public SBasisN<1>;
+
+};
+#else
+
+namespace Geom{
+
+/*** An empty SBasis is identically 0. */
+class SBasis{
+ std::vector<Linear> d;
+ void push_back(Linear const&l) { d.push_back(l); }
+
public:
+ // As part of our migration away from SBasis isa vector we provide this minimal set of vector interface methods.
+ size_t size() const {return d.size();}
+ Linear operator[](unsigned i) const {
+ return d[i];
+ }
+ Linear& operator[](unsigned i) { return d.at(i); }
+ Linear const* begin() const { return (Linear const*)&*d.begin();}
+ Linear const* end() const { return (Linear const*)&*d.end();}
+ Linear* begin() { return (Linear*)&*d.begin();}
+ Linear* end() { return (Linear*)&*d.end();}
+ bool empty() const {return d.empty();}
+ Linear &back() {return d.back();}
+ Linear const &back() const {return d.back();}
+ void pop_back() { d.pop_back();}
+ void resize(unsigned n) { d.resize(n);}
+ void resize(unsigned n, Linear const& l) { d.resize(n, l);}
+ void reserve(unsigned n) { d.reserve(n);}
+ void clear() {d.clear();}
+ void insert(Linear* before, const Linear* src_begin, const Linear* src_end) { d.insert(std::vector<Linear>::iterator(before), src_begin, src_end);}
+ //void insert(Linear* aa, Linear* bb, Linear* cc} { d.insert(aa, bb, cc);}
+ Linear& at(unsigned i) { return d.at(i);}
+ //void insert(Linear* before, int& n, Linear const &l) { d.insert(std::vector<Linear>::iterator(before), n, l);}
+ bool operator==(SBasis const&B) const { return d == B.d;}
+ bool operator!=(SBasis const&B) const { return d != B.d;}
+ operator std::vector<Linear>() { return d;}
+
+
SBasis() {}
explicit SBasis(double a) {
push_back(Linear(a,a));
}
+ explicit SBasis(double a, double b) {
+ push_back(Linear(a,b));
+ }
SBasis(SBasis const & a) :
- std::vector<Linear>(a)
+ d(a.d)
{}
SBasis(Linear const & bo) {
push_back(bo);
}
+ SBasis(Linear* bo) {
+ push_back(*bo);
+ }
+ explicit SBasis(size_t n, Linear const&l) : d(n, l) {}
//IMPL: FragmentConcept
typedef double output_type;
}
return true;
}
+ inline bool isConstant() const {
+ if (empty()) return true;
+ for (unsigned i = 0; i < size(); i++) {
+ if(!(*this)[i].isConstant()) return false;
+ }
+ return true;
+ }
+
bool isFinite() const;
inline double at0() const {
if(empty()) return 0; else return (*this)[0][0];
inline double at1() const{
if(empty()) return 0; else return (*this)[0][1];
}
+
+ int degreesOfFreedom() const { return size()*2;}
double valueAt(double t) const {
double s = t*(1-t);
double p0 = 0, p1 = 0;
- double sk = 1;
-//TODO: rewrite as horner
- for(unsigned k = 0; k < size(); k++) {
- p0 += sk*(*this)[k][0];
- p1 += sk*(*this)[k][1];
- sk *= s;
+ for(unsigned k = size(); k > 0; k--) {
+ const Linear &lin = (*this)[k-1];
+ p0 = p0*s + lin[0];
+ p1 = p1*s + lin[1];
}
return (1-t)*p0 + t*p1;
}
+ //double valueAndDerivative(double t, double &der) const {
+ //}
double operator()(double t) const {
return valueAt(t);
}
+
+ std::vector<double> valueAndDerivatives(double t, unsigned n) const;
+
SBasis toSBasis() const { return SBasis(*this); }
double tailError(unsigned tail) const;
// compute f(g)
SBasis operator()(SBasis const & g) const;
- Linear operator[](unsigned i) const {
- assert(i < size());
- return std::vector<Linear>::operator[](i);
- }
-
//MUTATOR PRISON
- Linear& operator[](unsigned i) { return this->at(i); }
-
//remove extra zeros
void normalize() {
while(!empty() && 0 == back()[0] && 0 == back()[1])
pop_back();
}
+
void truncate(unsigned k) { if(k < size()) resize(k); }
+private:
+ void derive(); // in place version
};
//TODO: figure out how to stick this in linear, while not adding an sbasis dep
inline SBasis Linear::toSBasis() const { return SBasis(*this); }
//implemented in sbasis-roots.cpp
-Interval bounds_exact(SBasis const &a);
-Interval bounds_fast(SBasis const &a, int order = 0);
-Interval bounds_local(SBasis const &a, const Interval &t, int order = 0);
+OptInterval bounds_exact(SBasis const &a);
+OptInterval bounds_fast(SBasis const &a, int order = 0);
+OptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0);
+
+/** Returns a function which reverses the domain of a.
+ \param a sbasis function
+useful for reversing a parameteric curve.
+*/
inline SBasis reverse(SBasis const &a) {
- SBasis result;
- result.reserve(a.size());
+ SBasis result(a.size(), Linear());
+
for(unsigned k = 0; k < a.size(); k++)
- result.push_back(reverse(a[k]));
+ result[k] = reverse(a[k]);
return result;
}
//IMPL: ScalableConcept
inline SBasis operator-(const SBasis& p) {
if(p.isZero()) return SBasis();
- SBasis result;
- result.reserve(p.size());
+ SBasis result(p.size(), Linear());
for(unsigned i = 0; i < p.size(); i++) {
- result.push_back(-p[i]);
+ result[i] = -p[i];
}
return result;
}
SBasis& operator-=(SBasis& a, const SBasis& b);
//TODO: remove?
-inline SBasis operator+(const SBasis & a, Linear const & b) {
+/*inline SBasis operator+(const SBasis & a, Linear const & b) {
if(b.isZero()) return a;
if(a.isZero()) return b;
SBasis result(a);
else
a[0] -= b;
return a;
-}
+ }*/
//IMPL: OffsetableConcept
inline SBasis operator+(const SBasis & a, double b) {
}
inline SBasis& operator+=(SBasis& a, double b) {
if(a.isZero())
- a.push_back(Linear(b,b));
+ a = SBasis(Linear(b,b));
else
a[0] += b;
return a;
}
inline SBasis& operator-=(SBasis& a, double b) {
if(a.isZero())
- a.push_back(Linear(-b,-b));
+ a = SBasis(Linear(-b,-b));
else
a[0] -= b;
return a;
}
SBasis multiply(SBasis const &a, SBasis const &b);
+// This performs a multiply and accumulate operation in about the same time as multiply. return a*b + c
+SBasis multiply_add(SBasis const &a, SBasis const &b, SBasis c);
SBasis integral(SBasis const &c);
SBasis derivative(SBasis const &a);
return a;
}
-//valuation: degree of the first non zero coefficient.
+/** Returns the degree of the first non zero coefficient.
+ \param a sbasis function
+ \param tol largest abs val considered 0
+ \returns first non zero coefficient
+*/
inline unsigned
valuation(SBasis const &a, double tol=0){
unsigned val=0;
//TODO: requires g(0)=0 & g(1)=1 atm. generalization should be obvious.
SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, double tol=1e-3);
+/** Returns the sbasis on domain [0,1] that was t on [from, to]
+ \param a sbasis function
+ \param from,to interval
+ \returns sbasis
+
+*/
inline SBasis portion(const SBasis &t, double from, double to) { return compose(t, Linear(from, to)); }
+inline SBasis portion(const SBasis &t, Interval ivl) { return compose(t, Linear(ivl[0], ivl[1])); }
// compute f(g)
inline SBasis
return out_file;
}
+// These are deprecated, use sbasis-math.h versions if possible
SBasis sin(Linear bo, int k);
SBasis cos(Linear bo, int k);
double b=1);
}
+#endif
/*
Local Variables:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
#endif