Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
match-curve.cpp
Go to the documentation of this file.
1#include <2geom/d2.h>
2#include <2geom/sbasis.h>
4#include <2geom/path.h>
5
6#include <toys/path-cairo.h>
8
9#define ZROOTS_TEST 0
10#if ZROOTS_TEST
11#include <2geom/zroots.c>
12#endif
13
14#include <vector>
15using std::vector;
16using namespace Geom;
17
18//#define HAVE_GSL
19
20template <typename T>
21void shift(T &a, T &b, T const &c) {
22 a = b;
23 b = c;
24}
25template <typename T>
26void shift(T &a, T &b, T &c, T const &d) {
27 a = b;
28 b = c;
29 c = d;
30}
31
32extern unsigned total_steps, total_subs;
33
34class MatchCurve: public Toy {
35public:
36 double timer_precision;
37 double units;
39
40 void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
41 cairo_set_line_width (cr, 1);
42 cairo_set_source_rgb(cr, 0,0,0);
43 std::vector<Geom::Point> trans;
44 trans.resize(psh.size());
45 for(unsigned i = 0; i < psh.size(); i++) {
46 trans[i] = psh.pts[i] - Geom::Point(0, 3*width/4);
47 }
48
49 std::vector<double> solutions;
50
51 D2<SBasis> test_sb = psh.asBezier();
52
53
54 D2<SBasis> B = psh.asBezier();
55 Geom::Path pb;
56 pb.append(B);
57 pb.close(false);
58 cairo_path(cr, pb);
59 cairo_stroke(cr);
60
61 D2<SBasis> m;
62 D2<SBasis> dB = derivative(B);
63 D2<SBasis> ddB = derivative(dB);
64 D2<SBasis> dddB = derivative(ddB);
65
66 Geom::Point pt = B(0);
67 Geom::Point tang = dB(0);
68 Geom::Point dtang = ddB(0);
69 Geom::Point ddtang = dddB(0);
70 for(int dim = 0; dim < 2; dim++) {
71 m[dim] = Linear(pt[dim],pt[dim]+tang[dim]);
72 m[dim] += Linear(0, 1)*Linear(0, 1*dtang[dim])/2;
73 m[dim] += Linear(0, 1)*Linear(0, 1)*Linear(0, ddtang[dim])/6;
74 }
75
76 double lo = 0, hi = 1;
77 double eps = 5;
78 while(hi - lo > 0.0001) {
79 double mid = (hi + lo)/2;
80 //double Bmid = (Bhi + Blo)/2;
81
82 m = truncate(compose(B, Linear(0, mid)), 2);
83 // perform golden section search
84 double best_f = 0, best_x = 1;
85 for(int n = 2; n < 4; n++) {
86 Geom::Point m_pt = m(double(n)/6);
87 double x0 = 0, x3 = 1.; // just a guess!
88 const double R = 0.61803399;
89 const double C = 1 - R;
90 double x1 = C*x0 + R*x3;
91 double x2 = C*x1 + R*x3;
92 double f1 = Geom::distance(m_pt, B(x1));
93 double f2 = Geom::distance(m_pt, B(x2));
94 while(fabs(x3 - x0) > 1e-3*(fabs(x1) + fabs(x2))) {
95 if(f2 < f1) {
96 shift(x0, x1, x2, R*x1 + C*x3);
97 shift(f1, f2, Geom::distance(m_pt, B(x2)));
98 } else {
99 shift(x3, x2, x1, R*x2 + C*x0);
100 shift(f2, f1, Geom::distance(m_pt, B(x2)));
101 }
102 std::cout << x0 << ","
103 << x1 << ","
104 << x2 << ","
105 << x3 << ","
106 << std::endl;
107 }
108 if(f2 < f1) {
109 f1 = f2;
110 x1 = x2;
111 }
112 if(f1 > best_f) {
113 best_f = f1;
114 best_x = x1;
115 }
116 }
117 std::cout << mid << ":" << best_x << "->" << best_f << std::endl;
118 //draw_cross(cr, point_at(B, x1));
119
120 if(best_f > eps) {
121 hi = mid;
122 } else {
123 lo = mid;
124 }
125 }
126 std::cout << std::endl;
127 //draw_cross(cr, point_at(B, hi));
128 draw_circ(cr, m(hi));
129 {
130 Geom::Path pb;
131 pb.append(m);
132 pb.close(false);
133 cairo_path(cr, pb);
134 }
135
136 cairo_stroke(cr);
137 Toy::draw(cr, notify, width, height, save,timer_stream);
138 }
139 MatchCurve() : timer_precision(0.1), units(1e6) // microseconds
140 {
141 handles.push_back(&psh);
142 for(int i = 0; i < 6; i++)
143 psh.push_back(uniform()*400, uniform()*400);
144 }
145};
146
147int main(int argc, char **argv) {
148 init(argc, argv, new MatchCurve());
149
150 return 0;
151}
152
153/*
154 Local Variables:
155 mode:c++
156 c-file-style:"stroustrup"
157 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
158 indent-tabs-mode:nil
159 fill-column:99
160 End:
161*/
162// 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
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
void push_back(double x, double y)
Geom::D2< Geom::SBasis > asBezier()
std::vector< Geom::Point > pts
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)
double c[8][4]
Lifts one dimensional objects into 2D.
Various utility functions.
Definition affine.h:22
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
SBasisOf< T > shift(SBasisOf< T > const &a, int sh)
Definition sbasis-of.h:435
D2< T > compose(D2< T > const &a, T const &b)
Definition d2.h:405
Bezier derivative(Bezier const &a)
Definition bezier.cpp:282
D2< SBasis > truncate(D2< SBasis > const &a, unsigned terms)
Definition d2-sbasis.cpp:52
struct _cairo cairo_t
Definition path-cairo.h:16
void cairo_path(cairo_t *cr, Geom::Path const &p)
void draw_circ(cairo_t *cr, Geom::Point h)
Polynomial in symmetric power basis (S-basis)
std::vector< double > & solutions
double height
double width
double uniform()
void init(int argc, char **argv, Toy *t, int width=600, int height=600)