Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
parametrics.cpp
Go to the documentation of this file.
1#include <2geom/d2.h>
2#include <2geom/sbasis.h>
3#include <2geom/sbasis-2d.h>
6#include <2geom/path.h>
8#include <2geom/sbasis-math.h>
9
10#include <toys/path-cairo.h>
12#include <2geom/affine.h>
13
14#include <glib.h>
15#include <vector>
16#include <iostream>
17using std::vector;
18using namespace Geom;
19
20int mode;
21
22static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double max, double space=10){
23 Piecewise<D2<SBasis> > Mperp = rot90(derivative(M)) * 3;
24 for( double t = M.cuts.front(); t < max; t += space) {
25 Point pos = M(t), perp = Mperp(t);
26 draw_line_seg(cr, pos + perp, pos - perp);
27 }
28 cairo_stroke(cr);
29}
30
31static void draw_axis(cairo_t *cr, Piecewise<D2<SBasis> > const &pw, unsigned d, Affine m) {
32 double mult;
33 if(abs(mode)==1) mult = 20;
34 if(abs(mode)==2) mult = 1;
35 if(abs(mode)==3) mult = 100;
36 if(abs(mode)==4) mult = 20;
37 if(abs(mode)==5) mult = 20;
38 if(abs(mode)==6) mult = 100;
39 for(unsigned i = 0; i < pw.size(); i++) {
40 cairo_d2_sb(cr, D2<SBasis>(SBasis(pw.cuts[i]-pw.cuts[0], pw.cuts[i+1]-pw.cuts[0])*mult, SBasis(pw[i][d]))*m);
41 }
42}
43/*
44void dump_latex(PathVector ps) {
45 for(unsigned d = 0; d < 2; d++) {
46 std::cout << "$$\n" << (d?"y":"x") << "(t) = \\left\\{\n\\begin{array}{ll}\n";
47 int seg = 0;
48 for(unsigned i = 0; i < ps.size(); i++)
49 for(unsigned j = 0; j < ps[i].size(); j++) {
50 Bezier<3> &b = dynamic_cast<Bezier<3>& >(const_cast<Curve&>(ps[i][j]));
51 std::cout << b[0][d] << "(" << seg+1 << "-t)^3 + "
52 << 3*b[1][d] << "t(" << seg+1 << "-t)^2 + "
53 << 3*b[2][d] << "t^2(" << seg+1 << "-t) + "
54 << b[3][d] << "t^3,& " << seg << "\\leq t < " << seg+1 << "\\\\\n";
55 seg++;
56 }
57 std::cout << "\\end{array}\n$$\n";
58 }
59}
60*/
61class Parametrics: public Toy {
62 Piecewise<D2<SBasis> > cat, alcat, box, arc, monk, traj;
63#ifdef USE_TIME
64 GTimer* time;
65 bool st;
66#endif
67 double waitt;
68 double t;
69 int count;
70 void draw(cairo_t *cr,
71 std::ostringstream *notify,
72 int width, int height, bool save, std::ostringstream *timer_stream) override {
73 //double t = handles[0][0] / 20.;
74
75#ifdef USE_TIME
76 gulong* foo = 0;
77 t = g_timer_elapsed(time, foo) * 100;
78#else
79 double inc;
80 if(mode==1) inc = .1;
81 if(mode==2) inc = 5;
82 if(mode==3) inc = .01;
83 if(mode==4) inc = .04;
84 if(mode==5) inc = .1;
85 if(mode==6) inc = .01;
86 if(mode<0) inc = .01*M_PI;
87 if(!save && !waitt) {
88 t += inc;
89 }
90 if(waitt) waitt += 1;
91 if(waitt>20) waitt = 0;
92#endif
94 if(abs(mode)==1) obj = cat;
95 if(abs(mode)==2) obj = alcat;
96 if(abs(mode)==3) obj = arc;
97 if(abs(mode)==4) obj = box;
98 if(abs(mode)==5) obj = monk;
99 if(abs(mode)==6) obj = traj;
100 if(t==obj.cuts.back()) t += inc/2;
101 cairo_set_source_rgb(cr, 1,1,1);
102 if(save) {
103 cairo_rectangle(cr, 0, 0, width, height);
104 cairo_fill(cr);
105 }
106 Piecewise<D2<SBasis> > port, rport;
107 if(mode>0) {
108 port = portion(obj, 0, t);
109 rport = mode>0? portion(obj, t, obj.cuts[obj.size()]) : obj;
110 cairo_set_source_rgba (cr, 0., 0., 0., 1);
111 Point curpt = rport[0].at0();
112 if(t<obj.cuts.back()) {
113 draw_line_seg(cr, curpt, Point(curpt[0], 350));
114 draw_line_seg(cr, curpt, Point(350, curpt[1]));
115 cairo_stroke(cr);
116 }
117
118 char tlab[64];
119 sprintf(tlab, "t=%.02f", t);
120 draw_text(cr, curpt, tlab , true);
121
122 cairo_set_line_width (cr, 2);
123 cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
124 cairo_pw_d2_sb(cr, port);
125 cairo_stroke(cr);
126 }
127 if(mode>=0 && t>=obj.cuts.back()+inc) t = 0;
128 cairo_set_source_rgba (cr, 0.9, 0., 0., 1);
129 if(mode<0) {
130 draw_axis(cr, obj, 0, from_basis(Point(cos(t),sin(t)),Point(sin(t),-cos(t)),Point(0, 350)));
131 if(cos(t) <= 0) {
132 mode = -mode;
133 t = 0;
134 waitt = 1;
135 }
136 } else
137 draw_axis(cr, rport, 0, from_basis(Point(0,1),Point(1,0),Point(0, 350)));
138 cairo_stroke(cr);
139
140 cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
141 if(mode<0)
142 draw_axis(cr, obj, 1, from_basis(Point(1,0),Point(0,1),Point(350*t/M_PI*2, 0)));
143 else
144 draw_axis(cr, rport, 1, from_basis(Point(1,0),Point(0,1),Point(350, 0)));
145 cairo_stroke(cr);
146
147 if(mode==2 && t>0) {
148 cairo_set_line_width (cr, 1);
149 cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
150 dot_plot(cr, port, t);
151 cairo_stroke(cr);
152 }
153
154 if(!save) {
155 char file[100];
156 sprintf(file, "output/%04d.png", count);
157 //take_screenshot(file);
158 count++;
159 }
160 // *notify << "pieces = " << alcat.size() << ";\n";
161
162 Toy::draw(cr, notify, width, height, save,timer_stream);
163 redraw();
164 }
165
166#ifdef USE_TIME
167 virtual void mouse_moved(Geom::Point const &pos, unsigned modifiers) {
168 if(st) {
169 g_timer_start(time);
170 st = false;
171 }
172 Toy::mouse_moved(pos, modifiers);
173 }
174#endif
175
176 public:
177 Parametrics(){
178 mode = 2;
179 PathVector cp = read_svgd("cat.svgd");
180 //dump_latex(cp);
181 cat = paths_to_pw(cp);
182 cat *= .3;
183 cat += Point(50, 50);
184 alcat = arc_length_parametrization(cat);
185
186 monk = paths_to_pw(read_svgd("monkey.svgd"));
187 //monk *= .3;
188 monk += Point(50,50);
189
190 arc = sectionize(D2<Piecewise<SBasis> >(cos(Linear(0,M_PI))*120, sin(Linear(0,M_PI))*-120));
191 arc += Point(200, 200);
192
193 box = Piecewise<D2<SBasis> >();
194 box.push_cut(0);
195 box.push(D2<SBasis>(SBasis(100.,300.), SBasis(100.)), 1);
196 box.push(D2<SBasis>(SBasis(300.), SBasis(100.,300.)), 2);
197 box.push(D2<SBasis>(SBasis(300.,100.), SBasis(300.)), 3);
198 box.push(D2<SBasis>(SBasis(100.), SBasis(300.,100.)), 4);
199 //handles.push_back(Point(100, 100));
200 traj = Piecewise<D2<SBasis> >();
201 SBasis quad = Linear(0,1)*Linear(0,1)*256-Linear(0,256)+200;
202 traj.push_cut(0);
203 traj.push(D2<SBasis>(SBasis(100.,300.),SBasis(quad)), 1);
204#ifdef USE_TIME
205 time = g_timer_new();
206 g_timer_reset(time);
207 st = true;
208#endif
209 waitt = 0;
210 count = 0;
211 t = 0;
212 }
213};
214
215int main(int argc, char **argv) {
216 init(argc, argv, new Parametrics, 720, 480);
217 return 0;
218}
219
220/*
221 Local Variables:
222 mode:c++
223 c-file-style:"stroustrup"
224 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
225 indent-tabs-mode:nil
226 fill-column:99
227 End:
228*/
229//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
Path - a sequence of contiguous curves.
3x3 affine transformation matrix.
static void dot_plot(cairo_t *cr, Piecewise< D2< SBasis > > const &M, double space=10)
int main()
Conversion between Bezier control points and SBasis curves.
3x3 matrix representing an affine transformation.
Definition affine.h:70
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 subpaths.
Definition pathvector.h:122
Function defined as discrete pieces.
Definition piecewise.h:71
unsigned size() const
Definition piecewise.h:131
void push(const T &s, double to)
Convenience/implementation hiding function to add segment/cut pairs.
Definition piecewise.h:141
void push_cut(double c)
Definition piecewise.h:152
std::vector< double > cuts
Definition piecewise.h:75
Two-dimensional point that doubles as a vector.
Definition point.h:66
Polynomial in symmetric power basis.
Definition sbasis.h:70
virtual void mouse_moved(Geom::Point const &pos, unsigned modifiers)
virtual void save(FILE *f)
virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream)
Lifts one dimensional objects into 2D.
PathVector read_svgd(char const *filename)
Create path vector from SVG path data stored in a file.
Various utility functions.
Definition affine.h:22
SBasisN< n > cos(LinearN< n > bo, int k)
Piecewise< D2< SBasis > > paths_to_pw(PathVector const &paths)
Definition path.cpp:1123
MultiDegree< n > max(MultiDegree< n > const &p, MultiDegree< n > const &q)
Returns the maximal degree appearing in the two arguments for each variables.
Definition sbasisN.h:158
Affine from_basis(const Point &x_basis, const Point &y_basis, const Point &offset=Point(0, 0))
Creates a Affine given an axis and origin point.
Definition affine.cpp:26
Piecewise< D2< SBasis > > sectionize(D2< Piecewise< SBasis > > const &a)
Definition d2-sbasis.cpp:65
Bezier portion(const Bezier &a, double from, double to)
Definition bezier.cpp:250
Bezier derivative(Bezier const &a)
Definition bezier.cpp:282
Piecewise< D2< SBasis > > arc_length_parametrization(D2< SBasis > const &M, unsigned order=3, double tol=.01)
iter inc(iter const &x, unsigned n)
Definition path.cpp:410
SBasisN< n > sin(LinearN< n > bo, int k)
D2< T > rot90(D2< T > const &a)
Definition d2.h:397
Point abs(Point const &b)
int mode
static void dot_plot(cairo_t *cr, Piecewise< D2< SBasis > > const &M, double max, double space=10)
static void draw_axis(cairo_t *cr, Piecewise< D2< SBasis > > const &pw, unsigned d, Affine m)
void cairo_rectangle(cairo_t *cr, Geom::Rect const &r)
struct _cairo cairo_t
Definition path-cairo.h:16
void cairo_d2_sb(cairo_t *cr, Geom::D2< Geom::SBasis > const &p)
void cairo_pw_d2_sb(cairo_t *cr, Geom::Piecewise< Geom::D2< Geom::SBasis > > const &p)
void draw_line_seg(cairo_t *cr, Geom::Point a, Geom::Point b)
Obsolete 2D SBasis function class.
two-dimensional geometric operators.
some std functions to work with (pw)s-basis
Polynomial in symmetric power basis (S-basis)
parse SVG path specifications
double height
double width
void draw_text(cairo_t *cr, Geom::Point pos, const char *txt, bool bottom=false, const char *fontdesc="Sans")
void cairo_set_source_rgba(cairo_t *cr, colour c)
void redraw()
void init(int argc, char **argv, Toy *t, int width=600, int height=600)