macro_rules! define_paths_blob_iter {
(
$(#[$iter_meta:meta])*
$vis:vis $Iter:ident,
point = $Pt:ty,
path = $Path:ty,
blob = $Blob:ty,
conv_slice = $conv:path,
) => {
$(#[$iter_meta])*
#[derive(Clone, Copy)]
$vis struct $Iter<'a> {
points: &'a [$Pt],
path_starts: &'a [usize],
idx: usize,
}
impl<'a> $Iter<'a> {
pub(crate) fn new(blob: &'a $Blob) -> Self {
Self {
points: &blob.points,
path_starts: &blob.path_starts,
idx: 0,
}
}
}
impl<'a> Iterator for $Iter<'a> {
type Item = $Path;
fn next(&mut self) -> Option<Self::Item> {
let i = self.idx;
if i + 1 >= self.path_starts.len() {
return None;
}
let a = self.path_starts[i];
let e = self.path_starts[i + 1];
self.idx += 1;
Some($conv(&self.points[a..e]))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let total = self.path_starts.len().saturating_sub(1);
let left = total.saturating_sub(self.idx);
(left, Some(left))
}
}
impl<'a> ExactSizeIterator for $Iter<'a> {}
impl<'a> std::iter::FusedIterator for $Iter<'a> {}
};
}
macro_rules! define_lazy_paths {
(
$(#[$lazy_meta:meta])*
$Lazy:ident,
blob = $Blob:ty,
paths = $Paths:ty,
path = $Path:ty,
iter = $Iter:ident,
from_blob = $from_blob:path,
) => {
$(#[$lazy_meta])*
#[derive(Clone, Debug, Default)]
pub struct $Lazy {
blob: $Blob,
}
impl $Lazy {
pub(crate) fn from_blob(blob: $Blob) -> Self {
Self { blob }
}
#[inline]
pub fn iter(&self) -> $Iter<'_> {
$Iter::new(&self.blob)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.blob.path_starts.len() < 2
}
pub fn into_paths(self) -> $Paths {
$from_blob(self.blob)
}
pub fn to_paths(&self) -> $Paths {
self.iter().collect()
}
pub fn into_first_path(self) -> $Path {
self.iter().next().unwrap_or_default()
}
}
impl<'a> IntoIterator for &'a $Lazy {
type Item = $Path;
type IntoIter = $Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
};
}
macro_rules! define_poly_cxx_preorder_64 {
() => {
#[derive(Clone, Debug)]
pub struct PolyCxxNode64 {
pub depth: usize,
pub is_hole: bool,
pub path: crate::Path64,
}
pub struct PolyCxxPreorderIter64 {
stack: Vec<(usize, usize)>,
root_to_free: Option<usize>,
}
impl PolyCxxPreorderIter64 {
pub(crate) fn new(root: usize) -> Self {
if root == 0 {
return Self {
stack: Vec::new(),
root_to_free: None,
};
}
Self {
stack: vec![(root, 0)],
root_to_free: Some(root),
}
}
}
impl Iterator for PolyCxxPreorderIter64 {
type Item = PolyCxxNode64;
fn next(&mut self) -> Option<Self::Item> {
use crate::paths_blob::path64_from_single_paths_blob;
let (n, depth) = self.stack.pop()?;
let is_hole = crate::cxx_bridge::clipper2_sys_cxx::cxx_poly64_is_hole(n);
let blob = crate::cxx_bridge::clipper2_sys_cxx::cxx_poly64_polygon(n);
let path = path64_from_single_paths_blob(blob);
let nc = crate::cxx_bridge::clipper2_sys_cxx::cxx_poly64_child_count(n) as usize;
for i in (0..nc).rev() {
let c = crate::cxx_bridge::clipper2_sys_cxx::cxx_poly64_child_at(n, i);
self.stack.push((c, depth + 1));
}
Some(PolyCxxNode64 {
depth,
is_hole,
path,
})
}
}
impl Drop for PolyCxxPreorderIter64 {
fn drop(&mut self) {
if let Some(r) = self.root_to_free.take() {
if r != 0 {
crate::cxx_bridge::clipper2_sys_cxx::cxx_poly64_delete(r);
}
}
}
}
};
}
macro_rules! define_poly_cxx_preorder_d {
() => {
#[derive(Clone, Debug)]
pub struct PolyCxxNodeD {
pub depth: usize,
pub is_hole: bool,
pub scale: f64,
pub path: crate::PathD,
}
pub struct PolyCxxPreorderIterD {
stack: Vec<(usize, usize)>,
root_to_free: Option<usize>,
}
impl PolyCxxPreorderIterD {
pub(crate) fn new(root: usize) -> Self {
if root == 0 {
return Self {
stack: Vec::new(),
root_to_free: None,
};
}
Self {
stack: vec![(root, 0)],
root_to_free: Some(root),
}
}
}
impl Iterator for PolyCxxPreorderIterD {
type Item = PolyCxxNodeD;
fn next(&mut self) -> Option<Self::Item> {
use crate::paths_blob::pathd_from_single_paths_blob;
let (n, depth) = self.stack.pop()?;
let is_hole = crate::cxx_bridge::clipper2_sys_cxx::cxx_polyd_is_hole(n);
let scale = crate::cxx_bridge::clipper2_sys_cxx::cxx_polyd_scale(n);
let blob = crate::cxx_bridge::clipper2_sys_cxx::cxx_polyd_polygon(n);
let path = pathd_from_single_paths_blob(blob);
let nc = crate::cxx_bridge::clipper2_sys_cxx::cxx_polyd_child_count(n) as usize;
for i in (0..nc).rev() {
let c = crate::cxx_bridge::clipper2_sys_cxx::cxx_polyd_child_at(n, i);
self.stack.push((c, depth + 1));
}
Some(PolyCxxNodeD {
depth,
is_hole,
scale,
path,
})
}
}
impl Drop for PolyCxxPreorderIterD {
fn drop(&mut self) {
if let Some(r) = self.root_to_free.take() {
if r != 0 {
crate::cxx_bridge::clipper2_sys_cxx::cxx_polyd_delete(r);
}
}
}
}
};
}
macro_rules! impl_path_geom {
(int64, $Path:ident, $Point:ident) => {
impl $Path {
#[inline]
pub fn from_vec(points: Vec<$Point>) -> Self {
Self(points)
}
#[inline]
pub fn new(points: impl Into<Vec<$Point>>) -> Self {
Self(points.into())
}
#[inline]
pub fn as_slice(&self) -> &[$Point] {
&self.0
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [$Point] {
&mut self.0
}
#[inline]
pub fn iter(&self) -> std::slice::Iter<'_, $Point> {
self.0.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, $Point> {
self.0.iter_mut()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn get_point(&self, index: usize) -> $Point {
self.0[index]
}
pub fn add_point(&mut self, point: $Point) {
self.0.push(point)
}
pub fn translate(&self, dx: i64, dy: i64) -> Self {
let n = self.0.len();
let mut new_points = Vec::with_capacity(n);
new_points.extend(self.0.iter().map(|p| $Point {
x: p.x + dx,
y: p.y + dy,
}));
Self(new_points)
}
pub fn scale(&self, sx: f64, sy: f64) -> Self {
let mut _sx = sx;
if _sx == 0. {
_sx = 1.;
}
let mut _sy = sy;
if _sy == 0. {
_sy = 1.;
}
let n = self.0.len();
let mut new_points = Vec::with_capacity(n);
new_points.extend(self.0.iter().map(|p| $Point {
x: ((p.x as f64) * _sx) as i64,
y: ((p.y as f64) * _sy) as i64,
}));
Self(new_points)
}
}
impl<'a> IntoIterator for &'a $Path {
type Item = &'a $Point;
type IntoIter = std::slice::Iter<'a, $Point>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for $Path {
type Item = $Point;
type IntoIter = std::vec::IntoIter<$Point>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
};
(float, $Path:ident, $Point:ident) => {
impl $Path {
#[inline]
pub fn from_vec(points: Vec<$Point>) -> Self {
Self(points)
}
#[inline]
pub fn new(points: impl Into<Vec<$Point>>) -> Self {
Self(points.into())
}
#[inline]
pub fn as_slice(&self) -> &[$Point] {
&self.0
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [$Point] {
&mut self.0
}
#[inline]
pub fn iter(&self) -> std::slice::Iter<'_, $Point> {
self.0.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, $Point> {
self.0.iter_mut()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn get_point(&self, index: usize) -> $Point {
self.0[index]
}
pub fn add_point(&mut self, point: $Point) {
self.0.push(point)
}
pub fn translate(&self, dx: f64, dy: f64) -> Self {
let n = self.0.len();
let mut new_points = Vec::with_capacity(n);
new_points.extend(self.0.iter().map(|p| $Point {
x: p.x + dx,
y: p.y + dy,
}));
Self(new_points)
}
pub fn scale(&self, sx: f64, sy: f64) -> Self {
let mut _sx = sx;
if _sx == 0. {
_sx = 1.;
}
let mut _sy = sy;
if _sy == 0. {
_sy = 1.;
}
let n = self.0.len();
let mut new_points = Vec::with_capacity(n);
new_points.extend(self.0.iter().map(|p| $Point {
x: p.x * _sx,
y: p.y * _sy,
}));
Self(new_points)
}
}
impl<'a> IntoIterator for &'a $Path {
type Item = &'a $Point;
type IntoIter = std::slice::Iter<'a, $Point>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for $Path {
type Item = $Point;
type IntoIter = std::vec::IntoIter<$Point>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
};
}
macro_rules! impl_paths_collection {
(int64, $Paths:ident, $Path:ty) => {
impl $Paths {
#[inline]
pub(crate) fn from_vec(paths: Vec<$Path>) -> Self {
Self(paths)
}
#[inline]
pub fn new(paths: impl Into<Vec<$Path>>) -> Self {
Self(paths.into())
}
#[inline]
pub fn as_slice(&self) -> &[$Path] {
&self.0
}
#[inline]
pub fn path(&self, index: usize) -> &$Path {
&self.0[index]
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn add_path(&mut self, path: $Path) {
self.0.push(path)
}
pub fn add_paths(&mut self, paths: impl IntoIterator<Item = $Path>) {
self.0.extend(paths)
}
pub fn to_vec(&self) -> Vec<$Path> {
self.0.clone()
}
pub fn translate(&self, dx: i64, dy: i64) -> Self {
let n = self.0.len();
let mut new_paths = Vec::with_capacity(n);
new_paths.extend(self.0.iter().map(|p| p.translate(dx, dy)));
Self(new_paths)
}
pub fn scale(&self, sx: f64, sy: f64) -> Self {
let n = self.0.len();
let mut new_paths = Vec::with_capacity(n);
new_paths.extend(self.0.iter().map(|p| p.scale(sx, sy)));
Self(new_paths)
}
}
impl FromIterator<$Path> for $Paths {
fn from_iter<T: IntoIterator<Item = $Path>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
};
(float, $Paths:ident, $Path:ty) => {
impl $Paths {
#[inline]
pub(crate) fn from_vec(paths: Vec<$Path>) -> Self {
Self(paths)
}
#[inline]
pub fn new(paths: impl Into<Vec<$Path>>) -> Self {
Self(paths.into())
}
#[inline]
pub fn as_slice(&self) -> &[$Path] {
&self.0
}
#[inline]
pub fn path(&self, index: usize) -> &$Path {
&self.0[index]
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn add_path(&mut self, path: $Path) {
self.0.push(path)
}
pub fn add_paths(&mut self, paths: impl IntoIterator<Item = $Path>) {
self.0.extend(paths)
}
pub fn to_vec(&self) -> Vec<$Path> {
self.0.clone()
}
pub fn translate(&self, dx: f64, dy: f64) -> Self {
let n = self.0.len();
let mut new_paths = Vec::with_capacity(n);
new_paths.extend(self.0.iter().map(|p| p.translate(dx, dy)));
Self(new_paths)
}
pub fn scale(&self, sx: f64, sy: f64) -> Self {
let n = self.0.len();
let mut new_paths = Vec::with_capacity(n);
new_paths.extend(self.0.iter().map(|p| p.scale(sx, sy)));
Self(new_paths)
}
}
impl FromIterator<$Path> for $Paths {
fn from_iter<T: IntoIterator<Item = $Path>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
};
}