X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=ETL%2FETL%2F_bspline.h;fp=ETL%2FETL%2F_bspline.h;h=edc00a7cc7d1f9a0016bde53c914fb7826355661;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/ETL/ETL/_bspline.h b/ETL/ETL/_bspline.h new file mode 100644 index 0000000..edc00a7 --- /dev/null +++ b/ETL/ETL/_bspline.h @@ -0,0 +1,237 @@ +/*! ======================================================================== +** Extended Template and Library +** B-Spline Class Implementation +** $Id$ +** +** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** === N O T E S =========================================================== +** +** This is an internal header file, included by other ETL headers. +** You should not attempt to use it directly. +** +** ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __ETL__BSPLINE_H +#define __ETL__BSPLINE_H + +/* === H E A D E R S ======================================================= */ + +#include +#include +#include "_curve_func.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +_ETL_BEGIN_NAMESPACE + +template , class D=distance_func > +class bspline : public std::unary_function +{ +public: + typedef T value_type; + typedef K knot_type; + typedef std::vector knot_container; + typedef std::vector cpoint_container; + typedef typename knot_container::iterator knot_iterator; + typedef typename cpoint_container::iterator cpoint_iterator; + + typedef C affine_func_type; + typedef D distance_func_type; + +protected: + affine_func_type affine_func; + distance_func_type distance_func; + +private: + int m; + knot_container _knots; + cpoint_container _cpoints; + bool _loop; + +public: + bspline():m(2),_loop(false) { } + + int get_m()const { return m-1; }; + int set_m(int new_m) { m=new_m+1; return m-1; }; + + bool set_loop(bool x) { _loop=x; reset_knots(); return _loop; } + + knot_container & knots() { return _knots; }; + cpoint_container & cpoints() { return _cpoints; }; + + const knot_container & knots()const { return _knots; }; + const cpoint_container & cpoints()const { return _cpoints; }; + + void reset_knots() + { + int i; + + if(!_loop) + { + _knots.clear(); + if(!_cpoints.size()) + return; + while(m>(signed)_cpoints.size()) + m--; + for(i=0;i(signed)_cpoints.size()) + m--; + for(i=0;i<=(signed)_cpoints.size()-m+1;i++) + *_knots.insert(_knots.end())=i; + } + } + + int calc_curve_segment(knot_type t)const + { + int k; + if(t<0) + t=0; + if(t>=_knots.back()) + t=_knots.back()-0.0001; + for(k=0;_knots[k]>t || _knots[k+1]<=t;k++) + ; + + return k; + } + + knot_container get_segment_knots(int i)const + { + if(i+1=(signed)_knots.size()) + { + knot_container ret(_knots.begin()+i-m+1,_knots.end()); + return ret; + } + return knot_container(_knots.begin()+i-m+1, _knots.begin()+i+m); + } + + cpoint_container get_segment_cpoints(int i)const + { + if(i+1=(signed)_knots.size()) + { + return cpoint_container(); + } + return cpoint_container(_cpoints.begin()+i-m+1, _cpoints.begin()+i+1); + } + + cpoint_container calc_shell(knot_type t, int level)const + { + int + i=calc_curve_segment(t), + j,k; + + knot_container u=get_segment_knots(i); + + cpoint_container d=get_segment_cpoints(i); + + if(!d.size()) + return cpoint_container(); + + for(j=0;d.size()>1 && j1;d.pop_back(),j++) + { + for(k=0;k<(signed)d.size()-1;k++) + { + d[k]=affine_func(d[k],d[k+1],((t-u[j+k+1])/(u[m+k]-u[j+k+1]))); + } + } + return d.front(); + } + + cpoint_iterator find_closest_cpoint(const value_type &point, typename distance_func_type::result_type max) + { + cpoint_iterator i=_cpoints.begin(); + cpoint_iterator ret=i; + typename distance_func_type::result_type dist=distance_func(point,_cpoints[0]); + + // The distance function returns "cooked" (ie: squared) + // distances, so we need to cook our max distance for + // the comparison to work correctly. + max=distance_func.cook(max); + + for(++i;i<_cpoints.end();i++) + { + typename distance_func_type::result_type thisdist=distance_func(point,*i); + + if(thisdist