Skip to content

Commit

Permalink
feat: add bounds struct to path/paths
Browse files Browse the repository at this point in the history
Adds Bounds struct that gives information about the
min/max cut coordinates of a Path or Paths struct.
  • Loading branch information
tirithen committed Apr 30, 2024
1 parent 39ea7a1 commit 3d541f8
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 2 deletions.
45 changes: 45 additions & 0 deletions src/bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::Point;

/// Represents an area from one min and one max [Point](struct.Point.html).
#[derive(Default, Debug, Copy, Clone, PartialEq)]
pub struct Bounds {
/// Minimum point of the boundary.
pub min: Point,
/// Maximum point of the boundary.
pub max: Point,
}

impl Bounds {
/// Create a `Bounds` struct starting at xy 0.0 and ending at the given xy
/// coordinates.
#[must_use]
pub fn new(x: f64, y: f64) -> Self {
Self {
min: Point::new(0.0, 0.0),
max: Point::new(x, y),
}
}

/// Create a `Bounds` struct using xy maximum value as min and minimum value
/// for max.
#[must_use]
pub fn minmax() -> Self {
Self {
min: Point::MAX,
max: Point::MIN,
}
}

/// Return the size of the bounds area as a [Point](struct.Point.html).
#[must_use]
pub fn size(&self) -> Point {
Point::new(self.max.x() - self.min.x(), self.max.y() - self.min.y())
}

/// Return the center of the bounds area as a [Point](struct.Point.html).
#[must_use]
pub fn center(&self) -> Point {
let size = self.size();
Point::new(self.min.x() + size.x() / 2.0, self.min.y() + size.y() / 2.0)
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@
//! [examples](https://github.com/tirithen/clipper2/tree/main/examples)
//! directory.

mod bounds;
mod clipper;
mod operations;
mod options;
mod path;
mod paths;
mod point;

pub use crate::bounds::*;
pub use crate::clipper::*;
pub use crate::operations::*;
pub use crate::options::*;
Expand Down
35 changes: 34 additions & 1 deletion src/path.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clipper2c_sys::{clipper_path64_of_points, clipper_path64_size, ClipperPath64, ClipperPoint64};

use crate::{malloc, Centi, Point, PointScaler};
use crate::{malloc, Bounds, Centi, Point, PointScaler};

/// A collection of points.
///
Expand Down Expand Up @@ -31,6 +31,11 @@ impl<P: PointScaler> Path<P> {
self.0.is_empty()
}

/// Returns `true` if the path contains at least one point
pub fn contains_points(&self) -> bool {
self.is_empty()
}

/// Returns an iterator over the points in the path.
pub fn iter(&self) -> PathIterator<P> {
PathIterator {
Expand All @@ -39,6 +44,34 @@ impl<P: PointScaler> Path<P> {
}
}

/// Returns the bounds for this path.
pub fn bounds(&self) -> Bounds {
let mut bounds = Bounds::minmax();

for p in &self.0 {
let x = p.x();
let y = p.y();

if x < bounds.min.x() {
bounds.min = Point::new(x, bounds.min.y());
}

if y < bounds.min.y() {
bounds.min = Point::new(bounds.min.x(), y);
}

if x > bounds.max.x() {
bounds.max = Point::new(x, bounds.max.y());
}

if y > bounds.max.y() {
bounds.max = Point::new(bounds.max.x(), y);
}
}

bounds
}

pub(crate) unsafe fn to_clipperpath64(&self) -> *mut ClipperPath64 {
let mem = malloc(clipper_path64_size());
clipper_path64_of_points(
Expand Down
44 changes: 43 additions & 1 deletion src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use clipper2c_sys::{
ClipperPaths64,
};

use crate::{malloc, Centi, Path, Point, PointScaler};
use crate::{malloc, Bounds, Centi, Path, Point, PointScaler};

/// A collection of paths.
///
Expand Down Expand Up @@ -35,6 +35,17 @@ impl<P: PointScaler> Paths<P> {
self.0.is_empty()
}

/// Returns `true` if at least one of the paths contains a point
pub fn contains_points(&self) -> bool {
for path in &self.0 {
if !path.is_empty() {
return true;
}
}

false
}

/// Returns an iterator over the paths in the paths.
pub fn iter(&self) -> PathsIterator<P> {
PathsIterator {
Expand All @@ -43,6 +54,37 @@ impl<P: PointScaler> Paths<P> {
}
}

/// Returns the bounds for this path.
pub fn bounds(&self) -> Bounds {
let mut bounds = Bounds::minmax();

for p in &self.0 {
let b = p.bounds();
let min_x = b.min.x();
let min_y = b.min.y();
let max_x = b.max.x();
let max_y = b.max.y();

if min_x < bounds.min.x() {
bounds.min = Point::new(min_x, bounds.min.y());
}

if min_y < bounds.min.y() {
bounds.min = Point::new(bounds.min.x(), min_y);
}

if max_x > bounds.max.x() {
bounds.max = Point::new(max_x, bounds.max.y());
}

if max_y > bounds.max.y() {
bounds.max = Point::new(bounds.max.x(), max_y);
}
}

bounds
}

pub(crate) fn from_clipperpaths64(ptr: *mut ClipperPaths64) -> Self {
let paths = unsafe {
let len: i32 = clipper_paths64_length(ptr).try_into().unwrap();
Expand Down
18 changes: 18 additions & 0 deletions src/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,24 @@ impl<P: PointScaler> Point<P> {
/// The zero point.
pub const ZERO: Self = Self(ClipperPoint64 { x: 0, y: 0 }, PhantomData);

/// The minimum value for a point.
pub const MIN: Self = Self(
ClipperPoint64 {
x: i64::MIN,
y: i64::MIN,
},
PhantomData,
);

/// The maximum value for a point.
pub const MAX: Self = Self(
ClipperPoint64 {
x: i64::MAX,
y: i64::MAX,
},
PhantomData,
);

/// Create a new point.
pub fn new(x: f64, y: f64) -> Self {
Self(
Expand Down

0 comments on commit 3d541f8

Please sign in to comment.