summaryrefslogtreecommitdiffstats
path: root/src/toys/parametrics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/toys/parametrics.cpp')
-rw-r--r--src/toys/parametrics.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/toys/parametrics.cpp b/src/toys/parametrics.cpp
new file mode 100644
index 0000000..2d2538c
--- /dev/null
+++ b/src/toys/parametrics.cpp
@@ -0,0 +1,229 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/affine.h>
+
+#include <glib.h>
+#include <vector>
+#include <iostream>
+using std::vector;
+using namespace Geom;
+
+int mode;
+
+static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double max, double space=10){
+ Piecewise<D2<SBasis> > Mperp = rot90(derivative(M)) * 3;
+ for( double t = M.cuts.front(); t < max; t += space) {
+ Point pos = M(t), perp = Mperp(t);
+ draw_line_seg(cr, pos + perp, pos - perp);
+ }
+ cairo_stroke(cr);
+}
+
+static void draw_axis(cairo_t *cr, Piecewise<D2<SBasis> > const &pw, unsigned d, Affine m) {
+ double mult;
+ if(abs(mode)==1) mult = 20;
+ if(abs(mode)==2) mult = 1;
+ if(abs(mode)==3) mult = 100;
+ if(abs(mode)==4) mult = 20;
+ if(abs(mode)==5) mult = 20;
+ if(abs(mode)==6) mult = 100;
+ for(unsigned i = 0; i < pw.size(); i++) {
+ 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);
+ }
+}
+/*
+void dump_latex(PathVector ps) {
+ for(unsigned d = 0; d < 2; d++) {
+ std::cout << "$$\n" << (d?"y":"x") << "(t) = \\left\\{\n\\begin{array}{ll}\n";
+ int seg = 0;
+ for(unsigned i = 0; i < ps.size(); i++)
+ for(unsigned j = 0; j < ps[i].size(); j++) {
+ Bezier<3> &b = dynamic_cast<Bezier<3>& >(const_cast<Curve&>(ps[i][j]));
+ std::cout << b[0][d] << "(" << seg+1 << "-t)^3 + "
+ << 3*b[1][d] << "t(" << seg+1 << "-t)^2 + "
+ << 3*b[2][d] << "t^2(" << seg+1 << "-t) + "
+ << b[3][d] << "t^3,& " << seg << "\\leq t < " << seg+1 << "\\\\\n";
+ seg++;
+ }
+ std::cout << "\\end{array}\n$$\n";
+ }
+}
+*/
+class Parametrics: public Toy {
+ Piecewise<D2<SBasis> > cat, alcat, box, arc, monk, traj;
+#ifdef USE_TIME
+ GTimer* time;
+ bool st;
+#endif
+ double waitt;
+ double t;
+ int count;
+ void draw(cairo_t *cr,
+ std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override {
+ //double t = handles[0][0] / 20.;
+
+#ifdef USE_TIME
+ gulong* foo = 0;
+ t = g_timer_elapsed(time, foo) * 100;
+#else
+ double inc;
+ if(mode==1) inc = .1;
+ if(mode==2) inc = 5;
+ if(mode==3) inc = .01;
+ if(mode==4) inc = .04;
+ if(mode==5) inc = .1;
+ if(mode==6) inc = .01;
+ if(mode<0) inc = .01*M_PI;
+ if(!save && !waitt) {
+ t += inc;
+ }
+ if(waitt) waitt += 1;
+ if(waitt>20) waitt = 0;
+#endif
+ Piecewise<D2<SBasis> > obj;
+ if(abs(mode)==1) obj = cat;
+ if(abs(mode)==2) obj = alcat;
+ if(abs(mode)==3) obj = arc;
+ if(abs(mode)==4) obj = box;
+ if(abs(mode)==5) obj = monk;
+ if(abs(mode)==6) obj = traj;
+ if(t==obj.cuts.back()) t += inc/2;
+ cairo_set_source_rgb(cr, 1,1,1);
+ if(save) {
+ cairo_rectangle(cr, 0, 0, width, height);
+ cairo_fill(cr);
+ }
+ Piecewise<D2<SBasis> > port, rport;
+ if(mode>0) {
+ port = portion(obj, 0, t);
+ rport = mode>0? portion(obj, t, obj.cuts[obj.size()]) : obj;
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ Point curpt = rport[0].at0();
+ if(t<obj.cuts.back()) {
+ draw_line_seg(cr, curpt, Point(curpt[0], 350));
+ draw_line_seg(cr, curpt, Point(350, curpt[1]));
+ cairo_stroke(cr);
+ }
+
+ char tlab[64];
+ sprintf(tlab, "t=%.02f", t);
+ draw_text(cr, curpt, tlab , true);
+
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_pw_d2_sb(cr, port);
+ cairo_stroke(cr);
+ }
+ if(mode>=0 && t>=obj.cuts.back()+inc) t = 0;
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1);
+ if(mode<0) {
+ draw_axis(cr, obj, 0, from_basis(Point(cos(t),sin(t)),Point(sin(t),-cos(t)),Point(0, 350)));
+ if(cos(t) <= 0) {
+ mode = -mode;
+ t = 0;
+ waitt = 1;
+ }
+ } else
+ draw_axis(cr, rport, 0, from_basis(Point(0,1),Point(1,0),Point(0, 350)));
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
+ if(mode<0)
+ draw_axis(cr, obj, 1, from_basis(Point(1,0),Point(0,1),Point(350*t/M_PI*2, 0)));
+ else
+ draw_axis(cr, rport, 1, from_basis(Point(1,0),Point(0,1),Point(350, 0)));
+ cairo_stroke(cr);
+
+ if(mode==2 && t>0) {
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
+ dot_plot(cr, port, t);
+ cairo_stroke(cr);
+ }
+
+ if(!save) {
+ char file[100];
+ sprintf(file, "output/%04d.png", count);
+ //take_screenshot(file);
+ count++;
+ }
+ // *notify << "pieces = " << alcat.size() << ";\n";
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ redraw();
+ }
+
+#ifdef USE_TIME
+ virtual void mouse_moved(GdkEventMotion* e) {
+ if(st) {
+ g_timer_start(time);
+ st = false;
+ }
+ Toy::mouse_moved(e);
+ }
+#endif
+
+ public:
+ Parametrics(){
+ mode = 2;
+ PathVector cp = read_svgd("cat.svgd");
+ //dump_latex(cp);
+ cat = paths_to_pw(cp);
+ cat *= .3;
+ cat += Point(50, 50);
+ alcat = arc_length_parametrization(cat);
+
+ monk = paths_to_pw(read_svgd("monkey.svgd"));
+ //monk *= .3;
+ monk += Point(50,50);
+
+ arc = sectionize(D2<Piecewise<SBasis> >(cos(Linear(0,M_PI))*120, sin(Linear(0,M_PI))*-120));
+ arc += Point(200, 200);
+
+ box = Piecewise<D2<SBasis> >();
+ box.push_cut(0);
+ box.push(D2<SBasis>(SBasis(100.,300.), SBasis(100.)), 1);
+ box.push(D2<SBasis>(SBasis(300.), SBasis(100.,300.)), 2);
+ box.push(D2<SBasis>(SBasis(300.,100.), SBasis(300.)), 3);
+ box.push(D2<SBasis>(SBasis(100.), SBasis(300.,100.)), 4);
+ //handles.push_back(Point(100, 100));
+ traj = Piecewise<D2<SBasis> >();
+ SBasis quad = Linear(0,1)*Linear(0,1)*256-Linear(0,256)+200;
+ traj.push_cut(0);
+ traj.push(D2<SBasis>(SBasis(100.,300.),SBasis(quad)), 1);
+#ifdef USE_TIME
+ time = g_timer_new();
+ g_timer_reset(time);
+ st = true;
+#endif
+ waitt = 0;
+ count = 0;
+ t = 0;
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Parametrics, 720, 480);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99: