curvedraw
diff src/curve.cc @ 0:8e524989c904
getting there
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 15 Dec 2015 07:15:53 +0200 |
parents | |
children | ce7aa9a0594c |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/curve.cc Tue Dec 15 07:15:53 2015 +0200 1.3 @@ -0,0 +1,144 @@ 1.4 +#include <float.h> 1.5 +#include "curve.h" 1.6 + 1.7 +Curve::Curve(CurveType type) 1.8 +{ 1.9 + this->type = type; 1.10 +} 1.11 + 1.12 +void Curve::set_type(CurveType type) 1.13 +{ 1.14 + this->type = type; 1.15 +} 1.16 + 1.17 +CurveType Curve::get_type() const 1.18 +{ 1.19 + return type; 1.20 +} 1.21 + 1.22 +void Curve::add_point(const Vector2 &p, float weight) 1.23 +{ 1.24 + cp.push_back(Vector3(p.x, p.y, weight)); 1.25 +} 1.26 + 1.27 +bool Curve::remove_point(int idx) 1.28 +{ 1.29 + if(idx < 0 || idx >= (int)cp.size()) { 1.30 + return false; 1.31 + } 1.32 + cp.erase(cp.begin() + idx); 1.33 + return true; 1.34 +} 1.35 + 1.36 +int Curve::nearest_point(const Vector2 &p) 1.37 +{ 1.38 + int res = -1; 1.39 + float bestsq = FLT_MAX; 1.40 + 1.41 + for(size_t i=0; i<cp.size(); i++) { 1.42 + float d = (get_point(i) - p).length_sq(); 1.43 + if(d < bestsq) { 1.44 + bestsq = d; 1.45 + res = i; 1.46 + } 1.47 + } 1.48 + 1.49 + return res; 1.50 +} 1.51 + 1.52 +int Curve::get_point_count() const 1.53 +{ 1.54 + return (int)cp.size(); 1.55 +} 1.56 + 1.57 +const Vector3 &Curve::get_homo_point(int idx) const 1.58 +{ 1.59 + return cp[idx]; 1.60 +} 1.61 + 1.62 +Vector2 Curve::get_point(int idx) const 1.63 +{ 1.64 + return Vector2(cp[idx].x, cp[idx].y); 1.65 +} 1.66 + 1.67 +float Curve::get_weight(int idx) const 1.68 +{ 1.69 + return cp[idx].z; 1.70 +} 1.71 + 1.72 +bool Curve::set_point(int idx, const Vector2 &p, float weight) 1.73 +{ 1.74 + if(idx < 0 || idx >= (int)cp.size()) { 1.75 + return false; 1.76 + } 1.77 + cp[idx] = Vector3(p.x, p.y, weight); 1.78 + return true; 1.79 +} 1.80 + 1.81 +bool Curve::set_weight(int idx, float weight) 1.82 +{ 1.83 + if(idx < 0 || idx >= (int)cp.size()) { 1.84 + return false; 1.85 + } 1.86 + cp[idx].z = weight; 1.87 + return true; 1.88 +} 1.89 + 1.90 +Vector2 Curve::interpolate(float t, CurveType type) const 1.91 +{ 1.92 + int num_cp = (int)cp.size(); 1.93 + if(!num_cp) { 1.94 + return Vector2(0, 0); 1.95 + } 1.96 + if(num_cp == 1) { 1.97 + return Vector2(cp[0].x, cp[0].y); 1.98 + } 1.99 + 1.100 + Vector3 res; 1.101 + int idx0 = (int)floor(t * (num_cp - 1)); 1.102 + int idx1 = idx0 + 1; 1.103 + 1.104 + float dt = 1.0 / (float)(num_cp - 1); 1.105 + float t0 = (float)idx0 * dt; 1.106 + float t1 = (float)idx1 * dt; 1.107 + 1.108 + t = (t - t0) / (t1 - t0); 1.109 + if(t < 0.0) t = 0.0; 1.110 + if(t > 1.0) t = 1.0; 1.111 + 1.112 + if(type == CURVE_LINEAR || num_cp <= 2) { 1.113 + res = lerp(cp[idx0], cp[idx1], t); 1.114 + } else { 1.115 + int idx_prev = idx0 <= 0 ? idx0 : idx0 - 1; 1.116 + int idx_next = idx1 >= num_cp - 1 ? idx1 : idx1 + 1; 1.117 + 1.118 + if(type == CURVE_HERMITE) { 1.119 + res = catmull_rom_spline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t); 1.120 + } else { 1.121 + res = bspline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t); 1.122 + if(res.z != 0.0f) { 1.123 + res.x /= res.z; 1.124 + res.y /= res.z; 1.125 + } 1.126 + } 1.127 + } 1.128 + 1.129 + return Vector2(res.x, res.y); 1.130 +} 1.131 + 1.132 +Vector2 Curve::interpolate(float t) const 1.133 +{ 1.134 + return interpolate(t, type); 1.135 +} 1.136 + 1.137 +Vector2 Curve::operator ()(float t) const 1.138 +{ 1.139 + return interpolate(t); 1.140 +} 1.141 + 1.142 +float Curve::map_param(float x) const 1.143 +{ 1.144 + if(x < 0.0f) x = 0.0f; 1.145 + if(x >= 1.0f) x = 1.0f; 1.146 + return x * ((float)cp.size() - 1); 1.147 +}