Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
/// Largest-Triangle-Three-Buckets (Steinarsson 2013). Same bucket arithmetic,
/// in the same order, as the TypeScript and Python versions and the reference
/// implementation.
///
/// # Panics
/// Panics if `threshold` is less than 3.
pub fn downsample(points: &[Sample], threshold: i64) -> Vec<Sample> {
if threshold < 3 {
panic!("threshold must be a whole number of at least 3, received {}", threshold);
}
let n = points.len();
if threshold as usize >= n {
return points.to_vec();
}
let every = (n - 2) as f64 / (threshold - 2) as f64;
let mut sampled = vec![points[0].clone()];
let mut a = 0usize;
for i in 0..(threshold - 2) as usize {
let avg_start = ((i + 1) as f64 * every).floor() as usize + 1;
let avg_end = (((i + 2) as f64 * every).floor() as usize + 1).min(n);
let mut avg_x = 0.0;
let mut avg_y = 0.0;
for p in &points[avg_start..avg_end] {
avg_x += p.x;
avg_y += p.y;
}
avg_x /= (avg_end - avg_start) as f64;
avg_y /= (avg_end - avg_start) as f64;
let from = (i as f64 * every).floor() as usize + 1;
let to = ((i + 1) as f64 * every).floor() as usize + 1;
let ax = points[a].x;
let ay = points[a].y;
let mut max_area = -1.0;
let mut next = from;
for j in from..to {
let area = ((ax - avg_x) * (points[j].y - ay) - (ax - points[j].x) * (avg_y - ay)).abs();
if area > max_area {
max_area = area;
next = j;
}
}
sampled.push(points[next].clone());
a = next;
}
sampled.push(points[n - 1].clone());
sampled
}
pub fn sample_from_value(v: &Value) -> Sample {
Sample { x: v.get("x").as_f64(), y: v.get("y").as_f64() }
}
pub fn sample_to_value(s: &Sample) -> Value {
Value::obj(vec![("x", Value::Float(s.x)), ("y", Value::Float(s.y))])
}
pub fn fune_vector(args: &[Value]) -> Value {
let points: Vec<Sample> = args[0].as_arr().iter().map(sample_from_value).collect();
Value::Arr(downsample(&points, args[1].as_i64()).iter().map(sample_to_value).collect())
}