Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions iOverlay/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "i_overlay"
version = "5.0.0"
version = "6.0.0"
authors = ["Nail Sharipov <nailxsharipov@gmail.com>"]
edition = "2024"
rust-version = "1.88"
Expand All @@ -12,8 +12,8 @@ readme = "README.md"
categories = ["algorithms", "graphics", "science::geo", "mathematics", "no-std"]

[dependencies]
i_float = { version = "~1.16.0" }
i_shape = { version = "~1.18.0" }
i_float = { version = "^2.0.0" }
i_shape = { version = "^2.0.0" }
i_tree = { version = "^0.18.0" }
i_key_sort = { version = "^0.10.1" }

Expand All @@ -38,5 +38,5 @@ serde_json = "^1.0"
rand = { version = "~0.10", features = ["alloc"] }
#i_float = { path = "../../iFloat", features = ["serde"] }
#i_shape = { path = "../../iShape", features = ["serde"] }
i_float = { version = "~1.16.0", features = ["serde"] }
i_shape = { version = "~1.18.0", features = ["serde"] }
i_float = { version = "^2.0.0", features = ["serde"] }
i_shape = { version = "~2.0.0", features = ["serde"] }
25 changes: 11 additions & 14 deletions iOverlay/src/float/clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ use crate::float::scale::FixedScaleOverlayError;
use crate::float::string_overlay::FloatStringOverlay;
use crate::string::clip::ClipRule;
use i_float::float::compatible::FloatPointCompatible;
use i_float::float::number::FloatNumber;
use i_shape::base::data::Paths;
use i_shape::source::resource::ShapeResource;

pub trait FloatClip<R, P, T>
pub trait FloatClip<R, P>
where
R: ShapeResource<P, T>,
P: FloatPointCompatible<T>,
T: FloatNumber,
R: ShapeResource<P>,
P: FloatPointCompatible,
{
/// Clips paths according to the specified build and clip rules.
/// - `resource`: A clipping shape.
Expand Down Expand Up @@ -44,7 +42,7 @@ where
source: &R,
fill_rule: FillRule,
clip_rule: ClipRule,
scale: T,
scale: P::Scalar,
) -> Result<Paths<P>, FixedScaleOverlayError>;

/// Clips paths according to the specified build and clip rules.
Expand Down Expand Up @@ -86,7 +84,7 @@ where
fill_rule: FillRule,
clip_rule: ClipRule,
solver: Solver,
scale: T,
scale: P::Scalar,
) -> Result<Paths<P>, FixedScaleOverlayError>;
}

Expand Down Expand Up @@ -146,12 +144,11 @@ mod tests {
}
}

