Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
root-finder-comparer.cpp
Go to the documentation of this file.
1#include <2geom/sbasis.h>
3#include <2geom/solver.h>
4#include <2geom/sbasis-poly.h>
5#include "../2geom/orphan-code/nearestpoint.cpp" // FIXME: This looks like it may give problems later, (including a .cpp file)
6#include <2geom/path.h>
7
8#include <toys/path-cairo.h>
10
11#define ZROOTS_TEST 0
12#if ZROOTS_TEST
13#include <2geom/zroots.c>
14#endif
15
16using std::swap;
17
18namespace Geom{
19extern void subdiv_sbasis(SBasis const & s,
20 std::vector<double> & roots,
21 double left, double right);
22};
23
24double eval_bernstein(double* w, double t, unsigned N) {
25 double Vtemp[2*N];
26 //const int degree = N-1;
27 for (unsigned i = 0; i < N; i++)
28 Vtemp[i] = w[i];
29
30 /* Triangle computation */
31 const double omt = (1-t);
32 //Left[0] = Vtemp[0];
33 //Right[degree] = Vtemp[degree];
34 double *prev_row = Vtemp;
35 double *row = Vtemp + N;
36 for (unsigned i = 1; i < N; i++) {
37 for (unsigned j = 0; j < N - i; j++) {
38 row[j] = omt*prev_row[j] + t*prev_row[j+1];
39 }
40 //Left[i] = row[0];
41 //Right[degree-i] = row[degree-i];
42 swap(prev_row, row);
43 }
44 return prev_row[0];
45}
46
47#include <vector>
48using std::vector;
49using namespace Geom;
50
51#ifdef HAVE_GSL
52#include <complex>
53using std::complex;
54#endif
55
56class RootFinderComparer: public Toy {
57public:
59
60 void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
61 std::vector<Geom::Point> trans;
62 trans.resize(psh.size());
63 for(unsigned i = 0; i < handles.size(); i++) {
64 trans[i] = psh.pts[i] - Geom::Point(0, height/2);
65 }
66
67 Timer tm;
68
69
70 std::vector<double> solutions;
71 solutions.resize(6);
72
74 tm.start();
75 FindRoots(&trans[0], 5, &solutions[0], 0);
76 Timer::Time als_time = tm.lap();
77 *notify << "original time = " << als_time << std::endl;
78
79 D2<SBasis> test_sb = psh.asBezier();//handles_to_sbasis(handles.begin(),5);
80 Interval bs = *bounds_exact(test_sb[1]);
81 cairo_move_to(cr, test_sb[0](0), bs.min());
82 cairo_line_to(cr, test_sb[0](1), bs.min());
83 cairo_move_to(cr, test_sb[0](0), bs.max());
84 cairo_line_to(cr, test_sb[0](1), bs.max());
85 cairo_stroke(cr);
86 *notify << "sb bounds = "<<bs.min()<< ", " <<bs.max()<<std::endl;
87 Poly ply = sbasis_to_poly(test_sb[1]);
88 ply = Poly(height/2) - ply;
89 cairo_move_to(cr, 0, height/2);
91 cairo_stroke(cr);
92#ifdef HAVE_GSL
93 vector<complex<double> > complex_solutions;
94 complex_solutions = solve(ply);
95#if 1
96 *notify << "gsl: ";
97 std::copy(complex_solutions.begin(), complex_solutions.end(), std::ostream_iterator<std::complex<double> >(*notify, ",\t"));
98 *notify << std::endl;
99#endif
100#endif
101
102#if ZROOTS_TEST
103 fcomplex a[ply.size()];
104 for(unsigned i = 0; i < ply.size(); i++) {
105 a[i] = ply[i];
106 }
107 //copy(a, a+ply.size(), ply.begin());
108 fcomplex rts[ply.size()];
109
110 zroots(a, ply.size(), rts, true);
111 for(unsigned i = 0; i < ply.size(); i++) {
112 if(! a[i].imag())
113 solutions[i] = a[i].real();
114 }
115#endif
116
117#ifdef HAVE_GSL
118
120 tm.start();
121 solve(ply);
122 als_time = tm.lap();
123 *timer_stream << "gsl poly = " << als_time << std::endl;
124#endif
125
126 #if ZROOTS_TEST
128 tm.start();
129 zroots(a, ply.size(), rts, false);
130 als_time = tm.lap();
131 *timer_stream << "zroots poly = " << als_time << std::endl;
132 #endif
133
134 #if LAGUERRE_TEST
136 tm.start();
137 Laguerre(ply);
138 als_time = tm.lap();
139 *timer_stream << "Laguerre poly = " << als_time << std::endl;
140 complex_solutions = Laguerre(ply);
141
142 #endif
143
144 #define SBASIS_SUBDIV_TEST 0
145 #if SBASIS_SUBDIV_TEST
147 tm.start();
148 subdiv_sbasis(-test_sb[1] + Linear(3*width/4),
149 rts, 0, 1);
150 als_time = tm.lap();
151 *timer_stream << "sbasis subdivision = " << als_time << std::endl;
152 #endif
153 #if 0
155 tm.start();
156 solutions.resize(0);
157 find_parametric_bezier_roots(&trans[0], 5, solutions, 0);
158 als_time = tm.lap();
159 *timer_stream << "solver parametric = " << als_time << std::endl;
160 #endif
161 double ys[trans.size()];
162 for(unsigned i = 0; i < trans.size(); i++) {
163 ys[i] = trans[i][1];
164 double x = double(i)/(trans.size()-1);
165 x = (1-x)*height/4 + x*height*3/4;
166 draw_handle(cr, Geom::Point(x, height/2 + ys[i]));
167 }
168
169 solutions.resize(0);
171 tm.start();
172 find_bernstein_roots(ys, 5, solutions, 0, 0, 1, false);
173 als_time = tm.lap();
174 *notify << "found sub solutions at:\n";
175 std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double >(*notify, ","));
176 *notify << "solver 1d bernstein subdivision n_slns = " << solutions.size()
177 << ", time = " << als_time << std::endl;
178
179 solutions.resize(0);
181 tm.start();
182 find_bernstein_roots(ys, 5, solutions, 0, 0, 1, true);
183 als_time = tm.lap();
184
185 *notify << "solver 1d bernstein secant subdivision slns" << solutions.size()
186 << ", time = " << als_time << std::endl;
187 *notify << "found secant solutions at:\n";
188 std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double >(*notify, ","));
189 *notify << "solver 1d bernstein subdivision accuracy:"
190 << std::endl;
191 for(double solution : solutions) {
192 *notify << solution << ":" << eval_bernstein(ys, solution, trans.size()) << ",";
193 }
195 tm.start();
196 solutions = roots( -test_sb[1] + Linear(height/2));
197 als_time = tm.lap();
198#if 1
199 *notify << "sbasis roots: ";
200 std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double>(*notify, ",\t"));
201 *notify << "\n time = " << als_time << std::endl;
202#endif
203 for(double solution : solutions) {
204 double x = test_sb[0](solution);
205 draw_cross(cr, Geom::Point(x, height/2));
206
207 }
208
209 *notify << "found " << solutions.size() << "solutions at:\n";
210 std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double >(*notify, ","));
211
212 D2<SBasis> B = psh.asBezier();//handles_to_sbasis(handles.begin(), 5);
213 Geom::Path pb;
214 pb.append(B);
215 pb.close(false);
216 cairo_path(cr, pb);
217
218 B[0] = Linear(width/4, 3*width/4);
219 cairo_d2_sb(cr, B);
220 Toy::draw(cr, notify, width, height, save,timer_stream);
221 }
222 RootFinderComparer(unsigned degree)
223 {
224 for(unsigned i = 0; i < degree; i++) psh.push_back(Geom::Point(uniform()*400, uniform()*400));
225 handles.push_back(&psh);
226 }
227};
228
229int main(int argc, char **argv) {
230 unsigned bez_ord = 6;
231 if(argc > 1)
232 sscanf(argv[1], "%d", &bez_ord);
233 init(argc, argv, new RootFinderComparer(bez_ord));
234
235 return 0;
236}
237
238/*
239 Local Variables:
240 mode:c++
241 c-file-style:"stroustrup"
242 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
243 indent-tabs-mode:nil
244 fill-column:99
245 End:
246*/
247// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Path - a sequence of contiguous curves.
int main()
Conversion between Bezier control points and SBasis curves.
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
Range of real numbers that is never empty.
Definition interval.h:59
Function that interpolates linearly between two values.
Definition linear.h:55
Sequence of contiguous curves, aka spline.
Definition path.h:353
void close(bool closed=true)
Set whether the path is closed.
Definition path.cpp:322
void append(Curve *curve)
Add a new curve to the end of the path.
Definition path.h:750
Two-dimensional point that doubles as a vector.
Definition point.h:66
Polynomial in canonical (monomial) basis.
Definition polynomial.h:50
Polynomial in symmetric power basis.
Definition sbasis.h:70
void push_back(double x, double y)
Geom::D2< Geom::SBasis > asBezier()
std::vector< Geom::Point > pts
void ask_for_timeslice()
Ask the OS nicely for a big time slice.
void start()
void lap(long long &ns)
vector< Handle * > handles
virtual void save(FILE *f)
virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream)
const double w
Definition conic-4.cpp:19
Various utility functions.
Definition affine.h:22
OptInterval bounds_exact(Bezier const &b)
Definition bezier.cpp:310
void subdiv_sbasis(SBasis const &s, std::vector< double > &roots, double left, double right)
Poly sbasis_to_poly(SBasis const &s)
Changes the basis of p to be monomial.
void find_parametric_bezier_roots(Geom::Point const *w, unsigned degree, std::vector< double > &solutions, unsigned depth)
void find_bernstein_roots(double const *w, unsigned degree, std::vector< double > &solutions, unsigned depth, double left_t=0, double right_t=1, bool use_secant=true)
std::vector< double > roots(SBasis const &s)
std::vector< std::complex< double > > solve(const Poly &p)
static int FindRoots(Geom::Point *w, int degree, double *t, int depth)
void cairo_line_to(cairo_t *cr, Geom::Point p1)
void draw_cross(cairo_t *cr, Geom::Point h)
struct _cairo cairo_t
Definition path-cairo.h:16
void cairo_path(cairo_t *cr, Geom::Path const &p)
void draw_handle(cairo_t *cr, Geom::Point h)
void cairo_move_to(cairo_t *cr, Geom::Point p1)
void cairo_d2_sb(cairo_t *cr, Geom::D2< Geom::SBasis > const &p)
unsigned long bs
Definition quantize.cpp:38
double eval_bernstein(double *w, double t, unsigned N)
Conversion between SBasis and Poly.
Polynomial in symmetric power basis (S-basis)
size_t degree
size_t N
std::vector< double > & solutions
Finding roots of Bernstein-Bezier polynomials.
double height
double width
double uniform()
void init(int argc, char **argv, Toy *t, int width=600, int height=600)