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