use crate::core::{is_positive, scale_path, scale_paths, Path64, PathD, Paths64, PathsD};
use crate::engine::ClipType;
use crate::engine_public::Clipper64;
use crate::FillRule;
fn minkowski_internal(pattern: &Path64, path: &Path64, is_sum: bool, is_closed: bool) -> Paths64 {
let delta: usize = if is_closed { 0 } else { 1 };
let pat_len = pattern.len();
let path_len = path.len();
if pat_len == 0 || path_len == 0 {
return Paths64::new();
}
let mut tmp: Vec<Path64> = Vec::with_capacity(path_len);
if is_sum {
for p in path.iter() {
let path2: Path64 = pattern.iter().map(|pt2| *p + *pt2).collect();
tmp.push(path2);
}
} else {
for p in path.iter() {
let path2: Path64 = pattern.iter().map(|pt2| *p - *pt2).collect();
tmp.push(path2);
}
}
let result_capacity = (path_len - delta) * pat_len;
let mut result: Paths64 = Vec::with_capacity(result_capacity);
let mut g: usize = if is_closed { path_len - 1 } else { 0 };
let mut i = delta;
while i < path_len {
let mut h: usize = pat_len - 1;
for j in 0..pat_len {
let mut quad: Path64 = vec![tmp[g][h], tmp[i][h], tmp[i][j], tmp[g][j]];
if !is_positive(&quad) {
quad.reverse();
}
result.push(quad);
h = j;
}
g = i;
i += 1;
}
result
}
fn union_paths(subjects: &Paths64, fill_rule: FillRule) -> Paths64 {
let mut result = Paths64::new();
let mut clipper = Clipper64::new();
clipper.add_subject(subjects);
clipper.execute(ClipType::Union, fill_rule, &mut result, None);
result
}
pub fn minkowski_sum(pattern: &Path64, path: &Path64, is_closed: bool) -> Paths64 {
union_paths(
&minkowski_internal(pattern, path, true, is_closed),
FillRule::NonZero,
)
}
pub fn minkowski_sum_d(
pattern: &PathD,
path: &PathD,
is_closed: bool,
decimal_places: i32,
) -> PathsD {
let mut error_code: i32 = 0;
let scale = 10f64.powi(decimal_places);
let pat64: Path64 = scale_path(pattern, scale, scale, &mut error_code);
let path64: Path64 = scale_path(path, scale, scale, &mut error_code);
let tmp = union_paths(
&minkowski_internal(&pat64, &path64, true, is_closed),
FillRule::NonZero,
);
let inv_scale = 1.0 / scale;
scale_paths(&tmp, inv_scale, inv_scale, &mut error_code)
}
pub fn minkowski_diff(pattern: &Path64, path: &Path64, is_closed: bool) -> Paths64 {
union_paths(
&minkowski_internal(pattern, path, false, is_closed),
FillRule::NonZero,
)
}
pub fn minkowski_diff_d(
pattern: &PathD,
path: &PathD,
is_closed: bool,
decimal_places: i32,
) -> PathsD {
let mut error_code: i32 = 0;
let scale = 10f64.powi(decimal_places);
let pat64: Path64 = scale_path(pattern, scale, scale, &mut error_code);
let path64: Path64 = scale_path(path, scale, scale, &mut error_code);
let tmp = union_paths(
&minkowski_internal(&pat64, &path64, false, is_closed),
FillRule::NonZero,
);
let inv_scale = 1.0 / scale;
scale_paths(&tmp, inv_scale, inv_scale, &mut error_code)
}
#[cfg(test)]
#[path = "minkowski_tests.rs"]
mod tests;