use crate::int::shape::{IntContour, IntShape, IntShapes};
use alloc::vec;
use alloc::vec::Vec;
use i_float::int::point::IntPoint;
pub trait Simplify {
fn simplify_contour(&mut self) -> bool;
}
pub trait SimpleContour {
fn is_simple(&self) -> bool;
fn simplified(&self) -> Option<IntContour>;
}
pub trait SimpleShape {
fn is_simple(&self) -> bool;
fn simplified(&self) -> Option<IntShape>;
}
pub trait SimpleShapes {
fn is_simple(&self) -> bool;
fn simplified(&self) -> IntShapes;
}
impl Simplify for IntContour {
#[inline]
fn simplify_contour(&mut self) -> bool {
if self.is_simple() {
return false;
}
if let Some(contour) = self.simplified() {
self.clear();
self.extend(contour);
} else {
self.clear()
}
true
}
}
impl Simplify for IntShape {
fn simplify_contour(&mut self) -> bool {
let mut any_simplified = false;
let mut any_empty = false;
for (index, contour) in self.iter_mut().enumerate() {
if contour.is_simple() {
continue;
}
any_simplified = true;
if let Some(simple_contour) = contour.simplified() {
contour.clear();
contour.extend(simple_contour);
} else if index == 0 {
self.clear();
return true;
} else {
contour.clear();
any_empty = true;
}
}
if any_empty {
self.retain(|contour| !contour.is_empty());
}
any_simplified
}
}
impl Simplify for IntShapes {
fn simplify_contour(&mut self) -> bool {
let mut any_simplified = false;
let mut any_empty = false;
for shape in self.iter_mut() {
if shape.is_simple() {
continue;
}
any_simplified = true;
if let Some(simple_shape) = shape.simplified() {
*shape = simple_shape;
} else {
shape.clear();
any_empty = true;
}
}
if any_empty {
self.retain(|contour| !contour.is_empty());
}
any_simplified
}
}
impl SimpleShape for [IntContour] {
#[inline]
fn is_simple(&self) -> bool {
for contour in self.iter() {
if !contour.is_simple() {
return false;
}
}
true
}
fn simplified(&self) -> Option<IntShape> {
let mut contours = Vec::with_capacity(self.len());
for (i, contour) in self.iter().enumerate() {
if contour.is_simple() {
contours.push(contour.clone());
} else if let Some(simple) = contour.simplified() {
contours.push(simple);
} else if i == 0 {
return None;
}
}
Some(contours)
}
}
impl SimpleShapes for [IntShape] {
#[inline]
fn is_simple(&self) -> bool {
for shape in self.iter() {
if !shape.is_simple() {
return false;
}
}
true
}
fn simplified(&self) -> IntShapes {
let mut shapes = Vec::with_capacity(self.len());
for shape in self.iter() {
if shape.is_simple() {
shapes.push(shape.clone());
} else if let Some(simple) = shape.simplified() {
shapes.push(simple);
}
}
shapes
}
}
impl SimpleContour for [IntPoint] {
fn is_simple(&self) -> bool {
let count = self.len();
if count < 3 {
return false;
}
let mut p0 = self[count - 2];
let p1 = self[count - 1];
let mut v0 = p1.subtract(p0);
p0 = p1;
for &pi in self.iter() {
let vi = pi.subtract(p0);
let prod = vi.cross_product(v0);
if prod == 0 {
return false;
}
v0 = vi;
p0 = pi;
}
true
}
#[inline]
fn simplified(&self) -> Option<IntContour> {
ContourSimplifier::default().simplify_contour(self)
}
}
#[derive(Default)]
pub struct ContourSimplifier {
nodes: Vec<Node>,
validated: Vec<bool>,
}
impl ContourSimplifier {
pub fn simplify_contour(&mut self, contour: &[IntPoint]) -> Option<IntContour> {
let mut n = contour.len();
if n < 3 {
return None;
}
self.validated.clear();
self.validated.resize(n, false);
self.nodes.clear();
self.nodes.reserve(n);
let mut prev = n - 1;
let mut next = 1;
let last = n - 1;
for index in 0..last {
self.nodes.push(Node { next, index, prev });
prev = index;
next += 1;
}
self.nodes.push(Node {
next: 0,
index: last,
prev,
});
let mut first: usize = 0;
let mut node = self.nodes[first];
let mut i = 0;
while i < n {
if self.validated[node.index] {
node = self.nodes[node.next];
continue;
}
let p0 = contour[node.prev];
let p1 = contour[node.index];
let p2 = contour[node.next];
if p1.subtract(p0).cross_product(p2.subtract(p1)) == 0 {
n -= 1;
if n < 3 {
return None;
}
self.nodes[node.prev].next = node.next;
self.nodes[node.next].prev = node.prev;
if node.index == first {
first = node.next
}
node = self.nodes[node.prev];
if self.validated[node.prev] {
i -= 1;
self.validated[node.prev] = false
}
if self.validated[node.next] {
i -= 1;
self.validated[node.next] = false
}
if self.validated[node.index] {
i -= 1;
self.validated[node.index] = false
}
} else {
self.validated[node.index] = true;
i += 1;
node = self.nodes[node.next];
}
}
let mut buffer = vec![IntPoint::ZERO; n];
node = self.nodes[first];
for item in buffer.iter_mut().take(n) {
*item = contour[node.index];
node = self.nodes[node.next];
}
Some(buffer)
}
}
#[derive(Clone, Copy)]
struct Node {
next: usize,
index: usize,
prev: usize,
}