summaryrefslogtreecommitdiffstats
path: root/src/toys/pwsbhandle.cpp
blob: ce4f21ed369a2a2f78c20199dc604ad3838a923f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class PWSBHandle : public Handle{
public:
    unsigned handles_per_curve, curve_size, segs;
    PWSBHandle()  {}
    PWSBHandle(unsigned cs, unsigned segs) :handles_per_curve(cs*segs),curve_size(cs), segs(segs) {}
    std::vector<Geom::Point> pts;
    virtual void draw(cairo_t *cr, bool annotes = false);
  
    virtual void* hit(Geom::Point mouse);
    virtual void move_to(void* hit, Geom::Point om, Geom::Point m);
    void push_back(double x, double y) {pts.push_back(Geom::Point(x,y));}
    Piecewise<SBasis> value(double y_0=150) {
        Piecewise<SBasis> pws;
	Point* base = &pts[0];
	for(unsigned i = 0; i < handles_per_curve; i+=curve_size) {
	    pws.push_cut(base[i][0]);
	    //Bad hack to move 0 to 150
	    for(unsigned j = i; j < i + curve_size; j++)
		base[j] = Point(base[j][0], base[j][1] - y_0);
	    pws.push_seg( Geom::handles_to_sbasis(base+i, curve_size-1)[1]);
	    for(unsigned j = i; j < i + curve_size; j++)
		base[j] = Point(base[j][0], base[j][1] + y_0);
	}
	pws.push_cut(base[handles_per_curve - 1][0]);
	assert(pws.invariants());
	return pws;
    }
    virtual void load(FILE* f);
    virtual void save(FILE* f);
};

void PWSBHandle::draw(cairo_t *cr, bool /*annotes*/) {
    for(auto & pt : pts) {
	draw_circ(cr, pt);
    }
}

void* PWSBHandle::hit(Geom::Point mouse) {
    for(auto & pt : pts) {
	if(Geom::distance(mouse, pt) < 5)
	    return (void*)(&pt);
    }
    return 0;
}

void PWSBHandle::move_to(void* hit, Geom::Point /*om*/, Geom::Point m) {
    if(hit) {
	*(Geom::Point*)hit = m;
	Point* base = &pts[0];
	for(unsigned i = curve_size; i < handles_per_curve; i+=curve_size) {
	    base[i-1][0] = base[i][0];
	}
	for(unsigned i = 0; i < handles_per_curve; i+=curve_size) {
	    for(unsigned j = 1; j < (curve_size-1); j++) {
                double t = float(j)/(curve_size-1);
		base[i+j][0] = (1 - t)*base[i][0] + t*base[i+curve_size-1][0];
            }
	}
    }
}

void PWSBHandle::load(FILE* f) {
    unsigned n = 0;
    assert(3 == fscanf(f, "%d %d %d\n", &curve_size, &segs, &n));
    assert(n == curve_size*segs);
    pts.clear();
    for(unsigned i = 0; i < n; i++) {
	pts.push_back(read_point(f));
    }
}

void PWSBHandle::save(FILE* f) {
    fprintf(f, "%d %d %lu\n", curve_size, segs, pts.size());
    for(auto & pt : pts) {
	fprintf(f, "%lf %lf\n", pt[0], pt[1]);
    }
}