use alloc::vec::Vec;
use core::{convert::TryFrom, slice};
pub trait Union<T> {
fn union(a: T, b: T) -> Option<T>;
}
use i_overlay::{
core::{fill_rule::FillRule, overlay::Overlay, overlay_rule::OverlayRule},
float::single::SingleFloatOverlay,
i_float::int::point::IntPoint,
i_shape::int::shape::IntShape,
};
use crate::Polygon;
impl<W> Union<Polygon<f32, W>> for Polygon<f32, W> {
fn union(a: Polygon<f32, W>, b: Polygon<f32, W>) -> Option<Polygon<f32, W>> {
let mut subj_shape = Vec::with_capacity(1 + a.interiors.len());
subj_shape.push(a.exterior.clone());
subj_shape.extend(a.interiors.iter().cloned());
let mut clip_shape = Vec::with_capacity(1 + b.interiors.len());
clip_shape.push(b.exterior);
clip_shape.extend(b.interiors);
let union = subj_shape.overlay(&clip_shape, OverlayRule::Union, FillRule::EvenOdd);
if union.len() >= 2 {
return None;
}
let merged_shape = union.first()?;
if merged_shape.is_empty() {
return None;
}
Some(Polygon {
exterior: merged_shape[0].clone(),
interiors: merged_shape[1..].to_vec(),
weight: a.weight,
})
}
}
impl<W> Union<Polygon<f64, W>> for Polygon<f64, W> {
fn union(a: Polygon<f64, W>, b: Polygon<f64, W>) -> Option<Polygon<f64, W>> {
let mut subj_shape = Vec::with_capacity(1 + a.interiors.len());
subj_shape.push(a.exterior.clone());
subj_shape.extend(a.interiors.iter().cloned());
let mut clip_shape = Vec::with_capacity(1 + b.interiors.len());
clip_shape.push(b.exterior);
clip_shape.extend(b.interiors);
let union = subj_shape.overlay(&clip_shape, OverlayRule::Union, FillRule::EvenOdd);
if union.len() >= 2 {
return None;
}
let merged_shape = union.first()?;
if merged_shape.is_empty() {
return None;
}
Some(Polygon {
exterior: merged_shape[0].clone(),
interiors: merged_shape[1..].to_vec(),
weight: a.weight,
})
}
}
impl<W> Union<Polygon<i8, W>> for Polygon<i8, W> {
fn union(a: Polygon<i8, W>, b: Polygon<i8, W>) -> Option<Polygon<i8, W>> {
let to_ring = |ring: Vec<[i8; 2]>| -> Option<Vec<IntPoint>> {
ring.into_iter()
.map(|v| {
Some(IntPoint::new(
i32::try_from(v[0]).ok()?,
i32::try_from(v[1]).ok()?,
))
})
.collect()
};
let mut subj_shape: IntShape = Vec::with_capacity(1 + a.interiors.len());
subj_shape.push(to_ring(a.exterior)?);
for ring in a.interiors {
subj_shape.push(to_ring(ring)?);
}
let mut clip_shape: IntShape = Vec::with_capacity(1 + b.interiors.len());
clip_shape.push(to_ring(b.exterior)?);
for ring in b.interiors {
clip_shape.push(to_ring(ring)?);
}
let union =
Overlay::with_shapes(slice::from_ref(&subj_shape), slice::from_ref(&clip_shape))
.overlay(OverlayRule::Union, FillRule::EvenOdd);
if union.len() >= 2 {
return None;
}
let merged_shape = union.first()?;
if merged_shape.is_empty() {
return None;
}
let from_ring = |ring: &[IntPoint]| -> Option<Vec<[i8; 2]>> {
ring.iter()
.map(|v| Some([i8::try_from(v.x).ok()?, i8::try_from(v.y).ok()?]))
.collect()
};
Some(Polygon {
exterior: from_ring(&merged_shape[0])?,
interiors: merged_shape[1..]
.iter()
.map(|ring| from_ring(ring))
.collect::<Option<Vec<_>>>()?,
weight: a.weight,
})
}
}
impl<W> Union<Polygon<i16, W>> for Polygon<i16, W> {
fn union(a: Polygon<i16, W>, b: Polygon<i16, W>) -> Option<Polygon<i16, W>> {
let to_ring = |ring: Vec<[i16; 2]>| -> Option<Vec<IntPoint>> {
ring.into_iter()
.map(|v| {
Some(IntPoint::new(
i32::try_from(v[0]).ok()?,
i32::try_from(v[1]).ok()?,
))
})
.collect()
};
let mut subj_shape: IntShape = Vec::with_capacity(1 + a.interiors.len());
subj_shape.push(to_ring(a.exterior)?);
for ring in a.interiors {
subj_shape.push(to_ring(ring)?);
}
let mut clip_shape: IntShape = Vec::with_capacity(1 + b.interiors.len());
clip_shape.push(to_ring(b.exterior)?);
for ring in b.interiors {
clip_shape.push(to_ring(ring)?);
}
let union =
Overlay::with_shapes(slice::from_ref(&subj_shape), slice::from_ref(&clip_shape))
.overlay(OverlayRule::Union, FillRule::EvenOdd);
if union.len() >= 2 {
return None;
}
let merged_shape = union.first()?;
if merged_shape.is_empty() {
return None;
}
let from_ring = |ring: &[IntPoint]| -> Option<Vec<[i16; 2]>> {
ring.iter()
.map(|v| Some([i16::try_from(v.x).ok()?, i16::try_from(v.y).ok()?]))
.collect()
};
Some(Polygon {
exterior: from_ring(&merged_shape[0])?,
interiors: merged_shape[1..]
.iter()
.map(|ring| from_ring(ring))
.collect::<Option<Vec<_>>>()?,
weight: a.weight,
})
}
}
impl<W> Union<Polygon<i32, W>> for Polygon<i32, W> {
fn union(a: Polygon<i32, W>, b: Polygon<i32, W>) -> Option<Polygon<i32, W>> {
let mut subj_shape: IntShape = Vec::with_capacity(1 + a.interiors.len());
subj_shape.push(
a.exterior
.iter()
.map(|v| IntPoint::new(v[0], v[1]))
.collect(),
);
subj_shape.extend(
a.interiors
.iter()
.map(|ring| ring.iter().map(|v| IntPoint::new(v[0], v[1])).collect()),
);
let mut clip_shape: IntShape = Vec::with_capacity(1 + b.interiors.len());
clip_shape.push(
b.exterior
.into_iter()
.map(|v| IntPoint::new(v[0], v[1]))
.collect(),
);
clip_shape.extend(b.interiors.into_iter().map(|ring| {
ring.into_iter()
.map(|v| IntPoint::new(v[0], v[1]))
.collect()
}));
let union =
Overlay::with_shapes(slice::from_ref(&subj_shape), slice::from_ref(&clip_shape))
.overlay(OverlayRule::Union, FillRule::EvenOdd);
if union.len() >= 2 {
return None;
}
let merged_shape = union.first()?;
if merged_shape.is_empty() {
return None;
}
Some(Polygon {
exterior: merged_shape[0].iter().map(|v| [v.x, v.y]).collect(),
interiors: merged_shape[1..]
.iter()
.map(|ring| ring.iter().map(|v| [v.x, v.y]).collect())
.collect(),
weight: a.weight,
})
}
}
impl<W> Union<Polygon<i64, W>> for Polygon<i64, W> {
fn union(a: Polygon<i64, W>, b: Polygon<i64, W>) -> Option<Polygon<i64, W>> {
let to_ring = |ring: Vec<[i64; 2]>| -> Option<Vec<IntPoint>> {
ring.into_iter()
.map(|v| {
Some(IntPoint::new(
i32::try_from(v[0]).ok()?,
i32::try_from(v[1]).ok()?,
))
})
.collect()
};
let mut subj_shape: IntShape = Vec::with_capacity(1 + a.interiors.len());
subj_shape.push(to_ring(a.exterior)?);
for ring in a.interiors {
subj_shape.push(to_ring(ring)?);
}
let mut clip_shape: IntShape = Vec::with_capacity(1 + b.interiors.len());
clip_shape.push(to_ring(b.exterior)?);
for ring in b.interiors {
clip_shape.push(to_ring(ring)?);
}
let union =
Overlay::with_shapes(slice::from_ref(&subj_shape), slice::from_ref(&clip_shape))
.overlay(OverlayRule::Union, FillRule::EvenOdd);
if union.len() >= 2 {
return None;
}
let merged_shape = union.first()?;
if merged_shape.is_empty() {
return None;
}
Some(Polygon {
exterior: merged_shape[0]
.iter()
.map(|v| [i64::from(v.x), i64::from(v.y)])
.collect(),
interiors: merged_shape[1..]
.iter()
.map(|ring| {
ring.iter()
.map(|v| [i64::from(v.x), i64::from(v.y)])
.collect()
})
.collect(),
weight: a.weight,
})
}
}