Rust에서 Ramer-Douglas-Peucker 행 단순화 알고리즘을 구현했으며 엡실론 값> 1.0에서 올바르게 작동합니다. 그러나 그보다 작은 값은 스택 오버 플로우를 발생시킵니다. 어떻게 이것을 피하기 위해 함수를 다시 작성할 수 있습니까?이 재귀 함수를 호출 할 때 스택 오버플로를 피하는 방법
// distance formula
pub fn distance(start: &[f64; 2], end: &[f64; 2]) -> f64 {
((start[0] - end[0]).powf(2.) + (start[1] - end[1]).powf(2.)).sqrt()
}
// perpendicular distance from a point to a line
pub fn point_line_distance(point: &[f64; 2], start: &[f64; 2], end: &[f64; 2]) -> f64 {
if start == end {
return distance(*&point, *&start);
} else {
let n = ((end[0] - start[0]) * (start[1] - point[1]) -
(start[0] - point[0]) * (end[1] - start[1]))
.abs();
let d = ((end[0] - start[0]).powf(2.0) + (end[1] - start[1]).powf(2.0)).sqrt();
n/d
}
}
// Ramer–Douglas-Peucker line simplification algorithm
pub fn rdp(points: &[[f64; 2]], epsilon: &f64) -> Vec<[f64; 2]> {
let mut dmax = 1.0;
let mut index: usize = 0;
let mut distance: f64;
for (i, _) in points.iter().enumerate().take(points.len() - 1).skip(1) {
distance = point_line_distance(&points[i],
&*points.first().unwrap(),
&*points.last().unwrap());
if distance > dmax {
index = i;
dmax = distance;
}
}
if dmax > *epsilon {
let mut intermediate = rdp(&points[..index + 1], &*epsilon);
intermediate.pop();
intermediate.extend_from_slice(&rdp(&points[index..], &*epsilon));
intermediate
} else {
vec![*points.first().unwrap(), *points.last().unwrap()]
}
}
fn main() {
let points = vec![[0.0, 0.0], [5.0, 4.0], [11.0, 5.5], [17.3, 3.2], [27.8, 0.1]];
// change this to &0.99 to overflow the stack
let foo: Vec<_> = rdp(&points, &1.0);
assert_eq!(foo, vec![[0.0, 0.0], [5.0, 4.0], [11.0, 5.5], [17.3, 3.2]]);
}
이 [의사 코드] (https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm)에서 'dmax'는 '0'으로 시작합니다. 왜'dmax'를'1.0'으로 시작합니까? – malbarbo
일반적으로 스택 오버플로는 사용자 오류입니다. –
@MatthieuM. 오, 의심의 여지가 없었습니다. 불행히도, 그것은 내 부분에 더 미묘한 오류가 아니었다 ... – urschrei