curvedraw
view src/curve.cc @ 6:6e980fddbf3b
curve export
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 18 Dec 2015 07:07:19 +0200 |
parents | ce7aa9a0594c |
children | 84a647283237 |
line source
1 #include <float.h>
2 #include <algorithm>
3 #include "curve.h"
5 Curve::Curve(CurveType type)
6 {
7 this->type = type;
8 }
10 void Curve::set_type(CurveType type)
11 {
12 this->type = type;
13 }
15 CurveType Curve::get_type() const
16 {
17 return type;
18 }
20 void Curve::add_point(const Vector2 &p, float weight)
21 {
22 cp.push_back(Vector3(p.x, p.y, weight));
23 }
25 bool Curve::remove_point(int idx)
26 {
27 if(idx < 0 || idx >= (int)cp.size()) {
28 return false;
29 }
30 cp.erase(cp.begin() + idx);
31 return true;
32 }
34 int Curve::nearest_point(const Vector2 &p)
35 {
36 int res = -1;
37 float bestsq = FLT_MAX;
39 for(size_t i=0; i<cp.size(); i++) {
40 float d = (get_point(i) - p).length_sq();
41 if(d < bestsq) {
42 bestsq = d;
43 res = i;
44 }
45 }
47 return res;
48 }
50 bool Curve::empty() const
51 {
52 return cp.empty();
53 }
55 int Curve::size() const
56 {
57 return (int)cp.size();
58 }
60 Vector3 &Curve::operator [](int idx)
61 {
62 return cp[idx];
63 }
65 const Vector3 &Curve::operator [](int idx) const
66 {
67 return cp[idx];
68 }
70 const Vector3 &Curve::get_homo_point(int idx) const
71 {
72 return cp[idx];
73 }
75 Vector2 Curve::get_point(int idx) const
76 {
77 return Vector2(cp[idx].x, cp[idx].y);
78 }
80 float Curve::get_weight(int idx) const
81 {
82 return cp[idx].z;
83 }
85 bool Curve::set_point(int idx, const Vector2 &p, float weight)
86 {
87 if(idx < 0 || idx >= (int)cp.size()) {
88 return false;
89 }
90 cp[idx] = Vector3(p.x, p.y, weight);
91 return true;
92 }
94 bool Curve::set_weight(int idx, float weight)
95 {
96 if(idx < 0 || idx >= (int)cp.size()) {
97 return false;
98 }
99 cp[idx].z = weight;
100 return true;
101 }
103 bool Curve::move_point(int idx, const Vector2 &p)
104 {
105 if(idx < 0 || idx >= (int)cp.size()) {
106 return false;
107 }
108 cp[idx] = Vector3(p.x, p.y, cp[idx].z);
109 return true;
110 }
112 Vector2 Curve::interpolate(float t, CurveType type) const
113 {
114 if(cp.empty()) {
115 return Vector2(0, 0);
116 }
118 int num_cp = (int)cp.size();
119 if(num_cp == 1) {
120 return Vector2(cp[0].x, cp[0].y);
121 }
123 Vector3 res;
124 int idx0 = std::min((int)floor(t * (num_cp - 1)), num_cp - 2);
125 int idx1 = idx0 + 1;
127 float dt = 1.0 / (float)(num_cp - 1);
128 float t0 = (float)idx0 * dt;
129 float t1 = (float)idx1 * dt;
131 t = (t - t0) / (t1 - t0);
132 if(t < 0.0) t = 0.0;
133 if(t > 1.0) t = 1.0;
135 if(type == CURVE_LINEAR || num_cp <= 2) {
136 res = lerp(cp[idx0], cp[idx1], t);
137 } else {
138 int idx_prev = idx0 <= 0 ? idx0 : idx0 - 1;
139 int idx_next = idx1 >= num_cp - 1 ? idx1 : idx1 + 1;
141 if(type == CURVE_HERMITE) {
142 res = catmull_rom_spline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t);
143 } else {
144 res = bspline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t);
145 if(res.z != 0.0f) {
146 res.x /= res.z;
147 res.y /= res.z;
148 }
149 }
150 }
152 return Vector2(res.x, res.y);
153 }
155 Vector2 Curve::interpolate(float t) const
156 {
157 return interpolate(t, type);
158 }
160 Vector2 Curve::operator ()(float t) const
161 {
162 return interpolate(t);
163 }