impl<R0, R1, P, T> FloatClip<R0, P, T> for R1
impl<R0, R1, P> FloatClip<R0, P> for R1
where
R0: ShapeResource<P, T>,
R1: ShapeResource<P, T>,
P: FloatPointCompatible<T>,
T: FloatNumber,
R0: ShapeResource<P>,
R1: ShapeResource<P>,
P: FloatPointCompatible,
{
#[inline]
fn clip_by(&self, resource: &R0, fill_rule: FillRule, clip_rule: ClipRule) -> Paths<P> {
Expand All @@ -176,7 +173,7 @@ where
resource: &R0,
fill_rule: FillRule,
clip_rule: ClipRule,
scale: T,
scale: P::Scalar,
) -> Result<Paths<P>, FixedScaleOverlayError> {
self.clip_by_fixed_scale_with_solver(resource, fill_rule, clip_rule, Default::default(), scale)
}
Expand All @@ -188,7 +185,7 @@ where
fill_rule: FillRule,
clip_rule: ClipRule,
solver: Solver,
scale: T,
scale: P::Scalar,
) -> Result<Paths<P>, FixedScaleOverlayError> {
Ok(
FloatStringOverlay::with_shape_and_string_fixed_scale(resource, self, scale)?
Expand Down
9 changes: 4 additions & 5 deletions iOverlay/src/float/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::core::graph::OverlayGraph;
use crate::core::overlay_rule::OverlayRule;
use i_float::adapter::FloatPointAdapter;
use i_float::float::compatible::FloatPointCompatible;
use i_float::float::number::FloatNumber;
use i_shape::base::data::Shapes;
use i_shape::float::adapter::ShapesToFloat;
use i_shape::float::despike::DeSpikeContour;
Expand All @@ -16,15 +15,15 @@ use i_shape::float::simple::SimplifyContour;
/// The `FloatOverlayGraph` struct represents an overlay graph with floating point precision,
/// providing methods to extract geometric shapes from the graph after applying boolean operations.
/// [More information](https://ishape-rust.github.io/iShape-js/overlay/overlay_graph/overlay_graph.html) about Overlay Graph.
pub struct FloatOverlayGraph<'a, P: FloatPointCompatible<T>, T: FloatNumber> {
pub struct FloatOverlayGraph<'a, P: FloatPointCompatible> {
pub graph: OverlayGraph<'a>,
pub adapter: FloatPointAdapter<P, T>,
pub adapter: FloatPointAdapter<P>,
clean_result: bool,
}

impl<'a, P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlayGraph<'a, P, T> {
impl<'a, P: FloatPointCompatible> FloatOverlayGraph<'a, P> {
#[inline]
pub(crate) fn new(graph: OverlayGraph<'a>, adapter: FloatPointAdapter<P, T>, clean_result: bool) -> Self {
pub(crate) fn new(graph: OverlayGraph<'a>, adapter: FloatPointAdapter<P>, clean_result: bool) -> Self {
Self {
graph,
adapter,
Expand Down
58 changes: 23 additions & 35 deletions iOverlay/src/float/overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ pub struct OverlayOptions<T: FloatNumber> {
}

/// This struct is essential for describing and uploading the geometry or shapes required to construct an `FloatOverlay`. It prepares the necessary data for boolean operations.
pub struct FloatOverlay<P: FloatPointCompatible<T>, T: FloatNumber> {
pub struct FloatOverlay<P: FloatPointCompatible> {
pub(super) overlay: Overlay,
pub(super) clean_result: bool,
pub(super) adapter: FloatPointAdapter<P, T>,
pub(super) adapter: FloatPointAdapter<P>,
}

impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
impl<P: FloatPointCompatible> FloatOverlay<P> {
/// Constructs a new `FloatOverlay`, a builder for overlaying geometric shapes
/// by converting float-based geometry to integer space, using a pre-configured adapter.
///
Expand All @@ -57,7 +57,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `capacity`: Initial capacity for storing segments, ideally matching the total number of
/// segments for efficient memory allocation.
#[inline]
pub fn with_adapter(adapter: FloatPointAdapter<P, T>, capacity: usize) -> Self {
pub fn with_adapter(adapter: FloatPointAdapter<P>, capacity: usize) -> Self {
Self::new_custom(adapter, Default::default(), Default::default(), capacity)
}

Expand All @@ -72,8 +72,8 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// segments for efficient memory allocation.
#[inline]
pub fn new_custom(
adapter: FloatPointAdapter<P, T>,
options: OverlayOptions<T>,
adapter: FloatPointAdapter<P>,
options: OverlayOptions<P::Scalar>,
solver: Solver,
capacity: usize,
) -> Self {
Expand All @@ -93,7 +93,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `capacity`: Initial capacity for storing segments, ideally matching the total number of
/// segments for efficient memory allocation.
#[inline]
pub fn new_empty(options: OverlayOptions<T>, solver: Solver, capacity: usize) -> Self {
pub fn new_empty(options: OverlayOptions<P::Scalar>, solver: Solver, capacity: usize) -> Self {
let clean_result = options.clean_result;
let adapter = FloatPointAdapter::new(FloatRect::zero());
let overlay = Overlay::new_custom(capacity, options.int_default(), solver);
Expand All @@ -113,10 +113,8 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours.
pub fn with_subj_and_clip<R0, R1>(subj: &R0, clip: &R1) -> Self
where
R0: ShapeResource<P, T> + ?Sized,
R1: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let adapter = FloatPointAdapter::with_iter(iter);
Expand All @@ -140,14 +138,12 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
pub fn with_subj_and_clip_custom<R0, R1>(
subj: &R0,
clip: &R1,
options: OverlayOptions<T>,
options: OverlayOptions<P::Scalar>,
solver: Solver,
) -> Self
where
R0: ShapeResource<P, T> + ?Sized,
R1: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let adapter = FloatPointAdapter::with_iter(iter);
Expand All @@ -167,9 +163,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours.
pub fn with_subj<R>(subj: &R) -> Self
where
R: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().flatten();
let adapter = FloatPointAdapter::with_iter(iter);
Expand All @@ -186,11 +180,9 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours.
/// - `options`: Adjust custom behavior.
/// - `solver`: Type of solver to use.
pub fn with_subj_custom<R>(subj: &R, options: OverlayOptions<T>, solver: Solver) -> Self
pub fn with_subj_custom<R>(subj: &R, options: OverlayOptions<P::Scalar>, solver: Solver) -> Self
where
R: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().flatten();
let adapter = FloatPointAdapter::with_iter(iter);
Expand All @@ -207,7 +199,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours.
/// - `shape_type`: Specifies the role of the added paths in the overlay operation, either as `Subject` or `Clip`.
#[inline]
pub fn unsafe_add_source<R: ShapeResource<P, T> + ?Sized>(
pub fn unsafe_add_source<R: ShapeResource<P> + ?Sized>(
mut self,
resource: &R,
shape_type: ShapeType,
Expand All @@ -233,7 +225,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
}

#[inline]
fn add_source<R: ShapeResource<P, T> + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) {
fn add_source<R: ShapeResource<P> + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) {
for contour in resource.iter_paths() {
self.overlay
.add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type);
Expand All @@ -249,10 +241,8 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours.
pub fn reinit_with_subj_and_clip<R0, R1>(&mut self, subj: &R0, clip: &R1)
where
R0: ShapeResource<P, T> + ?Sized,
R1: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
self.clear();

Expand All @@ -270,9 +260,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours.
pub fn reinit_with_subj<R>(&mut self, subj: &R)
where
R: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R: ShapeResource<P> + ?Sized,
{
self.clear();

Expand All @@ -284,7 +272,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatOverlay<P, T> {
/// Convert into `FloatOverlayGraph` from the added paths or shapes using the specified build rule. This graph is the foundation for executing boolean operations, allowing for the analysis and manipulation of the geometric data. The `OverlayGraph` created by this method represents a preprocessed state of the input shapes, optimized for the application of boolean operations based on the provided build rule.
/// - `fill_rule`: Specifies the rule for determining filled areas within the shapes, influencing how the resulting graph represents intersections and unions.
#[inline]
pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option<FloatOverlayGraph<'_, P, T>> {
pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option<FloatOverlayGraph<'_, P>> {
let graph = self.overlay.build_graph_view(fill_rule)?;
Some(FloatOverlayGraph::new(
graph,
Expand Down Expand Up @@ -396,9 +384,9 @@ impl<T: FloatNumber> Default for OverlayOptions<T> {
}

impl<T: FloatNumber> OverlayOptions<T> {
pub(crate) fn int_with_adapter<P: FloatPointCompatible<T>>(
pub(crate) fn int_with_adapter<P: FloatPointCompatible<Scalar = T>>(
&self,
adapter: &FloatPointAdapter<P, T>,
adapter: &FloatPointAdapter<P>,
) -> IntOverlayOptions {
IntOverlayOptions {
preserve_input_collinear: self.preserve_input_collinear,
Expand Down
37 changes: 17 additions & 20 deletions iOverlay/src/float/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::core::relate::PredicateOverlay;
use crate::core::solver::Solver;
use i_float::adapter::FloatPointAdapter;
use i_float::float::compatible::FloatPointCompatible;
use i_float::float::number::FloatNumber;
use i_shape::source::resource::ShapeResource;

/// Float-coordinate wrapper for spatial predicate evaluation.
Expand All @@ -27,12 +26,12 @@ use i_shape::source::resource::ShapeResource;
///
/// For a more ergonomic API, see the [`FloatRelate`] trait which provides
/// methods directly on shape types.
pub struct FloatPredicateOverlay<P: FloatPointCompatible<T>, T: FloatNumber> {
pub struct FloatPredicateOverlay<P: FloatPointCompatible> {
pub(crate) overlay: PredicateOverlay,
pub(crate) adapter: FloatPointAdapter<P, T>,
pub(crate) adapter: FloatPointAdapter<P>,
}

impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
impl<P: FloatPointCompatible> FloatPredicateOverlay<P> {
/// Creates a new predicate overlay with a pre-configured adapter.
///
/// Use this when you need fixed-scale precision via `FloatPointAdapter::with_scale()`.
Expand All @@ -41,7 +40,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
/// * `adapter` - A `FloatPointAdapter` instance for coordinate conversion.
/// * `capacity` - Initial capacity for storing segments.
#[inline]
pub fn with_adapter(adapter: FloatPointAdapter<P, T>, capacity: usize) -> Self {
pub fn with_adapter(adapter: FloatPointAdapter<P>, capacity: usize) -> Self {
Self {
overlay: PredicateOverlay::new(capacity),
adapter,
Expand All @@ -59,7 +58,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
/// * `capacity` - Initial capacity for storing segments.
#[inline]
pub fn with_adapter_custom(
adapter: FloatPointAdapter<P, T>,
adapter: FloatPointAdapter<P>,
fill_rule: FillRule,
solver: Solver,
capacity: usize,
Expand All @@ -73,8 +72,8 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
/// Creates a new predicate overlay from subject and clip shapes.
pub fn with_subj_and_clip<R0, R1>(subj: &R0, clip: &R1) -> Self
where
R0: ShapeResource<P, T> + ?Sized,
R1: ShapeResource<P, T> + ?Sized,
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let adapter = FloatPointAdapter::with_iter(iter);
Expand All @@ -98,8 +97,8 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
solver: Solver,
) -> Self
where
R0: ShapeResource<P, T> + ?Sized,
R1: ShapeResource<P, T> + ?Sized,
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
{
let iter = subj.iter_paths().chain(clip.iter_paths()).flatten();
let adapter = FloatPointAdapter::with_iter(iter);
Expand All @@ -121,7 +120,7 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
/// # Arguments
/// * `resource` - A `ShapeResource` specifying the geometry to add.
/// * `shape_type` - Whether to add as `Subject` or `Clip`.
pub fn add_source<R: ShapeResource<P, T> + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) {
pub fn add_source<R: ShapeResource<P> + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) {
for contour in resource.iter_paths() {
self.overlay
.add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type);
Expand Down Expand Up @@ -200,11 +199,10 @@ impl<P: FloatPointCompatible<T>, T: FloatNumber> FloatPredicateOverlay<P, T> {
/// - `Vec<[f64; 2]>` - single contour
/// - `Vec<Vec<[f64; 2]>>` - multiple contours (shape with holes)
/// - `Vec<Vec<Vec<[f64; 2]>>>` - multiple shapes
pub trait FloatRelate<R1, P, T>
pub trait FloatRelate<R1, P>
where
R1: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R1: ShapeResource<P> + ?Sized,
P: FloatPointCompatible,
{
/// Returns `true` if this shape intersects with another (shares any point).
///
Expand Down Expand Up @@ -247,12 +245,11 @@ where
fn covers(&self, other: &R1) -> bool;
}

impl<R0, R1, P, T> FloatRelate<R1, P, T> for R0
impl<R0, R1, P> FloatRelate<R1, P> for R0
where
R0: ShapeResource<P, T> + ?Sized,
R1: ShapeResource<P, T> + ?Sized,
P: FloatPointCompatible<T>,
T: FloatNumber,
R0: ShapeResource<P> + ?Sized,
R1: ShapeResource<P> + ?Sized,
P: FloatPointCompatible,
{
#[inline]
fn intersects(&self, other: &R1) -> bool {
Expand Down
Loading
Loading