From e4c9171b21d5546e80fb4b18f2929319289a6194 Mon Sep 17 00:00:00 2001 From: Nail Sharipov Date: Sun, 1 Feb 2026 15:43:46 +0300 Subject: [PATCH 1/2] auto fmt --- iOverlay/rustfmt.toml | 2 + iOverlay/src/bind/mod.rs | 2 +- iOverlay/src/bind/segment.rs | 4 +- iOverlay/src/bind/solver.rs | 45 +--- iOverlay/src/build/boolean.rs | 109 +++++---- iOverlay/src/build/builder.rs | 19 +- iOverlay/src/build/graph.rs | 5 +- iOverlay/src/build/mod.rs | 6 +- iOverlay/src/build/offset.rs | 16 +- iOverlay/src/build/string.rs | 55 +++-- iOverlay/src/core/divide.rs | 19 +- iOverlay/src/core/extract.rs | 40 ++-- iOverlay/src/core/extract_ogc.rs | 13 +- iOverlay/src/core/fill_rule.rs | 4 +- iOverlay/src/core/graph.rs | 5 +- iOverlay/src/core/link.rs | 4 +- iOverlay/src/core/mod.rs | 2 +- iOverlay/src/core/nearest_vector.rs | 23 +- iOverlay/src/core/overlay.rs | 76 +++---- iOverlay/src/core/overlay_rule.rs | 4 +- iOverlay/src/core/simplify.rs | 62 ++--- iOverlay/src/core/solver.rs | 1 - iOverlay/src/float/clip.rs | 8 +- iOverlay/src/float/graph.rs | 20 +- iOverlay/src/float/overlay.rs | 262 ++++++++++++---------- iOverlay/src/float/scale.rs | 10 +- iOverlay/src/float/simplify.rs | 29 ++- iOverlay/src/float/single.rs | 43 ++-- iOverlay/src/float/string_graph.rs | 16 +- iOverlay/src/float/string_overlay.rs | 28 +-- iOverlay/src/geom/id_point.rs | 2 +- iOverlay/src/geom/line_range.rs | 2 +- iOverlay/src/geom/mod.rs | 6 +- iOverlay/src/geom/v_segment.rs | 25 +-- iOverlay/src/geom/x_segment.rs | 15 +- iOverlay/src/lib.rs | 10 +- iOverlay/src/mesh/extract.rs | 20 +- iOverlay/src/mesh/graph.rs | 2 +- iOverlay/src/mesh/math.rs | 2 +- iOverlay/src/mesh/mod.rs | 14 +- iOverlay/src/mesh/outline/builder.rs | 31 +-- iOverlay/src/mesh/outline/builder_join.rs | 23 +- iOverlay/src/mesh/outline/mod.rs | 2 +- iOverlay/src/mesh/outline/offset.rs | 22 +- iOverlay/src/mesh/outline/section.rs | 8 +- iOverlay/src/mesh/overlay.rs | 15 +- iOverlay/src/mesh/rotator.rs | 13 +- iOverlay/src/mesh/stroke/builder.rs | 47 ++-- iOverlay/src/mesh/stroke/builder_cap.rs | 34 ++- iOverlay/src/mesh/stroke/builder_join.rs | 17 +- iOverlay/src/mesh/stroke/mod.rs | 6 +- iOverlay/src/mesh/stroke/offset.rs | 8 +- iOverlay/src/mesh/stroke/section.rs | 8 +- iOverlay/src/mesh/style.rs | 22 +- iOverlay/src/mesh/subject.rs | 10 +- iOverlay/src/segm/boolean.rs | 17 +- iOverlay/src/segm/build.rs | 30 ++- iOverlay/src/segm/merge.rs | 53 +++-- iOverlay/src/segm/mod.rs | 10 +- iOverlay/src/segm/offset.rs | 19 +- iOverlay/src/segm/sort.rs | 6 +- iOverlay/src/segm/string.rs | 24 +- iOverlay/src/segm/winding.rs | 2 +- iOverlay/src/split/cross_solver.rs | 14 +- iOverlay/src/split/fragment.rs | 5 +- iOverlay/src/split/grid_layout.rs | 27 +-- iOverlay/src/split/line_mark.rs | 12 +- iOverlay/src/split/mod.rs | 8 +- iOverlay/src/split/snap_radius.rs | 2 +- iOverlay/src/split/solver.rs | 6 +- iOverlay/src/split/solver_fragment.rs | 26 +-- iOverlay/src/split/solver_list.rs | 4 +- iOverlay/src/split/solver_tree.rs | 18 +- iOverlay/src/string/clip.rs | 126 ++++++++--- iOverlay/src/string/extract.rs | 30 ++- iOverlay/src/string/filter.rs | 7 +- iOverlay/src/string/graph.rs | 4 +- iOverlay/src/string/mod.rs | 12 +- iOverlay/src/string/overlay.rs | 75 +++++-- iOverlay/src/string/rule.rs | 4 +- iOverlay/src/string/slice.rs | 29 +-- iOverlay/src/string/split.rs | 47 +--- iOverlay/src/util/log.rs | 16 +- iOverlay/src/util/mod.rs | 2 +- iOverlay/src/vector/edge.rs | 8 +- iOverlay/src/vector/extract.rs | 41 +--- iOverlay/src/vector/simplify.rs | 20 +- iOverlay/tests/data.rs | 12 +- iOverlay/tests/direction_tests.rs | 4 +- iOverlay/tests/doc_tests.rs | 35 +-- iOverlay/tests/dynamic_tests.rs | 65 ++---- iOverlay/tests/empty_tests.rs | 2 +- iOverlay/tests/fill_rule_tests.rs | 92 ++++++-- iOverlay/tests/float_overlay_tests.rs | 104 +++++---- iOverlay/tests/float_point_adapter.rs | 4 +- iOverlay/tests/fragment_tests.rs | 81 ++++--- iOverlay/tests/ocg_tests.rs | 16 +- iOverlay/tests/overlay_tests.rs | 83 ++----- iOverlay/tests/simplify_tests.rs | 102 ++++----- iOverlay/tests/slice_tests.rs | 41 +--- iOverlay/tests/string_tests.rs | 35 ++- iOverlay/tests/util.rs | 1 - iOverlay/tests/vector_tests.rs | 80 +++---- 103 files changed, 1363 insertions(+), 1394 deletions(-) create mode 100644 iOverlay/rustfmt.toml diff --git a/iOverlay/rustfmt.toml b/iOverlay/rustfmt.toml new file mode 100644 index 00000000..eec9c77f --- /dev/null +++ b/iOverlay/rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2024" +max_width = 110 \ No newline at end of file diff --git a/iOverlay/src/bind/mod.rs b/iOverlay/src/bind/mod.rs index b66bfd37..8622f972 100644 --- a/iOverlay/src/bind/mod.rs +++ b/iOverlay/src/bind/mod.rs @@ -1,2 +1,2 @@ +pub(crate) mod segment; pub(crate) mod solver; -pub(crate) mod segment; \ No newline at end of file diff --git a/iOverlay/src/bind/segment.rs b/iOverlay/src/bind/segment.rs index 36ae8cbe..b1a95de7 100644 --- a/iOverlay/src/bind/segment.rs +++ b/iOverlay/src/bind/segment.rs @@ -1,6 +1,6 @@ -use alloc::vec::Vec; use crate::geom::v_segment::VSegment; use crate::vector::edge::{VectorEdge, VectorPath}; +use alloc::vec::Vec; use i_float::int::point::IntPoint; use i_shape::int::path::IntPath; @@ -139,4 +139,4 @@ impl IdSegments for VectorPath { inner(self.iter().rev().copied(), buffer, id_data, x_min, x_max); } } -} \ No newline at end of file +} diff --git a/iOverlay/src/bind/solver.rs b/iOverlay/src/bind/solver.rs index 20883697..c10fbdf5 100644 --- a/iOverlay/src/bind/solver.rs +++ b/iOverlay/src/bind/solver.rs @@ -83,8 +83,7 @@ impl ShapeBinder { j += 1 } - let target_id = - scan_list.first_less(anchor.v_segment.a.x, ContourIndex::EMPTY, anchor.v_segment); + let target_id = scan_list.first_less(anchor.v_segment.a.x, ContourIndex::EMPTY, anchor.v_segment); let parent_index = if target_id.is_hole() { // index is a hole index // at this moment this hole parent is known @@ -108,12 +107,7 @@ impl ShapeBinder { pub(crate) trait JoinHoles { fn join_unsorted_holes(&mut self, holes: Vec, clockwise: bool); - fn join_sorted_holes( - &mut self, - holes: Vec, - anchors: Vec, - clockwise: bool, - ); + fn join_sorted_holes(&mut self, holes: Vec, anchors: Vec, clockwise: bool); fn scan_join(&mut self, holes: Vec, hole_segments: Vec, clockwise: bool); } @@ -146,12 +140,7 @@ impl JoinHoles for Vec { } #[inline] - fn join_sorted_holes( - &mut self, - holes: Vec, - anchors: Vec, - clockwise: bool, - ) { + fn join_sorted_holes(&mut self, holes: Vec, anchors: Vec, clockwise: bool) { if self.is_empty() || holes.is_empty() { return; } @@ -175,23 +164,11 @@ impl JoinHoles for Vec { let capacity = self.iter().fold(0, |s, it| s + it[0].len()) / 2; let mut segments = Vec::with_capacity(capacity); for (i, shape) in self.iter().enumerate() { - shape[0].append_id_segments( - &mut segments, - ContourIndex::new_shape(i), - x_min, - x_max, - clockwise, - ); + shape[0].append_id_segments(&mut segments, ContourIndex::new_shape(i), x_min, x_max, clockwise); } for (i, hole) in holes.iter().enumerate() { - hole.append_id_segments( - &mut segments, - ContourIndex::new_hole(i), - x_min, - x_max, - clockwise, - ); + hole.append_id_segments(&mut segments, ContourIndex::new_hole(i), x_min, x_max, clockwise); } segments.sort_by_a_then_by_angle(); @@ -322,16 +299,8 @@ mod tests { ]; let holes = vec![ - vec![ - IntPoint::new(2, 3), - IntPoint::new(4, 4), - IntPoint::new(4, 3), - ], - vec![ - IntPoint::new(2, 3), - IntPoint::new(4, 2), - IntPoint::new(3, 1), - ], + vec![IntPoint::new(2, 3), IntPoint::new(4, 4), IntPoint::new(4, 3)], + vec![IntPoint::new(2, 3), IntPoint::new(4, 2), IntPoint::new(3, 1)], ]; shapes.join_unsorted_holes(holes, false); diff --git a/iOverlay/src/build/boolean.rs b/iOverlay/src/build/boolean.rs index 934b7d6a..2b8cb054 100644 --- a/iOverlay/src/build/boolean.rs +++ b/iOverlay/src/build/boolean.rs @@ -1,26 +1,30 @@ -use alloc::vec::Vec; -use i_shape::util::reserve::Reserve; -use crate::segm::boolean::ShapeCountBoolean; -use crate::core::link::OverlayLinkFilter; -use crate::core::graph::OverlayNode; -use crate::core::fill_rule::FillRule; -use crate::core::solver::Solver; use crate::build::builder::{FillStrategy, GraphBuilder, InclusionFilterStrategy}; use crate::core::extract::VisitState; +use crate::core::fill_rule::FillRule; use crate::core::graph::OverlayGraph; +use crate::core::graph::OverlayNode; use crate::core::link::OverlayLink; +use crate::core::link::OverlayLinkFilter; use crate::core::overlay::IntOverlayOptions; use crate::core::overlay_rule::OverlayRule; -use crate::segm::segment::{Segment, SegmentFill, ALL, BOTH_BOTTOM, BOTH_TOP, CLIP_BOTH, CLIP_BOTTOM, CLIP_TOP, SUBJ_BOTH, SUBJ_BOTTOM, SUBJ_TOP}; +use crate::core::solver::Solver; +use crate::segm::boolean::ShapeCountBoolean; +use crate::segm::segment::{ + ALL, BOTH_BOTTOM, BOTH_TOP, CLIP_BOTH, CLIP_BOTTOM, CLIP_TOP, SUBJ_BOTH, SUBJ_BOTTOM, SUBJ_TOP, Segment, + SegmentFill, +}; use crate::segm::winding::WindingCount; +use alloc::vec::Vec; +use i_shape::util::reserve::Reserve; impl GraphBuilder { #[inline] - pub(crate) fn build_boolean_all(&mut self, - fill_rule: FillRule, - options: IntOverlayOptions, - solver: &Solver, - segments: &[Segment], + pub(crate) fn build_boolean_all( + &mut self, + fill_rule: FillRule, + options: IntOverlayOptions, + solver: &Solver, + segments: &[Segment], ) -> OverlayGraph<'_> { self.build_boolean_fills(fill_rule, solver, segments); self.build_links_all(segments); @@ -28,12 +32,13 @@ impl GraphBuilder { } #[inline] - pub(crate) fn build_boolean_overlay(&mut self, - fill_rule: FillRule, - overlay_rule: OverlayRule, - options: IntOverlayOptions, - solver: &Solver, - segments: &[Segment], + pub(crate) fn build_boolean_overlay( + &mut self, + fill_rule: FillRule, + overlay_rule: OverlayRule, + options: IntOverlayOptions, + solver: &Solver, + segments: &[Segment], ) -> OverlayGraph<'_> { self.build_boolean_fills(fill_rule, solver, segments); match overlay_rule { @@ -49,7 +54,12 @@ impl GraphBuilder { } #[inline] - fn build_boolean_fills(&mut self, fill_rule: FillRule, solver: &Solver, segments: &[Segment]) { + fn build_boolean_fills( + &mut self, + fill_rule: FillRule, + solver: &Solver, + segments: &[Segment], + ) { match fill_rule { FillRule::EvenOdd => self.build_fills_with_strategy::(solver, segments), FillRule::NonZero => self.build_fills_with_strategy::(solver, segments), @@ -64,7 +74,7 @@ impl GraphBuilder { OverlayGraph { nodes: &self.nodes, links: &self.links, - options + options, } } } @@ -76,10 +86,7 @@ struct NegativeStrategy; impl FillStrategy for EvenOddStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountBoolean, - bot: ShapeCountBoolean, - ) -> (ShapeCountBoolean, SegmentFill) { + fn add_and_fill(this: ShapeCountBoolean, bot: ShapeCountBoolean) -> (ShapeCountBoolean, SegmentFill) { let top = bot.add(this); let subj_top = 1 & top.subj as SegmentFill; let subj_bot = 1 & bot.subj as SegmentFill; @@ -94,10 +101,7 @@ impl FillStrategy for EvenOddStrategy { impl FillStrategy for NonZeroStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountBoolean, - bot: ShapeCountBoolean, - ) -> (ShapeCountBoolean, SegmentFill) { + fn add_and_fill(this: ShapeCountBoolean, bot: ShapeCountBoolean) -> (ShapeCountBoolean, SegmentFill) { let top = bot.add(this); let subj_top = (top.subj != 0) as SegmentFill; let subj_bot = (bot.subj != 0) as SegmentFill; @@ -112,10 +116,7 @@ impl FillStrategy for NonZeroStrategy { impl FillStrategy for PositiveStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountBoolean, - bot: ShapeCountBoolean, - ) -> (ShapeCountBoolean, SegmentFill) { + fn add_and_fill(this: ShapeCountBoolean, bot: ShapeCountBoolean) -> (ShapeCountBoolean, SegmentFill) { let top = bot.add(this); let subj_top = (top.subj > 0) as SegmentFill; let subj_bot = (bot.subj > 0) as SegmentFill; @@ -130,10 +131,7 @@ impl FillStrategy for PositiveStrategy { impl FillStrategy for NegativeStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountBoolean, - bot: ShapeCountBoolean, - ) -> (ShapeCountBoolean, SegmentFill) { + fn add_and_fill(this: ShapeCountBoolean, bot: ShapeCountBoolean) -> (ShapeCountBoolean, SegmentFill) { let top = bot.add(this); let subj_top = (top.subj < 0) as SegmentFill; let subj_bot = (bot.subj < 0) as SegmentFill; @@ -307,37 +305,58 @@ impl OverlayLinkFilter for [OverlayLink] { #[inline] fn filter_subject(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_subject())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_subject())) + .collect() } #[inline] fn filter_clip(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_clip())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_clip())) + .collect() } #[inline] fn filter_intersect(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_intersect())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_intersect())) + .collect() } #[inline] fn filter_union(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_union())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_union())) + .collect() } #[inline] fn filter_difference(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_difference())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_difference())) + .collect() } #[inline] fn filter_inverse_difference(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_inverse_difference())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_inverse_difference())) + .collect() } #[inline] fn filter_xor(links: &[OverlayLink]) -> Vec { - links.iter().map(|link| VisitState::new(!link.fill.is_xor())).collect() + links + .iter() + .map(|link| VisitState::new(!link.fill.is_xor())) + .collect() } #[inline] @@ -401,4 +420,4 @@ fn filter_xor_into(links: &[OverlayLink], buffer: &mut Vec) { for link in links.iter() { buffer.push(VisitState::new(!link.fill.is_xor())); } -} \ No newline at end of file +} diff --git a/iOverlay/src/build/builder.rs b/iOverlay/src/build/builder.rs index b28e2a4c..aecbd891 100644 --- a/iOverlay/src/build/builder.rs +++ b/iOverlay/src/build/builder.rs @@ -1,17 +1,17 @@ -use alloc::vec::Vec; +use crate::core::link::OverlayLink; use crate::core::solver::Solver; use crate::geom::end::End; +use crate::geom::id_point::IdPoint; use crate::geom::v_segment::VSegment; use crate::segm::segment::{NONE, Segment, SegmentFill}; use crate::segm::winding::WindingCount; use crate::util::log::Int; +use alloc::vec::Vec; use i_float::triangle::Triangle; use i_shape::util::reserve::Reserve; use i_tree::key::exp::KeyExpCollection; use i_tree::key::list::KeyExpList; use i_tree::key::tree::KeyExpTree; -use crate::core::link::OverlayLink; -use crate::geom::id_point::IdPoint; pub(super) trait FillStrategy { fn add_and_fill(this: C, bot: C) -> (C, SegmentFill); @@ -35,7 +35,6 @@ pub(crate) struct GraphBuilder { } impl GraphBuilder { - #[inline] pub(crate) fn new() -> Self { Self { @@ -49,7 +48,11 @@ impl GraphBuilder { } #[inline] - pub(super) fn build_fills_with_strategy>(&mut self, solver: &Solver, segments: &[Segment]) { + pub(super) fn build_fills_with_strategy>( + &mut self, + solver: &Solver, + segments: &[Segment], + ) { let count = segments.len(); if solver.is_list_fill(segments) { let capacity = count.log2_sqrt().max(4) * 2; @@ -65,7 +68,11 @@ impl GraphBuilder { } #[inline] - fn build_fills, S: KeyExpCollection>(&mut self, scan_list: &mut S, segments: &[Segment]) { + fn build_fills, S: KeyExpCollection>( + &mut self, + scan_list: &mut S, + segments: &[Segment], + ) { let mut node = Vec::with_capacity(4); let n = segments.len(); diff --git a/iOverlay/src/build/graph.rs b/iOverlay/src/build/graph.rs index cb63d8c3..0661b040 100644 --- a/iOverlay/src/build/graph.rs +++ b/iOverlay/src/build/graph.rs @@ -1,12 +1,11 @@ -use i_key_sort::sort::two_keys::TwoKeysSort; use crate::build::builder::{GraphBuilder, GraphNode}; use crate::core::solver::Solver; use crate::geom::end::End; use crate::segm::winding::WindingCount; use alloc::vec::Vec; +use i_key_sort::sort::two_keys::TwoKeysSort; impl GraphBuilder { - pub(super) fn build_nodes_and_connect_links(&mut self, solver: &Solver) { let n = self.links.len(); if n == 0 { @@ -96,4 +95,4 @@ impl GraphBuilder { self.ends .sort_by_two_keys(solver.is_parallel_sort_allowed(), |e| e.point.x, |e| e.point.y); } -} \ No newline at end of file +} diff --git a/iOverlay/src/build/mod.rs b/iOverlay/src/build/mod.rs index e2c78eef..ade59347 100644 --- a/iOverlay/src/build/mod.rs +++ b/iOverlay/src/build/mod.rs @@ -1,6 +1,6 @@ -pub(crate) mod builder; pub(crate) mod boolean; -pub(crate) mod string; +pub(crate) mod builder; mod graph; mod offset; -mod util; \ No newline at end of file +pub(crate) mod string; +mod util; diff --git a/iOverlay/src/build/offset.rs b/iOverlay/src/build/offset.rs index b6039d63..8d3d5356 100644 --- a/iOverlay/src/build/offset.rs +++ b/iOverlay/src/build/offset.rs @@ -8,9 +8,10 @@ use crate::segm::segment::{Segment, SegmentFill}; impl GraphBuilder { #[inline] - pub(crate) fn build_offset(&mut self, - solver: &Solver, - segments: &[Segment], + pub(crate) fn build_offset( + &mut self, + solver: &Solver, + segments: &[Segment], ) -> OffsetGraph<'_> { self.build_fills_with_strategy::(solver, segments); self.build_links_all(segments); @@ -31,7 +32,6 @@ struct SubjectOffsetStrategy; const BOLD_BIT: usize = 2; impl FillStrategy for SubjectOffsetStrategy { - #[inline(always)] fn add_and_fill(this: ShapeCountOffset, bot: ShapeCountOffset) -> (ShapeCountOffset, SegmentFill) { let top_subj = bot.subj + this.subj; @@ -43,16 +43,18 @@ impl FillStrategy for SubjectOffsetStrategy { let bold = this.bold as SegmentFill; let fill = subj_top | (subj_bot << 1) | (bold << BOLD_BIT); - let top = ShapeCountOffset { subj: top_subj, bold: false }; // bold not need + let top = ShapeCountOffset { + subj: top_subj, + bold: false, + }; // bold not need (top, fill) } } - impl OverlayLink { #[inline(always)] pub(crate) fn is_bold(&self) -> bool { self.fill & (1 << BOLD_BIT) != 0 } -} \ No newline at end of file +} diff --git a/iOverlay/src/build/string.rs b/iOverlay/src/build/string.rs index 57c21177..32586544 100644 --- a/iOverlay/src/build/string.rs +++ b/iOverlay/src/build/string.rs @@ -1,18 +1,19 @@ -use alloc::vec::Vec; -use crate::segm::string::ShapeCountString; use crate::build::builder::{FillStrategy, GraphBuilder, InclusionFilterStrategy}; use crate::core::fill_rule::FillRule; use crate::core::solver::Solver; -use crate::segm::segment::{Segment, SegmentFill, CLIP_BOTH, SUBJ_BOTH}; +use crate::segm::segment::{CLIP_BOTH, SUBJ_BOTH, Segment, SegmentFill}; +use crate::segm::string::ShapeCountString; use crate::string::clip::ClipRule; use crate::string::graph::StringGraph; +use alloc::vec::Vec; impl GraphBuilder> { #[inline] - pub(crate) fn build_string_all(&mut self, - fill_rule: FillRule, - solver: &Solver, - segments: &[Segment], + pub(crate) fn build_string_all( + &mut self, + fill_rule: FillRule, + solver: &Solver, + segments: &[Segment], ) -> StringGraph<'_> { self.build_string_fills(fill_rule, solver, segments); self.build_links_all(segments); @@ -20,11 +21,12 @@ impl GraphBuilder> { } #[inline] - pub(crate) fn build_string_clip(&mut self, - fill_rule: FillRule, - clip_rule: ClipRule, - solver: &Solver, - segments: &[Segment], + pub(crate) fn build_string_clip( + &mut self, + fill_rule: FillRule, + clip_rule: ClipRule, + solver: &Solver, + segments: &[Segment], ) -> StringGraph<'_> { self.build_string_fills(fill_rule, solver, segments); match clip_rule { @@ -49,7 +51,12 @@ impl GraphBuilder> { } #[inline] - fn build_string_fills(&mut self, fill_rule: FillRule, solver: &Solver, segments: &[Segment]) { + fn build_string_fills( + &mut self, + fill_rule: FillRule, + solver: &Solver, + segments: &[Segment], + ) { match fill_rule { FillRule::EvenOdd => self.build_fills_with_strategy::(solver, segments), FillRule::NonZero => self.build_fills_with_strategy::(solver, segments), @@ -75,10 +82,7 @@ struct NegativeStrategy; impl FillStrategy for EvenOddStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountString, - bot: ShapeCountString, - ) -> (ShapeCountString, SegmentFill) { + fn add_and_fill(this: ShapeCountString, bot: ShapeCountString) -> (ShapeCountString, SegmentFill) { let subj = bot.subj + this.subj; let top = ShapeCountString { subj, clip: 0 }; @@ -93,10 +97,7 @@ impl FillStrategy for EvenOddStrategy { impl FillStrategy for NonZeroStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountString, - bot: ShapeCountString, - ) -> (ShapeCountString, SegmentFill) { + fn add_and_fill(this: ShapeCountString, bot: ShapeCountString) -> (ShapeCountString, SegmentFill) { let subj = bot.subj + this.subj; let top = ShapeCountString { subj, clip: 0 }; // clip not need @@ -111,10 +112,7 @@ impl FillStrategy for NonZeroStrategy { impl FillStrategy for PositiveStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountString, - bot: ShapeCountString, - ) -> (ShapeCountString, SegmentFill) { + fn add_and_fill(this: ShapeCountString, bot: ShapeCountString) -> (ShapeCountString, SegmentFill) { let subj = bot.subj + this.subj; let top = ShapeCountString { subj, clip: 0 }; // clip not need @@ -129,10 +127,7 @@ impl FillStrategy for PositiveStrategy { impl FillStrategy for NegativeStrategy { #[inline(always)] - fn add_and_fill( - this: ShapeCountString, - bot: ShapeCountString, - ) -> (ShapeCountString, SegmentFill) { + fn add_and_fill(this: ShapeCountString, bot: ShapeCountString) -> (ShapeCountString, SegmentFill) { let subj = bot.subj + this.subj; let top = ShapeCountString { subj, clip: 0 }; // clip not need @@ -225,4 +220,4 @@ impl StringFillFilter for SegmentFill { false } } -} \ No newline at end of file +} diff --git a/iOverlay/src/core/divide.rs b/iOverlay/src/core/divide.rs index b6fc70fa..39bbec7c 100644 --- a/iOverlay/src/core/divide.rs +++ b/iOverlay/src/core/divide.rs @@ -1,9 +1,9 @@ +use crate::geom::id_point::IdPoint; use alloc::vec; use alloc::vec::Vec; use i_float::int::point::IntPoint; use i_shape::int::path::IntPath; use i_shape::int::shape::IntContour; -use crate::geom::id_point::IdPoint; struct SubPath { last: usize, @@ -39,7 +39,8 @@ impl ContourDecomposition for IntContour { if self.len() < 3 { return None; } - let mut id_points: Vec<_> = self.iter() + let mut id_points: Vec<_> = self + .iter() .enumerate() .map(|(i, &p)| IdPoint::new(i, p)) .collect(); @@ -69,7 +70,6 @@ impl ContourDecomposition for IntContour { anchors.sort_by(|p0, p1| p0.id.cmp(&p1.id)); - let mut contours = Vec::with_capacity((anchors.len() >> 1) + 1); let mut queue = vec![]; @@ -118,13 +118,12 @@ impl ContourDecomposition for IntContour { } } - #[cfg(test)] mod tests { + use crate::core::divide::ContourDecomposition; use alloc::vec; use i_float::int::point::IntPoint; use i_shape::int::shape::IntContour; - use crate::core::divide::ContourDecomposition; #[test] fn test_0() { @@ -278,6 +277,12 @@ mod tests { } fn rotate(contour: &IntContour, s: usize) -> IntContour { - contour.iter().cycle().skip(s).take(contour.len()).cloned().collect() + contour + .iter() + .cycle() + .skip(s) + .take(contour.len()) + .cloned() + .collect() } -} \ No newline at end of file +} diff --git a/iOverlay/src/core/extract.rs b/iOverlay/src/core/extract.rs index d6bf618d..afad0a75 100644 --- a/iOverlay/src/core/extract.rs +++ b/iOverlay/src/core/extract.rs @@ -51,7 +51,8 @@ impl OverlayGraph<'_> { overlay_rule: OverlayRule, buffer: &mut BooleanExtractionBuffer, ) -> IntShapes { - self.links.filter_by_overlay_into(overlay_rule, &mut buffer.visited); + self.links + .filter_by_overlay_into(overlay_rule, &mut buffer.visited); if self.options.ogc { self.extract_ogc(overlay_rule, buffer) } else { @@ -114,8 +115,7 @@ impl OverlayGraph<'_> { self.links.get_unchecked(left_top_link) }; let is_hole = overlay_rule.is_fill_top(link.fill); - let visited_state = - [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; + let visited_state = [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; let direction = is_hole == clockwise; let start_data = StartPathData::new(direction, link, left_top_link); @@ -237,8 +237,7 @@ impl OverlayGraph<'_> { self.links.get_unchecked(left_top_link) }; let is_hole = overlay_rule.is_fill_top(link.fill); - let visited_state = - [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; + let visited_state = [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; let direction = is_hole == clockwise; let start_data = StartPathData::new(direction, link, left_top_link); @@ -438,9 +437,7 @@ impl GraphUtil { // SAFETY: indices holds link ids emitted by GraphBuilder, so each i < links.len(). links.get_unchecked(i) }; - if !link.is_direct() - || Triangle::is_clockwise_point(top.a.point, top.b.point, link.b.point) - { + if !link.is_direct() || Triangle::is_clockwise_point(top.a.point, top.b.point, link.b.point) { continue; } @@ -459,12 +456,7 @@ impl GraphUtil { fn find_left_top_link_on_bridge(links: &[OverlayLink], bridge: &[usize; 2]) -> usize { // SAFETY: every bridge index comes straight from GraphBuilder::build_nodes_and_connect_links, // which only records values in 0..links.len(), so the unchecked lookups stay in-bounds. - let (l0, l1) = unsafe { - ( - links.get_unchecked(bridge[0]), - links.get_unchecked(bridge[1]), - ) - }; + let (l0, l1) = unsafe { (links.get_unchecked(bridge[0]), links.get_unchecked(bridge[1])) }; if Triangle::is_clockwise_point(l0.a.point, l0.b.point, l1.b.point) { bridge[0] } else { @@ -494,9 +486,9 @@ impl GraphUtil { bridge[0] } } - OverlayNode::Cross(indices) => GraphUtil::find_nearest_link_to( - links, link_id, node_id, clockwise, indices, visited, - ), + OverlayNode::Cross(indices) => { + GraphUtil::find_nearest_link_to(links, link_id, node_id, clockwise, indices, visited) + } } } @@ -548,8 +540,8 @@ impl GraphUtil { // SAFETY: first_index originates from indices, so it is within links. links.get_unchecked(first_index) } - .other(node_id) - .point; + .other(node_id) + .point; let mut vector_solver = NearestVector::new(c, a, b, first_index, clockwise); // add second vector @@ -558,8 +550,8 @@ impl GraphUtil { // SAFETY: second_index comes from indices just like first_index. links.get_unchecked(second_index) } - .other(node_id) - .point, + .other(node_id) + .point, second_index, ); @@ -570,8 +562,8 @@ impl GraphUtil { // SAFETY: every link_index here is sourced from indices, so it addresses links. links.get_unchecked(link_index) } - .other(node_id) - .point; + .other(node_id) + .point; vector_solver.add(p, link_index); } } @@ -613,4 +605,4 @@ mod tests { debug_assert!(shapes_1.len() == 1); } -} \ No newline at end of file +} diff --git a/iOverlay/src/core/extract_ogc.rs b/iOverlay/src/core/extract_ogc.rs index 3116fb89..3b3b26ff 100644 --- a/iOverlay/src/core/extract_ogc.rs +++ b/iOverlay/src/core/extract_ogc.rs @@ -43,8 +43,7 @@ impl OverlayGraph<'_> { self.links.get_unchecked(left_top_link) }; let is_hole = overlay_rule.is_fill_top(link.fill); - let visited_state = - [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; + let visited_state = [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; let direction = is_hole == is_main_dir_cw; let traversal_direction = !is_main_dir_cw; @@ -100,12 +99,7 @@ impl OverlayGraph<'_> { let left_top_link = unsafe { // Safety: `link_index` walks 0..buffer.visited.len(), and buffer.visited.len() <= self.links.len(). - GraphUtil::find_left_top_link( - self.links, - self.nodes, - link_index, - &buffer.visited, - ) + GraphUtil::find_left_top_link(self.links, self.nodes, link_index, &buffer.visited) }; let link = unsafe { @@ -181,8 +175,7 @@ impl OverlayGraph<'_> { // Find a closed tour while node_id != last_node_id { - link_id = - GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, visited); + link_id = GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, visited); let link = unsafe { // Safety: `link_id` is always derived from a previous in-bounds index or diff --git a/iOverlay/src/core/fill_rule.rs b/iOverlay/src/core/fill_rule.rs index 8e7c167d..235d47d0 100644 --- a/iOverlay/src/core/fill_rule.rs +++ b/iOverlay/src/core/fill_rule.rs @@ -11,7 +11,7 @@ pub enum FillRule { #[default] NonZero, Positive, - Negative + Negative, } impl fmt::Display for FillRule { @@ -25,4 +25,4 @@ impl fmt::Display for FillRule { write!(f, "{}", text) } -} \ No newline at end of file +} diff --git a/iOverlay/src/core/graph.rs b/iOverlay/src/core/graph.rs index 1d5d3ef3..9936bc4f 100644 --- a/iOverlay/src/core/graph.rs +++ b/iOverlay/src/core/graph.rs @@ -41,10 +41,7 @@ impl OverlayGraph<'_> { for node in self.nodes.iter() { if let OverlayNode::Cross(indices) = node { debug_assert!(indices.len() > 1, "indices: {}", indices.len()); - debug_assert!( - self.nodes.len() <= self.links.len(), - "nodes is more then links" - ); + debug_assert!(self.nodes.len() <= self.links.len(), "nodes is more then links"); } } } diff --git a/iOverlay/src/core/link.rs b/iOverlay/src/core/link.rs index 0030567c..ca11646a 100644 --- a/iOverlay/src/core/link.rs +++ b/iOverlay/src/core/link.rs @@ -1,8 +1,8 @@ -use alloc::vec::Vec; use crate::core::extract::VisitState; use crate::core::overlay_rule::OverlayRule; use crate::geom::id_point::IdPoint; use crate::segm::segment::SegmentFill; +use alloc::vec::Vec; #[derive(Debug, Clone, Copy)] pub(crate) struct OverlayLink { @@ -31,4 +31,4 @@ impl OverlayLink { pub(crate) trait OverlayLinkFilter { fn filter_by_overlay(&self, fill_rule: OverlayRule) -> Vec; fn filter_by_overlay_into(&self, overlay_rule: OverlayRule, buffer: &mut Vec); -} \ No newline at end of file +} diff --git a/iOverlay/src/core/mod.rs b/iOverlay/src/core/mod.rs index 13e14bc2..0877a7cf 100644 --- a/iOverlay/src/core/mod.rs +++ b/iOverlay/src/core/mod.rs @@ -1,6 +1,6 @@ pub mod divide; -mod extract_ogc; pub mod extract; +mod extract_ogc; pub mod fill_rule; pub mod graph; pub(crate) mod link; diff --git a/iOverlay/src/core/nearest_vector.rs b/iOverlay/src/core/nearest_vector.rs index 32b70638..1f7a1d4f 100644 --- a/iOverlay/src/core/nearest_vector.rs +++ b/iOverlay/src/core/nearest_vector.rs @@ -2,12 +2,12 @@ use i_float::fix_vec::FixVec; use i_float::int::point::IntPoint; pub(crate) struct NearestVector { - c: IntPoint, // center - va: FixVec, // our target vector - vb: FixVec, // nearest vector to Va by specified rotation - ab_more_180: bool, // is angle between Va and Vb more than 180 degrees + c: IntPoint, // center + va: FixVec, // our target vector + vb: FixVec, // nearest vector to Va by specified rotation + ab_more_180: bool, // is angle between Va and Vb more than 180 degrees pub(crate) best_id: usize, - rotation_factor: i64, // +1 for clockwise, -1 for counterclockwise + rotation_factor: i64, // +1 for clockwise, -1 for counterclockwise } impl NearestVector { @@ -20,7 +20,14 @@ impl NearestVector { } else { (va.cross_product(vb) <= 0, -1) }; - Self { c, va, vb, ab_more_180, best_id, rotation_factor } + Self { + c, + va, + vb, + ab_more_180, + best_id, + rotation_factor, + } } #[inline] @@ -43,9 +50,9 @@ impl NearestVector { #[cfg(test)] mod tests { + use crate::core::nearest_vector::NearestVector; use i_float::fix_vec::FixVec; use i_float::int::point::IntPoint; - use crate::core::nearest_vector::NearestVector; #[test] fn test_nearest_ccw_vector_creation() { @@ -104,7 +111,7 @@ mod tests { #[test] fn test_ccw_0() { let c = IntPoint::new(-1, -1); - let a = IntPoint::new( 0, -1); + let a = IntPoint::new(0, -1); let b = IntPoint::new(-2, -1); let mut nearest_ccw = NearestVector::new(c, a, b, 1, false); diff --git a/iOverlay/src/core/overlay.rs b/iOverlay/src/core/overlay.rs index 46791407..5a09bea0 100644 --- a/iOverlay/src/core/overlay.rs +++ b/iOverlay/src/core/overlay.rs @@ -149,8 +149,7 @@ impl Overlay { options: IntOverlayOptions, solver: Solver, ) -> Self { - let mut overlay = - Self::new_custom(subj.points_count() + clip.points_count(), options, solver); + let mut overlay = Self::new_custom(subj.points_count() + clip.points_count(), options, solver); overlay.add_contours(subj, ShapeType::Subject); overlay.add_contours(clip, ShapeType::Clip); overlay @@ -177,8 +176,7 @@ impl Overlay { options: IntOverlayOptions, solver: Solver, ) -> Self { - let mut overlay = - Self::new_custom(subj.points_count() + clip.points_count(), options, solver); + let mut overlay = Self::new_custom(subj.points_count() + clip.points_count(), options, solver); overlay.add_shapes(subj, ShapeType::Subject); overlay.add_shapes(clip, ShapeType::Clip); overlay @@ -259,15 +257,15 @@ impl Overlay { fill_rule: FillRule, overlay_rule: OverlayRule, ) -> Vec { - self.split_solver - .split_segments(&mut self.segments, &self.solver); + self.split_solver.split_segments(&mut self.segments, &self.solver); if self.segments.is_empty() { return Vec::new(); } let mut buffer = self.boolean_buffer.take().unwrap_or_default(); - let shapes = self.graph_builder + let shapes = self + .graph_builder .build_boolean_overlay( fill_rule, overlay_rule, @@ -285,8 +283,7 @@ impl Overlay { /// Convert into vectors from the added paths or shapes, applying the specified build rule. This method is particularly useful for development purposes and for creating visualizations in educational demos, where understanding the impact of different rules on the final geometry is crucial. /// - `fill_rule`: The build rule to use for the shapes. pub fn build_separate_vectors(&mut self, fill_rule: FillRule) -> Vec { - self.split_solver - .split_segments(&mut self.segments, &self.solver); + self.split_solver.split_segments(&mut self.segments, &self.solver); if self.segments.is_empty() { return Vec::new(); } @@ -299,17 +296,13 @@ impl Overlay { /// - `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> { - self.split_solver - .split_segments(&mut self.segments, &self.solver); + self.split_solver.split_segments(&mut self.segments, &self.solver); if self.segments.is_empty() { return None; } - let graph = self.graph_builder.build_boolean_all( - fill_rule, - self.options, - &self.solver, - &self.segments, - ); + let graph = + self.graph_builder + .build_boolean_all(fill_rule, self.options, &self.solver, &self.segments); Some(graph) } @@ -354,8 +347,7 @@ impl Overlay { /// particularly for complex or resource-intensive geometries. #[inline] pub fn overlay(&mut self, overlay_rule: OverlayRule, fill_rule: FillRule) -> IntShapes { - self.split_solver - .split_segments(&mut self.segments, &self.solver); + self.split_solver.split_segments(&mut self.segments, &self.solver); if self.segments.is_empty() { return Vec::new(); } @@ -419,24 +411,22 @@ impl IntOverlayOptions { #[cfg(test)] mod tests { + use crate::core::fill_rule::FillRule; + use crate::core::overlay::Overlay; + use crate::core::overlay_rule::OverlayRule; use alloc::vec; use i_float::int::point::IntPoint; use i_shape::int::area::Area; use i_shape::int::shape::IntContour; - use crate::core::fill_rule::FillRule; - use crate::core::overlay::Overlay; - use crate::core::overlay_rule::OverlayRule; #[test] fn test_0() { - let subj = [ - vec![ - IntPoint::new(0, 0), - IntPoint::new(10, 0), - IntPoint::new(10, 10), - IntPoint::new(0, 10), - ], - ]; + let subj = [vec![ + IntPoint::new(0, 0), + IntPoint::new(10, 0), + IntPoint::new(10, 10), + IntPoint::new(0, 10), + ]]; let mut overlay = Overlay::with_contours(&subj, &[]); let result = overlay.overlay(OverlayRule::Subject, FillRule::EvenOdd); @@ -807,26 +797,10 @@ mod tests { #[test] fn test_14() { let subj = [ - vec![ - IntPoint::new(0, 0), - IntPoint::new(0, 2), - IntPoint::new(2, 0), - ], - vec![ - IntPoint::new(0, 0), - IntPoint::new(2, 0), - IntPoint::new(0, -2), - ], - vec![ - IntPoint::new(0, 0), - IntPoint::new(0, -2), - IntPoint::new(-2, 0), - ], - vec![ - IntPoint::new(0, 0), - IntPoint::new(-2, 0), - IntPoint::new(0, 2), - ], + vec![IntPoint::new(0, 0), IntPoint::new(0, 2), IntPoint::new(2, 0)], + vec![IntPoint::new(0, 0), IntPoint::new(2, 0), IntPoint::new(0, -2)], + vec![IntPoint::new(0, 0), IntPoint::new(0, -2), IntPoint::new(-2, 0)], + vec![IntPoint::new(0, 0), IntPoint::new(-2, 0), IntPoint::new(0, 2)], ]; let mut overlay = Overlay::with_contours(&subj, &[]); @@ -845,5 +819,5 @@ mod tests { let result = overlay.overlay(OverlayRule::Subject, FillRule::NonZero); assert_eq!(result.len(), 0); - } + } } diff --git a/iOverlay/src/core/overlay_rule.rs b/iOverlay/src/core/overlay_rule.rs index b9095aa3..734addfa 100644 --- a/iOverlay/src/core/overlay_rule.rs +++ b/iOverlay/src/core/overlay_rule.rs @@ -1,5 +1,5 @@ +use crate::segm::segment::{BOTH_BOTTOM, BOTH_TOP, CLIP_TOP, NONE, SUBJ_TOP, SegmentFill}; use core::fmt; -use crate::segm::segment::{SegmentFill, BOTH_BOTTOM, BOTH_TOP, CLIP_TOP, NONE, SUBJ_TOP}; /// Defines the types of overlay/boolean operations that can be applied to shapes. For a visual description, see [Overlay Rules](https://ishape-rust.github.io/iShape-js/overlay/overlay_rules/overlay_rules.html). /// - `Subject`: Processes the subject shape, useful for resolving self-intersections and degenerate cases within the subject itself. @@ -53,4 +53,4 @@ impl fmt::Display for OverlayRule { write!(f, "{}", text) } -} \ No newline at end of file +} diff --git a/iOverlay/src/core/simplify.rs b/iOverlay/src/core/simplify.rs index f0d4040f..a4196bd1 100644 --- a/iOverlay/src/core/simplify.rs +++ b/iOverlay/src/core/simplify.rs @@ -1,18 +1,18 @@ //! This module provides methods to simplify paths and shapes by reducing complexity //! (e.g., removing small artifacts or shapes below a certain area threshold) based on a build rule. -use i_shape::flat::buffer::FlatContoursBuffer; -use crate::core::overlay::ContourDirection; -use alloc::vec; -use crate::i_float::int::point::IntPoint; use crate::core::fill_rule::FillRule; +use crate::core::overlay::ContourDirection; use crate::core::overlay::ContourDirection::Clockwise; use crate::core::overlay::{IntOverlayOptions, Overlay, ShapeType}; use crate::core::overlay_rule::OverlayRule; +use crate::i_float::int::point::IntPoint; +use alloc::vec; +use i_shape::flat::buffer::FlatContoursBuffer; use crate::segm::build::BuildSegments; -use i_shape::int::path::ContourExtension; use i_shape::int::count::PointsCount; +use i_shape::int::path::ContourExtension; use i_shape::int::shape::{IntContour, IntShape, IntShapes}; /// Trait `Simplify` provides a method to simplify geometric shapes by reducing the number of points in contours or shapes @@ -36,9 +36,7 @@ pub trait Simplify { impl Simplify for [IntPoint] { #[inline] fn simplify(&self, fill_rule: FillRule, options: IntOverlayOptions) -> IntShapes { - match Overlay::new_custom(self.len(), options, Default::default()) - .simplify_contour(self, fill_rule) - { + match Overlay::new_custom(self.len(), options, Default::default()).simplify_contour(self, fill_rule) { Some(shapes) => shapes, None => vec![vec![self.to_vec()]], } @@ -48,9 +46,7 @@ impl Simplify for [IntPoint] { impl Simplify for [IntContour] { #[inline] fn simplify(&self, fill_rule: FillRule, options: IntOverlayOptions) -> IntShapes { - match Overlay::new_custom(self.len(), options, Default::default()) - .simplify_shape(self, fill_rule) - { + match Overlay::new_custom(self.len(), options, Default::default()).simplify_shape(self, fill_rule) { Some(shapes) => shapes, None => vec![self.to_vec()], } @@ -60,19 +56,17 @@ impl Simplify for [IntContour] { impl Simplify for [IntShape] { #[inline] fn simplify(&self, fill_rule: FillRule, options: IntOverlayOptions) -> IntShapes { - Overlay::new_custom(self.points_count(), options, Default::default()) - .simplify_shapes(self, fill_rule) + Overlay::new_custom(self.points_count(), options, Default::default()).simplify_shapes(self, fill_rule) } } enum ContourFillDirection { Reverse, Correct, - Empty + Empty, } impl Overlay { - /// Fast-path simplification for a single contour. /// /// Skips full overlay if the contour is already simple (no splits, no loops, no collinear issues). @@ -80,11 +74,7 @@ impl Overlay { /// /// Returns `None` if the contour is valid and needs no changes, or `Some(IntShapes)` with the simplified result. #[inline] - pub fn simplify_contour( - &mut self, - contour: &[IntPoint], - fill_rule: FillRule, - ) -> Option { + pub fn simplify_contour(&mut self, contour: &[IntPoint], fill_rule: FillRule) -> Option { self.clear(); let is_perfect = self.find_intersections(contour); @@ -92,9 +82,7 @@ impl Overlay { if is_perfect { // the path is already perfect // need to check fill rule direction - let fill_direction = Self::contour_direction( - self.options.output_direction, fill_rule, contour - ); + let fill_direction = Self::contour_direction(self.options.output_direction, fill_rule, contour); return match fill_direction { ContourFillDirection::Reverse => { @@ -103,8 +91,8 @@ impl Overlay { Some(vec![vec![rev_contour]]) } ContourFillDirection::Correct => None, - ContourFillDirection::Empty => Some(vec![]) - } + ContourFillDirection::Empty => Some(vec![]), + }; } let mut boolean_buffer = self.boolean_buffer.take().unwrap_or_default(); @@ -187,19 +175,18 @@ impl Overlay { if is_perfect { // the path is already perfect // need to check fill rule direction - let fill_direction = Self::contour_direction( - self.options.output_direction, fill_rule, first_contour - ); + let fill_direction = + Self::contour_direction(self.options.output_direction, fill_rule, first_contour); match fill_direction { ContourFillDirection::Reverse => { flat_buffer.as_first_contour_mut().reverse(); } - ContourFillDirection::Correct => {}, - ContourFillDirection::Empty => flat_buffer.clear_and_reserve(0, 0) + ContourFillDirection::Correct => {} + ContourFillDirection::Empty => flat_buffer.clear_and_reserve(0, 0), } - return + return; } } else { self.add_flat_buffer(flat_buffer, ShapeType::Subject); @@ -212,8 +199,7 @@ impl Overlay { let mut boolean_buffer = self.boolean_buffer.take().unwrap_or_default(); - self - .graph_builder + self.graph_builder .build_boolean_overlay( fill_rule, OverlayRule::Subject, @@ -233,16 +219,16 @@ impl Overlay { self.options.preserve_input_collinear, ); - let split_modified = self - .split_solver - .split_segments(&mut self.segments, &self.solver); + let split_modified = self.split_solver.split_segments(&mut self.segments, &self.solver); if split_modified || append_modified || self.segments.is_empty() { return false; } let mut buffer = self.boolean_buffer.take().unwrap_or_default(); - let has_loops = self.graph_builder.test_contour_for_loops(contour, &mut buffer.points); + let has_loops = self + .graph_builder + .test_contour_for_loops(contour, &mut buffer.points); self.boolean_buffer = Some(buffer); !has_loops @@ -409,7 +395,7 @@ mod tests { #[test] fn test_near_collinear_paths() { let contour = vec![ - IntPoint::new(-100, -100), + IntPoint::new(-100, -100), IntPoint::new(0, 0), IntPoint::new(101, 100), ]; diff --git a/iOverlay/src/core/solver.rs b/iOverlay/src/core/solver.rs index 09bd6905..144011c6 100644 --- a/iOverlay/src/core/solver.rs +++ b/iOverlay/src/core/solver.rs @@ -185,5 +185,4 @@ impl Solver { pub(crate) fn is_parallel_sort_allowed(&self) -> bool { self.multithreading.is_some() } - } diff --git a/iOverlay/src/float/clip.rs b/iOverlay/src/float/clip.rs index 5817828d..e0c8ab0b 100644 --- a/iOverlay/src/float/clip.rs +++ b/iOverlay/src/float/clip.rs @@ -178,13 +178,7 @@ where clip_rule: ClipRule, scale: T, ) -> Result, FixedScaleOverlayError> { - self.clip_by_fixed_scale_with_solver( - resource, - fill_rule, - clip_rule, - Default::default(), - scale, - ) + self.clip_by_fixed_scale_with_solver(resource, fill_rule, clip_rule, Default::default(), scale) } #[inline] diff --git a/iOverlay/src/float/graph.rs b/iOverlay/src/float/graph.rs index 88bed582..85d79652 100644 --- a/iOverlay/src/float/graph.rs +++ b/iOverlay/src/float/graph.rs @@ -2,6 +2,7 @@ //! subject and clip polygons after boolean operations. The graph helps in extracting final shapes //! based on the overlay rule applied. +use crate::core::extract::BooleanExtractionBuffer; use crate::core::graph::OverlayGraph; use crate::core::overlay_rule::OverlayRule; use i_float::adapter::FloatPointAdapter; @@ -11,7 +12,6 @@ use i_shape::base::data::Shapes; use i_shape::float::adapter::ShapesToFloat; use i_shape::float::despike::DeSpikeContour; use i_shape::float::simple::SimplifyContour; -use crate::core::extract::BooleanExtractionBuffer; /// The `FloatOverlayGraph` struct represents an overlay graph with floating point precision, /// providing methods to extract geometric shapes from the graph after applying boolean operations. @@ -19,13 +19,17 @@ use crate::core::extract::BooleanExtractionBuffer; pub struct FloatOverlayGraph<'a, P: FloatPointCompatible, T: FloatNumber> { pub graph: OverlayGraph<'a>, pub adapter: FloatPointAdapter, - clean_result: bool + clean_result: bool, } impl<'a, P: FloatPointCompatible, T: FloatNumber> FloatOverlayGraph<'a, P, T> { #[inline] pub(crate) fn new(graph: OverlayGraph<'a>, adapter: FloatPointAdapter, clean_result: bool) -> Self { - Self { graph, adapter, clean_result } + Self { + graph, + adapter, + clean_result, + } } /// Extracts shapes from the overlay graph based on the specified overlay rule. @@ -46,10 +50,12 @@ impl<'a, P: FloatPointCompatible, T: FloatNumber> FloatOverlayGraph<'a, P, T> /// /// Note: Outer boundary paths have a counterclockwise order, and holes have a clockwise order. #[inline] - pub fn extract_shapes(&self, overlay_rule: OverlayRule, buffer: &mut BooleanExtractionBuffer) -> Shapes

{ - let shapes = self - .graph - .extract_shapes(overlay_rule, buffer); + pub fn extract_shapes( + &self, + overlay_rule: OverlayRule, + buffer: &mut BooleanExtractionBuffer, + ) -> Shapes

{ + let shapes = self.graph.extract_shapes(overlay_rule, buffer); let mut float = shapes.to_float(&self.adapter); if self.clean_result { diff --git a/iOverlay/src/float/overlay.rs b/iOverlay/src/float/overlay.rs index 7b1b7ebb..57d725ae 100644 --- a/iOverlay/src/float/overlay.rs +++ b/iOverlay/src/float/overlay.rs @@ -2,6 +2,11 @@ //! boolean operations (union, intersection, etc.) on polygons. It provides structures and methods to //! manage subject and clip polygons and convert them into graphs for further operations. +use crate::core::fill_rule::FillRule; +use crate::core::overlay::{ContourDirection, IntOverlayOptions, Overlay, ShapeType}; +use crate::core::overlay_rule::OverlayRule; +use crate::core::solver::Solver; +use crate::float::graph::FloatOverlayGraph; use crate::i_shape::source::resource::ShapeResource; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; @@ -11,11 +16,6 @@ use i_shape::base::data::Shapes; use i_shape::float::adapter::ShapesToFloat; use i_shape::float::despike::DeSpikeContour; use i_shape::float::simple::SimplifyContour; -use crate::core::fill_rule::FillRule; -use crate::core::overlay::{ContourDirection, IntOverlayOptions, Overlay, ShapeType}; -use crate::core::overlay_rule::OverlayRule; -use crate::core::solver::Solver; -use crate::float::graph::FloatOverlayGraph; #[derive(Debug, Clone, Copy)] pub struct OverlayOptions { @@ -69,10 +69,19 @@ impl, T: FloatNumber> FloatOverlay { /// - `capacity`: Initial capacity for storing segments, ideally matching the total number of /// segments for efficient memory allocation. #[inline] - pub fn new_custom(adapter: FloatPointAdapter, options: OverlayOptions, solver: Solver, capacity: usize) -> Self { + pub fn new_custom( + adapter: FloatPointAdapter, + options: OverlayOptions, + solver: Solver, + capacity: usize, + ) -> Self { let clean_result = options.clean_result; let overlay = Overlay::new_custom(capacity, options.int_with_adapter(&adapter), solver); - Self { overlay, clean_result, adapter } + Self { + overlay, + clean_result, + adapter, + } } /// Constructs a new `FloatOverlay`, a builder for overlaying geometric shapes @@ -86,7 +95,11 @@ impl, T: FloatNumber> FloatOverlay { let clean_result = options.clean_result; let adapter = FloatPointAdapter::new(FloatRect::zero()); let overlay = Overlay::new_custom(capacity, options.int_default(), solver); - Self { overlay, clean_result, adapter } + Self { + overlay, + clean_result, + adapter, + } } /// Creates a new `FloatOverlay` instance and initializes it with subject and clip shapes. @@ -98,8 +111,8 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn with_subj_and_clip(subj: &R0, clip: &R1) -> Self where - R0: ShapeResource +?Sized, - R1: ShapeResource +?Sized, + R0: ShapeResource + ?Sized, + R1: ShapeResource + ?Sized, P: FloatPointCompatible, T: FloatNumber, { @@ -122,10 +135,15 @@ impl, T: FloatNumber> FloatOverlay { /// - `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_and_clip_custom(subj: &R0, clip: &R1, options: OverlayOptions, solver: Solver) -> Self + pub fn with_subj_and_clip_custom( + subj: &R0, + clip: &R1, + options: OverlayOptions, + solver: Solver, + ) -> Self where - R0: ShapeResource +?Sized, - R1: ShapeResource +?Sized, + R0: ShapeResource + ?Sized, + R1: ShapeResource + ?Sized, P: FloatPointCompatible, T: FloatNumber, { @@ -147,7 +165,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn with_subj(subj: &R) -> Self where - R: ShapeResource +?Sized, + R: ShapeResource + ?Sized, P: FloatPointCompatible, T: FloatNumber, { @@ -155,8 +173,7 @@ impl, T: FloatNumber> FloatOverlay { let adapter = FloatPointAdapter::with_iter(iter); let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len()); - Self::with_adapter(adapter, subj_capacity) - .unsafe_add_source(subj, ShapeType::Subject) + Self::with_adapter(adapter, subj_capacity).unsafe_add_source(subj, ShapeType::Subject) } /// Creates a new `FloatOverlay` instance and initializes it with subject. @@ -169,7 +186,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `solver`: Type of solver to use. pub fn with_subj_custom(subj: &R, options: OverlayOptions, solver: Solver) -> Self where - R: ShapeResource +?Sized, + R: ShapeResource + ?Sized, P: FloatPointCompatible, T: FloatNumber, { @@ -177,8 +194,7 @@ impl, T: FloatNumber> FloatOverlay { let adapter = FloatPointAdapter::with_iter(iter); let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len()); - Self::new_custom(adapter, options, solver, subj_capacity) - .unsafe_add_source(subj, ShapeType::Subject) + Self::new_custom(adapter, options, solver, subj_capacity).unsafe_add_source(subj, ShapeType::Subject) } /// Adds a shapes to the overlay. @@ -189,7 +205,11 @@ impl, T: FloatNumber> FloatOverlay { /// - `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 +?Sized>(mut self, resource: &R, shape_type: ShapeType) -> Self { + pub fn unsafe_add_source + ?Sized>( + mut self, + resource: &R, + shape_type: ShapeType, + ) -> Self { self.add_source(resource, shape_type); self } @@ -200,7 +220,8 @@ impl, T: FloatNumber> FloatOverlay { /// - **Safety**: Marked `unsafe` because it assumes the path is fully contained within the bounding box. #[inline] pub fn unsafe_add_contour(mut self, contour: &[P], shape_type: ShapeType) -> Self { - self.overlay.add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type); + self.overlay + .add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type); self } @@ -210,9 +231,10 @@ impl, T: FloatNumber> FloatOverlay { } #[inline] - fn add_source +?Sized>(&mut self, resource: &R, shape_type: ShapeType) { + fn add_source + ?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); + self.overlay + .add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type); } } @@ -225,8 +247,8 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn reinit_with_subj_and_clip(&mut self, subj: &R0, clip: &R1) where - R0: ShapeResource +?Sized, - R1: ShapeResource +?Sized, + R0: ShapeResource + ?Sized, + R1: ShapeResource + ?Sized, P: FloatPointCompatible, T: FloatNumber, { @@ -246,7 +268,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn reinit_with_subj(&mut self, subj: &R) where - R: ShapeResource +?Sized, + R: ShapeResource + ?Sized, P: FloatPointCompatible, T: FloatNumber, { @@ -262,7 +284,11 @@ impl, T: FloatNumber> FloatOverlay { #[inline] pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option> { let graph = self.overlay.build_graph_view(fill_rule)?; - Some(FloatOverlayGraph::new(graph, self.adapter.clone(), self.clean_result)) + Some(FloatOverlayGraph::new( + graph, + self.adapter.clone(), + self.clean_result, + )) } /// Executes a single Boolean operation on the current geometry using the specified overlay and build rules. @@ -336,7 +362,10 @@ impl Default for OverlayOptions { } impl OverlayOptions { - pub(crate) fn int_with_adapter>(&self, adapter: &FloatPointAdapter) -> IntOverlayOptions { + pub(crate) fn int_with_adapter>( + &self, + adapter: &FloatPointAdapter, + ) -> IntOverlayOptions { IntOverlayOptions { preserve_input_collinear: self.preserve_input_collinear, output_direction: self.output_direction, @@ -372,10 +401,10 @@ impl OverlayOptions { #[cfg(test)] mod tests { - use alloc::vec; -use crate::core::fill_rule::FillRule; + use crate::core::fill_rule::FillRule; use crate::core::overlay_rule::OverlayRule; use crate::float::overlay::FloatOverlay; + use alloc::vec; #[test] fn test_contour_fixed() { @@ -383,10 +412,7 @@ use crate::core::fill_rule::FillRule; let right_rect = [[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; let shapes = FloatOverlay::with_subj_and_clip(&left_rect, &right_rect) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd, - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -398,12 +424,8 @@ use crate::core::fill_rule::FillRule; let left_rect = vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]]; let right_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; - let shapes = FloatOverlay::with_subj_and_clip(&left_rect, &right_rect) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -416,10 +438,7 @@ use crate::core::fill_rule::FillRule; let right_rect = [[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; let shapes = FloatOverlay::with_subj_and_clip(left_rect.as_slice(), right_rect.as_slice()) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -429,23 +448,14 @@ use crate::core::fill_rule::FillRule; #[test] fn test_contours_vec() { let rects = vec![ - vec![ - [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0] - ], - vec![ - [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0] - ], - vec![ - [1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0] - ] + vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]], + vec![[0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0]], + vec![[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0]], ]; let right_bottom_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; let shapes = FloatOverlay::with_subj_and_clip(&rects.as_slice(), &right_bottom_rect) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -455,23 +465,14 @@ use crate::core::fill_rule::FillRule; #[test] fn test_contours_slice() { let rects = vec![ - vec![ - [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0] - ], - vec![ - [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0] - ], - vec![ - [1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0] - ] + vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]], + vec![[0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0]], + vec![[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0]], ]; let right_bottom_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; let shapes = FloatOverlay::with_subj_and_clip(rects.as_slice(), right_bottom_rect.as_slice()) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -480,27 +481,15 @@ use crate::core::fill_rule::FillRule; #[test] fn test_shapes() { - let shapes = vec![ - vec![ - vec![ - [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0] - ], - vec![ - [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0] - ], - vec![ - [1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0] - ] - ] - ]; + let shapes = vec![vec![ + vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]], + vec![[0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0]], + vec![[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0]], + ]]; let right_bottom_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; - let shapes = FloatOverlay::with_subj_and_clip(&shapes, &right_bottom_rect) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -509,28 +498,16 @@ use crate::core::fill_rule::FillRule; #[test] fn test_different_resource() { - let res_0 = vec![ - vec![ - vec![ - [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0] - ], - vec![ - [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0] - ], - vec![ - [1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0] - ] - ] - ]; + let res_0 = vec![vec![ + vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]], + vec![[0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0]], + vec![[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0]], + ]]; let res_1 = [[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; - let shapes = FloatOverlay::with_subj_and_clip(&res_0, &res_1.as_slice()) - .overlay( - OverlayRule::Union, - FillRule::EvenOdd - ); + .overlay(OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -540,26 +517,77 @@ use crate::core::fill_rule::FillRule; #[test] fn test_grid() { let subj = vec![ - vec![vec![[175.0, 475.0], [175.0, 375.0], [275.0, 375.0], [275.0, 475.0]]], - vec![vec![[175.0, 325.0], [175.0, 225.0], [275.0, 225.0], [275.0, 325.0]]], + vec![vec![ + [175.0, 475.0], + [175.0, 375.0], + [275.0, 375.0], + [275.0, 475.0], + ]], + vec![vec![ + [175.0, 325.0], + [175.0, 225.0], + [275.0, 225.0], + [275.0, 325.0], + ]], vec![vec![[175.0, 175.0], [175.0, 75.0], [275.0, 75.0], [275.0, 175.0]]], - vec![vec![[325.0, 475.0], [325.0, 375.0], [425.0, 375.0], [425.0, 475.0]]], - vec![vec![[325.0, 325.0], [325.0, 225.0], [425.0, 225.0], [425.0, 325.0]]], + vec![vec![ + [325.0, 475.0], + [325.0, 375.0], + [425.0, 375.0], + [425.0, 475.0], + ]], + vec![vec![ + [325.0, 325.0], + [325.0, 225.0], + [425.0, 225.0], + [425.0, 325.0], + ]], vec![vec![[325.0, 175.0], [325.0, 75.0], [425.0, 75.0], [425.0, 175.0]]], - vec![vec![[475.0, 475.0], [475.0, 375.0], [575.0, 375.0], [575.0, 475.0]]], - vec![vec![[475.0, 325.0], [475.0, 225.0], [575.0, 225.0], [575.0, 325.0]]], - vec![vec![[475.0, 175.0], [475.0, 75.0], [575.0, 75.0], [575.0, 175.0]]]]; + vec![vec![ + [475.0, 475.0], + [475.0, 375.0], + [575.0, 375.0], + [575.0, 475.0], + ]], + vec![vec![ + [475.0, 325.0], + [475.0, 225.0], + [575.0, 225.0], + [575.0, 325.0], + ]], + vec![vec![[475.0, 175.0], [475.0, 75.0], [575.0, 75.0], [575.0, 175.0]]], + ]; let clip = vec![ - vec![vec![[250.0, 400.0], [250.0, 300.0], [350.0, 300.0], [350.0, 400.0]]], - vec![vec![[250.0, 250.0], [250.0, 150.0], [350.0, 150.0], [350.0, 250.0]]], - vec![vec![[400.0, 400.0], [400.0, 300.0], [500.0, 300.0], [500.0, 400.0]]], - vec![vec![[400.0, 250.0], [400.0, 150.0], [500.0, 150.0], [500.0, 250.0]]] + vec![vec![ + [250.0, 400.0], + [250.0, 300.0], + [350.0, 300.0], + [350.0, 400.0], + ]], + vec![vec![ + [250.0, 250.0], + [250.0, 150.0], + [350.0, 150.0], + [350.0, 250.0], + ]], + vec![vec![ + [400.0, 400.0], + [400.0, 300.0], + [500.0, 300.0], + [500.0, 400.0], + ]], + vec![vec![ + [400.0, 250.0], + [400.0, 150.0], + [500.0, 150.0], + [500.0, 250.0], + ]], ]; let mut overlay = FloatOverlay::with_subj_and_clip(&subj, &clip); - let result = overlay.overlay(OverlayRule::Intersect, FillRule::EvenOdd ); + let result = overlay.overlay(OverlayRule::Intersect, FillRule::EvenOdd); assert_eq!(result.len(), 16); } diff --git a/iOverlay/src/float/scale.rs b/iOverlay/src/float/scale.rs index 98c8d5d8..b098e34c 100644 --- a/iOverlay/src/float/scale.rs +++ b/iOverlay/src/float/scale.rs @@ -81,10 +81,8 @@ where fill_rule: FillRule, scale: T, ) -> Result, FixedScaleOverlayError> { - Ok( - FloatOverlay::with_subj_and_clip_fixed_scale(self, source, scale)? - .overlay(overlay_rule, fill_rule), - ) + Ok(FloatOverlay::with_subj_and_clip_fixed_scale(self, source, scale)? + .overlay(overlay_rule, fill_rule)) } } @@ -262,6 +260,8 @@ mod tests { assert!(FloatOverlay::with_subj_and_clip_fixed_scale(&left_rect, &right_rect, -1.0).is_err()); assert!(FloatOverlay::with_subj_and_clip_fixed_scale(&left_rect, &right_rect, 0.0).is_err()); assert!(FloatOverlay::with_subj_and_clip_fixed_scale(&left_rect, &right_rect, f64::NAN).is_err()); - assert!(FloatOverlay::with_subj_and_clip_fixed_scale(&left_rect, &right_rect, f64::INFINITY).is_err()); + assert!( + FloatOverlay::with_subj_and_clip_fixed_scale(&left_rect, &right_rect, f64::INFINITY).is_err() + ); } } diff --git a/iOverlay/src/float/simplify.rs b/iOverlay/src/float/simplify.rs index b0efd167..65b067d3 100644 --- a/iOverlay/src/float/simplify.rs +++ b/iOverlay/src/float/simplify.rs @@ -1,11 +1,11 @@ -use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; -use i_shape::base::data::Shapes; -use i_shape::source::resource::ShapeResource; use crate::core::fill_rule::FillRule; use crate::core::overlay_rule::OverlayRule; use crate::core::solver::Solver; use crate::float::overlay::{FloatOverlay, OverlayOptions}; +use i_float::float::compatible::FloatPointCompatible; +use i_float::float::number::FloatNumber; +use i_shape::base::data::Shapes; +use i_shape::source::resource::ShapeResource; /// Trait `Simplify` provides a method to simplify geometric shapes by reducing the number of points in contours or shapes /// while preserving overall shape and topology. The method applies a minimum area threshold and a build rule to @@ -24,7 +24,12 @@ pub trait SimplifyShape { /// - Returns: A collection of Shapes

that represents the simplified geometry. /// /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. - fn simplify_shape_custom(&self, fill_rule: FillRule, options: OverlayOptions, solver: Solver) -> Shapes

; + fn simplify_shape_custom( + &self, + fill_rule: FillRule, + options: OverlayOptions, + solver: Solver, + ) -> Shapes

; } impl SimplifyShape for S @@ -40,17 +45,21 @@ where } #[inline] - fn simplify_shape_custom(&self, fill_rule: FillRule, options: OverlayOptions, solver: Solver) -> Shapes

{ - FloatOverlay::with_subj_custom(self, options, solver) - .overlay(OverlayRule::Subject, fill_rule) + fn simplify_shape_custom( + &self, + fill_rule: FillRule, + options: OverlayOptions, + solver: Solver, + ) -> Shapes

{ + FloatOverlay::with_subj_custom(self, options, solver).overlay(OverlayRule::Subject, fill_rule) } } #[cfg(test)] mod tests { - use alloc::vec; use crate::core::fill_rule::FillRule; use crate::float::simplify::SimplifyShape; + use alloc::vec; #[test] fn test_contour_slice() { @@ -73,4 +82,4 @@ mod tests { assert_eq!(shapes[0].len(), 1); assert_eq!(shapes[0][0].len(), 4); } -} \ No newline at end of file +} diff --git a/iOverlay/src/float/single.rs b/iOverlay/src/float/single.rs index 6283d500..984d7f0f 100644 --- a/iOverlay/src/float/single.rs +++ b/iOverlay/src/float/single.rs @@ -1,10 +1,10 @@ +use crate::core::fill_rule::FillRule; +use crate::core::overlay_rule::OverlayRule; +use crate::float::overlay::FloatOverlay; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_shape::base::data::Shapes; use i_shape::source::resource::ShapeResource; -use crate::core::fill_rule::FillRule; -use crate::core::overlay_rule::OverlayRule; -use crate::float::overlay::FloatOverlay; /// Trait `SingleFloatOverlay` provides methods for overlay operations between various geometric entities. /// This trait supports boolean operations on contours, shapes, and collections of shapes, using customizable overlay and build rules. @@ -43,19 +43,18 @@ where #[cfg(test)] mod tests { - use alloc::vec; use crate::core::fill_rule::FillRule; use crate::core::overlay_rule::OverlayRule; use crate::float::overlay::FloatOverlay; use crate::float::single::SingleFloatOverlay; + use alloc::vec; #[test] fn test_contour() { let left_rect = vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]]; let right_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; - let shapes = left_rect - .overlay(&right_rect, OverlayRule::Union, FillRule::EvenOdd); + let shapes = left_rect.overlay(&right_rect, OverlayRule::Union, FillRule::EvenOdd); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -65,15 +64,9 @@ mod tests { #[test] fn test_contours() { let r3 = vec![ - vec![ - [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0] - ], - vec![ - [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0] - ], - vec![ - [1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0] - ] + vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]], + vec![[0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0]], + vec![[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0]], ]; let right_bottom_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; @@ -87,19 +80,11 @@ mod tests { #[test] fn test_shapes() { - let shapes = vec![ - vec![ - vec![ - [0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0] - ], - vec![ - [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0] - ], - vec![ - [1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0] - ] - ] - ]; + let shapes = vec![vec![ + vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]], + vec![[0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 1.0]], + vec![[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 1.0]], + ]]; let right_bottom_rect = vec![[1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 0.0]]; let shapes = FloatOverlay::with_subj_and_clip(&shapes, &right_bottom_rect) @@ -109,4 +94,4 @@ mod tests { assert_eq!(shapes[0].len(), 1); assert_eq!(shapes[0][0].len(), 4); } -} \ No newline at end of file +} diff --git a/iOverlay/src/float/string_graph.rs b/iOverlay/src/float/string_graph.rs index 8df49ac4..44363df5 100644 --- a/iOverlay/src/float/string_graph.rs +++ b/iOverlay/src/float/string_graph.rs @@ -1,3 +1,6 @@ +use crate::float::overlay::OverlayOptions; +use crate::string::graph::StringGraph; +use crate::string::rule::StringRule; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; @@ -5,9 +8,6 @@ use i_shape::base::data::Shapes; use i_shape::float::adapter::ShapesToFloat; use i_shape::float::despike::DeSpikeContour; use i_shape::float::simple::SimplifyContour; -use crate::float::overlay::OverlayOptions; -use crate::string::graph::StringGraph; -use crate::string::rule::StringRule; /// The `FloatStringGraph` struct represents a graph structure with floating-point precision, /// providing methods to extract geometric shapes from the graph after applying string-based operations. @@ -58,17 +58,19 @@ impl, T: FloatNumber> FloatStringGraph<'_, P, T> { /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. #[inline] pub fn extract_shapes_custom(&self, string_rule: StringRule, options: OverlayOptions) -> Shapes

{ - let shapes = self.graph.extract_shapes_custom(string_rule, options.int_with_adapter(&self.adapter)); + let shapes = self + .graph + .extract_shapes_custom(string_rule, options.int_with_adapter(&self.adapter)); let mut float = shapes.to_float(&self.adapter); if options.clean_result { if options.preserve_output_collinear { - float.despike_contour(&self.adapter); + float.despike_contour(&self.adapter); } else { - float.simplify_contour(&self.adapter); + float.simplify_contour(&self.adapter); } } float } -} \ No newline at end of file +} diff --git a/iOverlay/src/float/string_overlay.rs b/iOverlay/src/float/string_overlay.rs index f6f387b1..7509b4dc 100644 --- a/iOverlay/src/float/string_overlay.rs +++ b/iOverlay/src/float/string_overlay.rs @@ -99,11 +99,9 @@ impl, T: FloatNumber> FloatStringOverlay { let shape_capacity = shape.iter_paths().fold(0, |s, c| s + c.len()); let string_capacity = string.iter_paths().fold(0, |s, c| s + c.len()); - Ok( - Self::with_adapter(adapter, shape_capacity + string_capacity) - .unsafe_add_shapes(shape) - .unsafe_add_string_lines(string), - ) + Ok(Self::with_adapter(adapter, shape_capacity + string_capacity) + .unsafe_add_shapes(shape) + .unsafe_add_string_lines(string)) } /// Adds a shapes to the overlay. @@ -179,9 +177,7 @@ impl, T: FloatNumber> FloatStringOverlay { fill_rule: FillRule, solver: Solver, ) -> Option> { - let graph = self - .overlay - .build_graph_view_with_solver(fill_rule, solver)?; + let graph = self.overlay.build_graph_view_with_solver(fill_rule, solver)?; Some(FloatStringGraph { graph, adapter: self.adapter.clone(), @@ -229,19 +225,11 @@ mod tests { let shape = vec![vec![[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]]]; let string = vec![[0.0, 0.5], [2.0, 0.5]]; + assert!(FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, 0.0).is_err()); + assert!(FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, -1.0).is_err()); + assert!(FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, f64::NAN).is_err()); assert!( - FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, 0.0).is_err() - ); - assert!( - FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, -1.0).is_err() - ); - assert!( - FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, f64::NAN) - .is_err() - ); - assert!( - FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, f64::INFINITY) - .is_err() + FloatStringOverlay::with_shape_and_string_fixed_scale(&shape, &string, f64::INFINITY).is_err() ); } } diff --git a/iOverlay/src/geom/id_point.rs b/iOverlay/src/geom/id_point.rs index 60f961f0..d9a82f1f 100644 --- a/iOverlay/src/geom/id_point.rs +++ b/iOverlay/src/geom/id_point.rs @@ -10,4 +10,4 @@ impl IdPoint { pub(crate) fn new(id: usize, point: IntPoint) -> Self { Self { id, point } } -} \ No newline at end of file +} diff --git a/iOverlay/src/geom/line_range.rs b/iOverlay/src/geom/line_range.rs index 96548ea6..1a0bc40d 100644 --- a/iOverlay/src/geom/line_range.rs +++ b/iOverlay/src/geom/line_range.rs @@ -2,4 +2,4 @@ pub(crate) struct LineRange { pub(crate) min: i32, pub(crate) max: i32, -} \ No newline at end of file +} diff --git a/iOverlay/src/geom/mod.rs b/iOverlay/src/geom/mod.rs index 92726576..1e03434f 100644 --- a/iOverlay/src/geom/mod.rs +++ b/iOverlay/src/geom/mod.rs @@ -1,5 +1,5 @@ -pub(crate) mod x_segment; -pub(crate) mod v_segment; pub(crate) mod end; +pub(crate) mod id_point; pub(crate) mod line_range; -pub(crate) mod id_point; \ No newline at end of file +pub(crate) mod v_segment; +pub(crate) mod x_segment; diff --git a/iOverlay/src/geom/v_segment.rs b/iOverlay/src/geom/v_segment.rs index a9a2bd9d..3ea0e6d2 100644 --- a/iOverlay/src/geom/v_segment.rs +++ b/iOverlay/src/geom/v_segment.rs @@ -1,8 +1,8 @@ +use crate::geom::x_segment::XSegment; use core::cmp::Ordering; -use i_tree::ExpiredKey; use i_float::int::point::IntPoint; use i_float::triangle::Triangle; -use crate::geom::x_segment::XSegment; +use i_tree::ExpiredKey; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) struct VSegment { @@ -31,15 +31,9 @@ impl VSegment { #[inline(always)] pub(crate) fn is_under_segment(&self, other: &VSegment) -> bool { match self.a.cmp(&other.a) { - Ordering::Less => { - Triangle::is_clockwise_point(self.a, other.a, self.b) - } - Ordering::Equal => { - Triangle::is_clockwise_point(self.a, other.b, self.b) - } - Ordering::Greater => { - Triangle::is_clockwise_point(other.a, other.b, self.a) - } + Ordering::Less => Triangle::is_clockwise_point(self.a, other.a, self.b), + Ordering::Equal => Triangle::is_clockwise_point(self.a, other.b, self.b), + Ordering::Greater => Triangle::is_clockwise_point(other.a, other.b, self.a), } } @@ -84,15 +78,18 @@ impl ExpiredKey for VSegment { #[cfg(test)] mod tests { + use crate::geom::v_segment::VSegment; use core::cmp::Ordering; use i_float::int::point::IntPoint; - use crate::geom::v_segment::VSegment; #[test] fn test_00() { let p = IntPoint::new(-10, 10); - let s = VSegment { a: IntPoint::new(-10, -10), b: IntPoint::new(10, -10) }; + let s = VSegment { + a: IntPoint::new(-10, -10), + b: IntPoint::new(10, -10), + }; let order = s.is_under_point_order(p); assert_eq!(order, Ordering::Less); } -} \ No newline at end of file +} diff --git a/iOverlay/src/geom/x_segment.rs b/iOverlay/src/geom/x_segment.rs index 4b64e6b1..cae600bd 100644 --- a/iOverlay/src/geom/x_segment.rs +++ b/iOverlay/src/geom/x_segment.rs @@ -1,6 +1,6 @@ +use crate::geom::line_range::LineRange; use core::cmp::Ordering; use i_float::int::point::IntPoint; -use crate::geom::line_range::LineRange; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) struct XSegment { @@ -12,9 +12,15 @@ impl XSegment { #[inline(always)] pub(crate) fn y_range(&self) -> LineRange { if self.a.y < self.b.y { - LineRange { min: self.a.y, max: self.b.y } + LineRange { + min: self.a.y, + max: self.b.y, + } } else { - LineRange { min: self.b.y, max: self.a.y } + LineRange { + min: self.b.y, + max: self.a.y, + } } } @@ -23,7 +29,6 @@ impl XSegment { self.a.x != self.b.x } - #[inline(always)] pub(crate) fn is_not_intersect_y_range(&self, range: &LineRange) -> bool { range.min > self.a.y && range.min > self.b.y || range.max < self.a.y && range.max < self.b.y @@ -47,4 +52,4 @@ impl Ord for XSegment { a } } -} \ No newline at end of file +} diff --git a/iOverlay/src/lib.rs b/iOverlay/src/lib.rs index 27b3ac39..16db78aa 100644 --- a/iOverlay/src/lib.rs +++ b/iOverlay/src/lib.rs @@ -190,18 +190,18 @@ #![no_std] extern crate alloc; -pub mod mesh; pub mod build; pub mod core; -pub mod vector; pub mod float; -pub mod string; +pub mod mesh; pub mod segm; +pub mod string; +pub mod vector; -pub(crate) mod split; pub(crate) mod bind; pub(crate) mod geom; +pub(crate) mod split; pub(crate) mod util; pub use i_float; -pub use i_shape; \ No newline at end of file +pub use i_shape; diff --git a/iOverlay/src/mesh/extract.rs b/iOverlay/src/mesh/extract.rs index e086b5e0..8d8dff04 100644 --- a/iOverlay/src/mesh/extract.rs +++ b/iOverlay/src/mesh/extract.rs @@ -1,15 +1,15 @@ -use alloc::vec; -use alloc::vec::Vec; -use i_shape::int::shape::{IntContour, IntShapes}; use crate::bind::segment::{ContourIndex, IdSegment}; use crate::bind::solver::{JoinHoles, LeftBottomSegment}; -use crate::core::extract::{GraphUtil, StartPathData, GraphContour, Visit, VisitState}; +use crate::core::extract::{GraphContour, GraphUtil, StartPathData, Visit, VisitState}; use crate::core::link::OverlayLinkFilter; use crate::core::overlay::ContourDirection; use crate::core::overlay_rule::OverlayRule; use crate::geom::v_segment::VSegment; use crate::mesh::graph::OffsetGraph; use crate::segm::segment::SUBJ_TOP; +use alloc::vec; +use alloc::vec::Vec; +use i_shape::int::shape::{IntContour, IntShapes}; impl OffsetGraph<'_> { pub(crate) fn extract_offset(&self, main_direction: ContourDirection, min_area: u64) -> IntShapes { @@ -54,8 +54,7 @@ impl OffsetGraph<'_> { let start_data = StartPathData::new(direction, link, left_top_link); - let mut contour = - self.get_fill_contour(&start_data, direction, &mut bold, visited); + let mut contour = self.get_fill_contour(&start_data, direction, &mut bold, visited); if !bold { link_index += 1; continue; @@ -124,14 +123,7 @@ impl OffsetGraph<'_> { // Find a closed tour while node_id != last_node_id { - link_id = GraphUtil::next_link( - self.links, - self.nodes, - link_id, - node_id, - clockwise, - visited, - ); + link_id = GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, visited); let link = unsafe { // SAFETY: `link_id` is always derived from a previous in-bounds index or diff --git a/iOverlay/src/mesh/graph.rs b/iOverlay/src/mesh/graph.rs index 67e49809..169ceda4 100644 --- a/iOverlay/src/mesh/graph.rs +++ b/iOverlay/src/mesh/graph.rs @@ -4,4 +4,4 @@ use crate::core::link::OverlayLink; pub struct OffsetGraph<'a> { pub(crate) nodes: &'a [OverlayNode], pub(crate) links: &'a [OverlayLink], -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/math.rs b/iOverlay/src/mesh/math.rs index c12cf6d6..b81f3a79 100644 --- a/iOverlay/src/mesh/math.rs +++ b/iOverlay/src/mesh/math.rs @@ -17,4 +17,4 @@ impl> Math { let t = P::from_xy(-p.y(), p.x()); FloatPointMath::scale(&t, s) } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/mod.rs b/iOverlay/src/mesh/mod.rs index df0fb809..d6f71b7b 100644 --- a/iOverlay/src/mesh/mod.rs +++ b/iOverlay/src/mesh/mod.rs @@ -1,10 +1,10 @@ -pub mod stroke; -pub mod outline; -pub(crate) mod math; +mod extract; pub(crate) mod graph; -mod rotator; -mod subject; -pub mod style; +pub(crate) mod math; mod miter; +pub mod outline; mod overlay; -mod extract; \ No newline at end of file +mod rotator; +pub mod stroke; +pub mod style; +mod subject; diff --git a/iOverlay/src/mesh/outline/builder.rs b/iOverlay/src/mesh/outline/builder.rs index 6c157d8f..0df178e8 100644 --- a/iOverlay/src/mesh/outline/builder.rs +++ b/iOverlay/src/mesh/outline/builder.rs @@ -1,14 +1,14 @@ +use crate::mesh::outline::builder_join::{BevelJoinBuilder, JoinBuilder, MiterJoinBuilder, RoundJoinBuilder}; +use crate::mesh::outline::section::{Section, SectionToSegment}; +use crate::mesh::style::LineJoin; +use crate::segm::offset::ShapeCountOffset; +use crate::segm::segment::Segment; use alloc::boxed::Box; use alloc::vec::Vec; use core::marker::PhantomData; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; -use crate::mesh::outline::builder_join::{JoinBuilder, BevelJoinBuilder, MiterJoinBuilder, RoundJoinBuilder}; -use crate::mesh::outline::section::{Section, SectionToSegment}; -use crate::mesh::style::LineJoin; -use crate::segm::offset::ShapeCountOffset; -use crate::segm::segment::Segment; trait OutlineBuild, T: FloatNumber> { fn build( @@ -23,7 +23,7 @@ trait OutlineBuild, T: FloatNumber> { } pub(super) struct OutlineBuilder, T: FloatNumber> { - builder: Box> + builder: Box>, } struct Builder, P: FloatPointCompatible, T: FloatNumber> { @@ -34,7 +34,6 @@ struct Builder, P: FloatPointCompatible, T: FloatNumber> impl + 'static, T: FloatNumber + 'static> OutlineBuilder { pub(super) fn new(radius: T, join: &LineJoin) -> OutlineBuilder { - let builder: Box> = match join { LineJoin::Miter(ratio) => Box::new(Builder { radius, @@ -67,10 +66,7 @@ impl + 'static, T: FloatNumber + 'static> OutlineBuil } #[inline] - pub(super) fn capacity( - &self, - points_count: usize, - ) -> usize { + pub(super) fn capacity(&self, points_count: usize) -> usize { self.builder.capacity(points_count) } @@ -80,7 +76,8 @@ impl + 'static, T: FloatNumber + 'static> OutlineBuil } } -impl, P: FloatPointCompatible, T: FloatNumber> OutlineBuild for Builder +impl, P: FloatPointCompatible, T: FloatNumber> OutlineBuild + for Builder { #[inline] fn build( @@ -89,12 +86,16 @@ impl, P: FloatPointCompatible, T: FloatNumber> OutlineBu adapter: &FloatPointAdapter, segments: &mut Vec>, ) { - if path.len() < 2 { return; } + if path.len() < 2 { + return; + } // build segments only from points which are not equal in int space let i0 = path.len() - 1; let i1 = Self::next_unique_point(i0, 0, path, adapter); - if i1 == usize::MAX { return } + if i1 == usize::MAX { + return; + } let start = Section::new(self.radius, &path[i0], &path[i1]); let mut s0 = start.clone(); @@ -138,4 +139,4 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder, T: FloatNumber> { fn add_join( @@ -48,7 +48,6 @@ impl BevelJoinBuilder { segments.push(Segment::weak_subject_ab(ia, ib)); } } - } impl> JoinBuilder for BevelJoinBuilder { @@ -120,7 +119,7 @@ impl> JoinBuilder for MiterJoin let turn = cross_product >= T::from_float(0.0); if turn == self.expand { BevelJoinBuilder::join_weak(s0, s1, adapter, segments); - return + return; } let pa = s0.b_top; @@ -132,7 +131,7 @@ impl> JoinBuilder for MiterJoin let sq_len = ia.sqr_distance(ib); if sq_len < 4 { BevelJoinBuilder::join_weak(s0, s1, adapter, segments); - return + return; } let dot_product = FloatPointMath::dot_product(&s0.dir, &s1.dir); @@ -167,7 +166,7 @@ impl> JoinBuilder for MiterJoin SharpMiter::AcB(a, c, b) => { segments.push(Segment::bold_subject_ab(a, c)); segments.push(Segment::bold_subject_ab(c, b)); - }, + } SharpMiter::Degenerate => {} } } @@ -227,7 +226,7 @@ impl> JoinBuilder for RoundJoin let turn = cross_product >= T::from_float(0.0); if turn == self.expand { BevelJoinBuilder::join_weak(s0, s1, adapter, segments); - return + return; } let dot_product = FloatPointMath::dot_product(&s0.dir, &s1.dir); @@ -277,4 +276,4 @@ impl> JoinBuilder for RoundJoin // add extra 10% to avoid problems with floating point precision. T::from_float(1.1) * radius } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/outline/mod.rs b/iOverlay/src/mesh/outline/mod.rs index 5a72b900..adf73534 100644 --- a/iOverlay/src/mesh/outline/mod.rs +++ b/iOverlay/src/mesh/outline/mod.rs @@ -1,4 +1,4 @@ -pub mod offset; mod builder; mod builder_join; +pub mod offset; mod section; diff --git a/iOverlay/src/mesh/outline/offset.rs b/iOverlay/src/mesh/outline/offset.rs index 088bc06c..14ddab6a 100644 --- a/iOverlay/src/mesh/outline/offset.rs +++ b/iOverlay/src/mesh/outline/offset.rs @@ -1,23 +1,23 @@ -use i_shape::source::resource::ShapeResource; -use alloc::vec; -use alloc::vec::Vec; use crate::core::fill_rule::FillRule; use crate::core::overlay::{ContourDirection, Overlay, ShapeType}; use crate::core::overlay_rule::OverlayRule; use crate::float::overlay::OverlayOptions; use crate::float::scale::FixedScaleOverlayError; use crate::mesh::outline::builder::OutlineBuilder; +use crate::mesh::overlay::OffsetOverlay; use crate::mesh::style::OutlineStyle; +use alloc::vec; +use alloc::vec::Vec; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_float::float::rect::FloatRect; use i_shape::base::data::Shapes; use i_shape::float::adapter::ShapesToFloat; -use i_shape::float::int_area::IntArea; use i_shape::float::despike::DeSpikeContour; +use i_shape::float::int_area::IntArea; use i_shape::float::simple::SimplifyContour; -use crate::mesh::overlay::OffsetOverlay; +use i_shape::source::resource::ShapeResource; pub trait OutlineOffset, T: FloatNumber> { /// Generates an outline shapes for contours, or shapes. @@ -147,8 +147,7 @@ impl + 'static, T: FloatNumber + 'static> OutlineSolv let additional_offset = outer_additional_offset.abs() + inner_additional_offset.abs(); - let mut rect = - FloatRect::with_iter(source.iter_paths().flatten()).unwrap_or(FloatRect::zero()); + let mut rect = FloatRect::with_iter(source.iter_paths().flatten()).unwrap_or(FloatRect::zero()); rect.add_offset(additional_offset); let adapter = FloatPointAdapter::new(rect); @@ -289,9 +288,9 @@ impl + 'static, T: FloatNumber + 'static> OutlineSolv #[cfg(test)] mod tests { - use alloc::vec; use crate::mesh::outline::offset::OutlineOffset; use crate::mesh::style::{LineJoin, OutlineStyle}; + use alloc::vec; use core::f32::consts::PI; #[test] @@ -408,7 +407,10 @@ mod tests { #[test] fn test_float_square_0() { let shape = vec![vec![ - [300.0, 300.0], [500.0, 300.0], [500.0, 500.0], [300.0, 500.0] + [300.0, 300.0], + [500.0, 300.0], + [500.0, 500.0], + [300.0, 500.0], ]]; let style = OutlineStyle::default().outer_offset(50.0).inner_offset(50.0); @@ -474,7 +476,7 @@ mod tests { [5400.0, 5891947.742386343], [5400.0, 5892817.151239874], [4804.8188261491, 5892876.799252035], - [4804.81882805645, 5892876.799253942] + [4804.81882805645, 5892876.799253942], ]; let angle = 10.0f64 / (core::f64::consts::PI / 2.0f64); diff --git a/iOverlay/src/mesh/outline/section.rs b/iOverlay/src/mesh/outline/section.rs index 7785dece..01eafd7a 100644 --- a/iOverlay/src/mesh/outline/section.rs +++ b/iOverlay/src/mesh/outline/section.rs @@ -1,12 +1,12 @@ +use crate::mesh::math::Math; +use crate::segm::offset::ShapeCountOffset; +use crate::segm::segment::Segment; use alloc::vec::Vec; use core::marker::PhantomData; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; -use crate::mesh::math::Math; -use crate::segm::offset::ShapeCountOffset; -use crate::segm::segment::Segment; #[derive(Debug, Clone)] pub(super) struct Section, T: FloatNumber> { @@ -47,4 +47,4 @@ impl> SectionToSegment for Vec< self.push(Segment::bold_subject_ab(a_top, b_top)); } } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/overlay.rs b/iOverlay/src/mesh/overlay.rs index a0a1c8dd..39149c6c 100644 --- a/iOverlay/src/mesh/overlay.rs +++ b/iOverlay/src/mesh/overlay.rs @@ -1,4 +1,3 @@ -use alloc::vec::Vec; use crate::build::builder::GraphBuilder; use crate::core::graph::OverlayNode; use crate::core::solver::Solver; @@ -6,11 +5,12 @@ use crate::mesh::graph::OffsetGraph; use crate::segm::offset::ShapeCountOffset; use crate::segm::segment::Segment; use crate::split::solver::SplitSolver; +use alloc::vec::Vec; pub struct OffsetOverlay { pub(super) segments: Vec>, pub(crate) split_solver: SplitSolver, - pub(crate) graph_builder: GraphBuilder + pub(crate) graph_builder: GraphBuilder, } impl OffsetOverlay { @@ -19,7 +19,7 @@ impl OffsetOverlay { Self { segments: Vec::with_capacity(capacity), split_solver: SplitSolver::new(), - graph_builder: GraphBuilder::::new() + graph_builder: GraphBuilder::::new(), } } @@ -28,7 +28,6 @@ impl OffsetOverlay { self.segments.clear(); } - #[inline] pub fn add_segments(&mut self, segments: &[Segment]) { self.segments.extend_from_slice(segments); @@ -39,7 +38,7 @@ impl OffsetOverlay { Self { segments, split_solver: SplitSolver::new(), - graph_builder: GraphBuilder::::new() + graph_builder: GraphBuilder::::new(), } } @@ -49,10 +48,8 @@ impl OffsetOverlay { if self.segments.is_empty() { return None; } - let graph = self - .graph_builder - .build_offset(&solver, &self.segments); + let graph = self.graph_builder.build_offset(&solver, &self.segments); Some(graph) } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/rotator.rs b/iOverlay/src/mesh/rotator.rs index 8e499679..5ab4e930 100644 --- a/iOverlay/src/mesh/rotator.rs +++ b/iOverlay/src/mesh/rotator.rs @@ -9,7 +9,6 @@ pub(crate) struct Rotator { } impl Rotator { - #[inline] pub(crate) fn new(cs: T, sn: T) -> Self { let a_x = cs; @@ -17,12 +16,7 @@ impl Rotator { let b_x = -a_y; let b_y = a_x; - Self { - a_x, - a_y, - b_x, - b_y, - } + Self { a_x, a_y, b_x, b_y } } #[inline] @@ -48,9 +42,8 @@ impl Rotator { #[cfg(test)] mod tests { - use core::f64::consts::PI; use crate::mesh::rotator::Rotator; - + use core::f64::consts::PI; #[test] fn test_ccw_rotate() { @@ -88,4 +81,4 @@ mod tests { assert!((v0[0] - v1[0]).abs() < 0.0001); assert!((v0[1] - v1[1]).abs() < 0.0001); } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/stroke/builder.rs b/iOverlay/src/mesh/stroke/builder.rs index 6c5784a5..b0f25353 100644 --- a/iOverlay/src/mesh/stroke/builder.rs +++ b/iOverlay/src/mesh/stroke/builder.rs @@ -1,16 +1,14 @@ -use alloc::boxed::Box; -use alloc::vec::Vec; use crate::mesh::stroke::builder_cap::CapBuilder; -use crate::mesh::stroke::builder_join::{ - BevelJoinBuilder, JoinBuilder, MiterJoinBuilder, RoundJoinBuilder, -}; +use crate::mesh::stroke::builder_join::{BevelJoinBuilder, JoinBuilder, MiterJoinBuilder, RoundJoinBuilder}; use crate::mesh::stroke::section::{Section, SectionToSegment}; use crate::mesh::style::{LineJoin, StrokeStyle}; +use crate::segm::offset::ShapeCountOffset; use crate::segm::segment::Segment; +use alloc::boxed::Box; +use alloc::vec::Vec; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; -use crate::segm::offset::ShapeCountOffset; trait StrokeBuild, T: FloatNumber> { fn build( @@ -79,12 +77,7 @@ impl + 'static, T: FloatNumber + 'static> StrokeBuild } #[inline] - pub(super) fn capacity( - &self, - paths_count: usize, - points_count: usize, - is_closed_path: bool, - ) -> usize { + pub(super) fn capacity(&self, paths_count: usize, points_count: usize, is_closed_path: bool) -> usize { self.builder.capacity(paths_count, points_count, is_closed_path) } @@ -94,7 +87,8 @@ impl + 'static, T: FloatNumber + 'static> StrokeBuild } } -impl, P: FloatPointCompatible, T: FloatNumber> StrokeBuild for Builder +impl, P: FloatPointCompatible, T: FloatNumber> StrokeBuild + for Builder { #[inline] fn build( @@ -117,8 +111,7 @@ impl, P: FloatPointCompatible, T: FloatNumber> StrokeBui self.join_builder.capacity() * points_count - 2 } else { self.join_builder.capacity() * (points_count.saturating_sub(1)) - + paths_count - * (self.end_cap_builder.capacity() + self.start_cap_builder.capacity()) + + paths_count * (self.end_cap_builder.capacity() + self.start_cap_builder.capacity()) } } @@ -142,7 +135,7 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder, P: FloatPointCompatible, T: FloatNumber> Builder= n { return; } + if j >= n { + return; + } ip = adapter.float_to_int(&path[j]); } @@ -162,13 +157,14 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder= n { break 'main_loop; } + if j >= n { + break 'main_loop; + } p = &path[j]; ip = adapter.float_to_int(p); } @@ -188,12 +184,16 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder, segments: &mut Vec>, ) { - if path.len() < 2 { return; } + if path.len() < 2 { + return; + } // build segments only from points which are not equal in int space let i0 = path.len() - 1; let i1 = Self::next_unique_point(i0, 0, path, adapter); - if i1 == usize::MAX { return } + if i1 == usize::MAX { + return; + } let start = Section::new(self.radius, &path[i0], &path[i1]); let mut s0 = start.clone(); @@ -225,5 +225,4 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder { @@ -20,16 +20,18 @@ pub(super) struct CapBuilder { } impl> CapBuilder { - pub(super) fn new(cap: LineCap, radius: T) -> Self { let points = match cap { LineCap::Butt => None, LineCap::Round(ratio) => Some(Self::round_points(ratio, radius)), LineCap::Square => Some(Self::square_points(radius)), - LineCap::Custom(points) => Some(Self::custom_points(points.to_vec(), radius)) + LineCap::Custom(points) => Some(Self::custom_points(points.to_vec(), radius)), }; - Self { points, _phantom: Default::default() } + Self { + points, + _phantom: Default::default(), + } } pub(super) fn round_points(angle: T, r: T) -> Vec

{ @@ -69,7 +71,12 @@ impl> CapBuilder { scaled } - pub(super) fn add_to_start(&self, section: &Section, adapter: &FloatPointAdapter, segments: &mut Vec>) { + pub(super) fn add_to_start( + &self, + section: &Section, + adapter: &FloatPointAdapter, + segments: &mut Vec>, + ) { let mut a = adapter.float_to_int(§ion.a_top); if let Some(points) = &self.points { let dir = P::from_xy(-section.dir.x(), -section.dir.y()); @@ -86,7 +93,12 @@ impl> CapBuilder { segments.push(Segment::bold_subject_ab(a, last)); } - pub(super) fn add_to_end(&self, section: &Section, adapter: &FloatPointAdapter, segments: &mut Vec>) { + pub(super) fn add_to_end( + &self, + section: &Section, + adapter: &FloatPointAdapter, + segments: &mut Vec>, + ) { let mut a = adapter.float_to_int(§ion.b_bot); if let Some(points) = &self.points { let rotator = Rotator::with_vector(§ion.dir); @@ -123,4 +135,4 @@ impl> CapBuilder { T::from_float(0.0) } } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/stroke/builder_join.rs b/iOverlay/src/mesh/stroke/builder_join.rs index 80e269ca..33760d9d 100644 --- a/iOverlay/src/mesh/stroke/builder_join.rs +++ b/iOverlay/src/mesh/stroke/builder_join.rs @@ -1,14 +1,14 @@ -use alloc::vec::Vec; +use crate::mesh::miter::{Miter, SharpMiter}; +use crate::mesh::rotator::Rotator; use crate::mesh::stroke::section::Section; +use crate::segm::offset::ShapeCountOffset; use crate::segm::segment::Segment; +use alloc::vec::Vec; +use core::f64::consts::PI; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; -use core::f64::consts::PI; use i_float::float::vector::FloatPointMath; -use crate::mesh::miter::{Miter, SharpMiter}; -use crate::mesh::rotator::Rotator; -use crate::segm::offset::ShapeCountOffset; pub(super) trait JoinBuilder, T: FloatNumber> { fn add_join( @@ -58,7 +58,6 @@ impl BevelJoinBuilder { segments.push(Segment::bold_subject_ab(ib, ia)); } } - } impl> JoinBuilder for BevelJoinBuilder { @@ -113,7 +112,7 @@ impl MiterJoinBuilder { Self { limit_dot_product, max_offset, - max_length + max_length, } } } @@ -200,7 +199,7 @@ impl> JoinBuilder for MiterJoin SharpMiter::AcB(a, c, b) => { segments.push(Segment::bold_subject_ab(c, a)); segments.push(Segment::bold_subject_ab(b, c)); - }, + } SharpMiter::Degenerate => {} } } @@ -299,4 +298,4 @@ impl> JoinBuilder for RoundJoin // add extra 10% to avoid problems with floating point precision. T::from_float(1.1) * radius } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/stroke/mod.rs b/iOverlay/src/mesh/stroke/mod.rs index 79abf622..4d1e1384 100644 --- a/iOverlay/src/mesh/stroke/mod.rs +++ b/iOverlay/src/mesh/stroke/mod.rs @@ -1,5 +1,5 @@ -pub mod offset; +mod builder; +mod builder_cap; mod builder_join; +pub mod offset; mod section; -mod builder; -mod builder_cap; \ No newline at end of file diff --git a/iOverlay/src/mesh/stroke/offset.rs b/iOverlay/src/mesh/stroke/offset.rs index eadd4fe0..69d931a4 100644 --- a/iOverlay/src/mesh/stroke/offset.rs +++ b/iOverlay/src/mesh/stroke/offset.rs @@ -153,8 +153,7 @@ impl, T: 'static + FloatNumber> StrokeSolve let builder = StrokeBuilder::new(style); let a = builder.additional_offset(r); - let mut rect = - FloatRect::with_iter(source.iter_paths().flatten()).unwrap_or(FloatRect::zero()); + let mut rect = FloatRect::with_iter(source.iter_paths().flatten()).unwrap_or(FloatRect::zero()); rect.add_offset(a); let adapter = FloatPointAdapter::new(rect); @@ -428,10 +427,7 @@ mod tests { assert!(path.stroke_fixed_scale(style.clone(), false, 0.0).is_err()); assert!(path.stroke_fixed_scale(style.clone(), false, -1.0).is_err()); - assert!( - path.stroke_fixed_scale(style.clone(), false, f64::NAN) - .is_err() - ); + assert!(path.stroke_fixed_scale(style.clone(), false, f64::NAN).is_err()); assert!( path.stroke_fixed_scale(style.clone(), false, f64::INFINITY) .is_err() diff --git a/iOverlay/src/mesh/stroke/section.rs b/iOverlay/src/mesh/stroke/section.rs index fb54f58e..acd7957d 100644 --- a/iOverlay/src/mesh/stroke/section.rs +++ b/iOverlay/src/mesh/stroke/section.rs @@ -1,12 +1,12 @@ +use crate::mesh::math::Math; +use crate::segm::offset::ShapeCountOffset; +use crate::segm::segment::Segment; use alloc::vec::Vec; use core::marker::PhantomData; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; -use crate::mesh::math::Math; -use crate::segm::offset::ShapeCountOffset; -use crate::segm::segment::Segment; #[derive(Debug, Clone)] pub(super) struct Section, T: FloatNumber> { @@ -62,4 +62,4 @@ impl> SectionToSegment for Vec< self.push(Segment::bold_subject_ab(a_bot, b_bot)); } } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/style.rs b/iOverlay/src/mesh/style.rs index 1d91944a..5ddbf45d 100644 --- a/iOverlay/src/mesh/style.rs +++ b/iOverlay/src/mesh/style.rs @@ -14,7 +14,7 @@ pub enum LineCap, T: FloatNumber> { /// A line with a squared-off end. An extended distance equal to half the line width. Square, /// Set a custom end with template points. - Custom(Rc<[P]>) + Custom(Rc<[P]>), } /// The join style of a line. @@ -75,7 +75,7 @@ impl LineJoin { let a = angle.to_f64().clamp(0.01 * PI, 0.25 * PI); LineJoin::Round(T::from_float(a)) } - _ => self + _ => self, } } } @@ -83,7 +83,10 @@ impl LineJoin { impl, T: FloatNumber> StrokeStyle { /// Creates a new `StrokeStyle` with the specified width. pub fn new(width: T) -> Self { - Self { width, ..Default::default() } + Self { + width, + ..Default::default() + } } /// Sets the stroke width. @@ -117,16 +120,19 @@ impl, T: FloatNumber> Default for StrokeStyle { width: T::from_float(1.0), start_cap: LineCap::Butt, end_cap: LineCap::Butt, - join: LineJoin::Bevel + join: LineJoin::Bevel, } } } impl OutlineStyle { - /// Creates a new `OutlineStyle` with the specified offset. pub fn new(offset: T) -> Self { - Self { outer_offset: offset, inner_offset: offset, ..Default::default() } + Self { + outer_offset: offset, + inner_offset: offset, + ..Default::default() + } } /// Sets the offset distance. @@ -160,7 +166,7 @@ impl Default for OutlineStyle { Self { outer_offset: T::from_float(1.0), inner_offset: T::from_float(1.0), - join: LineJoin::Bevel + join: LineJoin::Bevel, } } -} \ No newline at end of file +} diff --git a/iOverlay/src/mesh/subject.rs b/iOverlay/src/mesh/subject.rs index 11c9294a..22467f3e 100644 --- a/iOverlay/src/mesh/subject.rs +++ b/iOverlay/src/mesh/subject.rs @@ -1,10 +1,9 @@ use crate::geom::x_segment::XSegment; +use crate::segm::offset::ShapeCountOffset; use crate::segm::segment::Segment; use i_float::int::point::IntPoint; -use crate::segm::offset::ShapeCountOffset; impl Segment { - #[inline] pub(crate) fn bold_subject_ab(p0: IntPoint, p1: IntPoint) -> Self { if p0 < p1 { @@ -30,8 +29,11 @@ impl Segment { } else { Self { x_segment: XSegment { a: p1, b: p0 }, - count: ShapeCountOffset { subj: -1, bold: false }, + count: ShapeCountOffset { + subj: -1, + bold: false, + }, } } } -} \ No newline at end of file +} diff --git a/iOverlay/src/segm/boolean.rs b/iOverlay/src/segm/boolean.rs index 10b5a15b..17793892 100644 --- a/iOverlay/src/segm/boolean.rs +++ b/iOverlay/src/segm/boolean.rs @@ -16,16 +16,20 @@ impl ShapeCountBoolean { impl WindingCount for ShapeCountBoolean { #[inline(always)] - fn is_not_empty(&self) -> bool { self.subj != 0 || self.clip != 0 } + fn is_not_empty(&self) -> bool { + self.subj != 0 || self.clip != 0 + } #[inline(always)] - fn new(subj: i32, clip: i32) -> Self { Self { subj, clip } } + fn new(subj: i32, clip: i32) -> Self { + Self { subj, clip } + } #[inline(always)] fn with_shape_type(shape_type: ShapeType) -> (Self, Self) { match shape_type { ShapeType::Subject => (ShapeCountBoolean::SUBJ_DIRECT, ShapeCountBoolean::SUBJ_INVERT), - ShapeType::Clip => (ShapeCountBoolean::CLIP_DIRECT, ShapeCountBoolean::CLIP_INVERT) + ShapeType::Clip => (ShapeCountBoolean::CLIP_DIRECT, ShapeCountBoolean::CLIP_INVERT), } } @@ -45,6 +49,9 @@ impl WindingCount for ShapeCountBoolean { #[inline(always)] fn invert(self) -> Self { - Self { subj: -self.subj, clip: -self.clip } + Self { + subj: -self.subj, + clip: -self.clip, + } } -} \ No newline at end of file +} diff --git a/iOverlay/src/segm/build.rs b/iOverlay/src/segm/build.rs index 21e26d7a..57f3cbd9 100644 --- a/iOverlay/src/segm/build.rs +++ b/iOverlay/src/segm/build.rs @@ -36,8 +36,16 @@ fn build_segments_with_filter, C: W shape_type: ShapeType, ) -> bool { // our goal add all not degenerate segments - let mut p0 = if let Some(p) = iter.next() { p } else { return false; }; - let mut p1 = if let Some(p) = iter.find(|p| p0.ne(p)) { p } else { return true; }; + let mut p0 = if let Some(p) = iter.next() { + p + } else { + return false; + }; + let mut p1 = if let Some(p) = iter.find(|p| p0.ne(p)) { + p + } else { + return true; + }; let mut filtered = false; @@ -244,11 +252,7 @@ mod tests { #[test] fn test_roll_5() { - let points = [ - IntPoint::new(0, 0), - IntPoint::new(1, 0), - IntPoint::new(2, 0), - ]; + let points = [IntPoint::new(0, 0), IntPoint::new(1, 0), IntPoint::new(2, 0)]; test_roll_count(&points, 0, false); test_roll_count(&points, 0, true); @@ -388,11 +392,7 @@ mod tests { fn test_count(points: &[IntPoint], count: usize, keep_same_line_points: bool) { let mut segments: Vec> = Vec::new(); - segments.append_path_iter( - points.iter().copied(), - ShapeType::Subject, - keep_same_line_points, - ); + segments.append_path_iter(points.iter().copied(), ShapeType::Subject, keep_same_line_points); segments.merge_if_needed(); assert_eq!(segments.len(), count); @@ -403,11 +403,7 @@ mod tests { let n = points.len(); let mut segments: Vec> = Vec::with_capacity(n); for _ in 0..n { - segments.append_path_iter( - points.iter().copied(), - ShapeType::Subject, - keep_same_line_points, - ); + segments.append_path_iter(points.iter().copied(), ShapeType::Subject, keep_same_line_points); segments.merge_if_needed(); assert_eq!(segments.len(), count); diff --git a/iOverlay/src/segm/merge.rs b/iOverlay/src/segm/merge.rs index ffab199c..d015d9ae 100644 --- a/iOverlay/src/segm/merge.rs +++ b/iOverlay/src/segm/merge.rs @@ -1,6 +1,6 @@ -use alloc::vec::Vec; use crate::segm::segment::Segment; use crate::segm::winding::WindingCount; +use alloc::vec::Vec; pub(crate) trait ShapeSegmentsMerge { fn merge_if_needed(&mut self) -> bool; @@ -8,7 +8,9 @@ pub(crate) trait ShapeSegmentsMerge { impl ShapeSegmentsMerge for Vec> { fn merge_if_needed(&mut self) -> bool { - if self.len() < 2 { return false; } + if self.len() < 2 { + return false; + } let mut prev = &self[0].x_segment; for i in 1..self.len() { @@ -53,16 +55,19 @@ fn merge(segments: &mut [Segment], after: usize) -> usize { #[cfg(test)] mod tests { - use alloc::vec; -use crate::segm::boolean::ShapeCountBoolean; -use i_float::int::point::IntPoint; use super::*; + use crate::segm::boolean::ShapeCountBoolean; + use alloc::vec; + use i_float::int::point::IntPoint; #[test] fn test_merge_if_needed_empty() { let mut segments: Vec> = Vec::new(); segments.merge_if_needed(); - assert!(segments.is_empty(), "Empty vector should remain empty after merge"); + assert!( + segments.is_empty(), + "Empty vector should remain empty after merge" + ); } #[test] @@ -92,7 +97,11 @@ use i_float::int::point::IntPoint; let mut segments = vec![segment1, segment2]; segments.merge_if_needed(); - assert_eq!(segments.len(), 2, "Segments with different x_segments should not be merged"); + assert_eq!( + segments.len(), + 2, + "Segments with different x_segments should not be merged" + ); assert_eq!(segments[0], segment1, "First segment should remain unchanged"); assert_eq!(segments[1], segment2, "Second segment should remain unchanged"); } @@ -115,7 +124,10 @@ use i_float::int::point::IntPoint; assert_eq!(segments.len(), 1, "Segments should be merged into one"); let merged_count = ShapeCountBoolean::new(1, 1); let expected_segment = Segment::create_and_validate(a1, b1, merged_count); - assert_eq!(segments[0], expected_segment, "Merged segment should have combined counts"); + assert_eq!( + segments[0], expected_segment, + "Merged segment should have combined counts" + ); } #[test] @@ -137,7 +149,10 @@ use i_float::int::point::IntPoint; assert_eq!(segments.len(), 1, "All segments should be merged into one"); let merged_count = ShapeCountBoolean::new(3, 3); let expected_segment = Segment::create_and_validate(a, b, merged_count); - assert_eq!(segments[0], expected_segment, "Merged segment should have combined counts"); + assert_eq!( + segments[0], expected_segment, + "Merged segment should have combined counts" + ); } #[test] @@ -157,11 +172,19 @@ use i_float::int::point::IntPoint; segments.merge_if_needed(); // Both segments should have the same ordered x_segment - assert_eq!(segments.len(), 1, "Segments with inverted points should be merged"); + assert_eq!( + segments.len(), + 1, + "Segments with inverted points should be merged" + ); let merged_count = ShapeCountBoolean::new(1, 1); - let expected_segment = Segment::create_and_validate(IntPoint::new(1, 2), IntPoint::new(3, 4), merged_count); - assert_eq!(segments[0], expected_segment, "Merged segment should have combined counts and ordered points"); + let expected_segment = + Segment::create_and_validate(IntPoint::new(1, 2), IntPoint::new(3, 4), merged_count); + assert_eq!( + segments[0], expected_segment, + "Merged segment should have combined counts and ordered points" + ); } #[test] @@ -184,7 +207,11 @@ use i_float::int::point::IntPoint; let mut segments = vec![segment1, segment2, segment3]; segments.merge_if_needed(); - assert_eq!(segments.len(), 3, "Segments with different x_segments should not be merged"); + assert_eq!( + segments.len(), + 3, + "Segments with different x_segments should not be merged" + ); assert_eq!(segments[0], segment1, "First segment should remain unchanged"); assert_eq!(segments[1], segment2, "Second segment should remain unchanged"); assert_eq!(segments[2], segment3, "Third segment should remain unchanged"); diff --git a/iOverlay/src/segm/mod.rs b/iOverlay/src/segm/mod.rs index 844acd63..857ffd78 100644 --- a/iOverlay/src/segm/mod.rs +++ b/iOverlay/src/segm/mod.rs @@ -1,8 +1,8 @@ -pub mod winding; pub mod boolean; -pub mod string; +pub(crate) mod build; +pub(crate) mod merge; pub mod offset; pub(crate) mod segment; -pub(crate) mod merge; -pub(crate) mod build; -pub(crate) mod sort; \ No newline at end of file +pub(crate) mod sort; +pub mod string; +pub mod winding; diff --git a/iOverlay/src/segm/offset.rs b/iOverlay/src/segm/offset.rs index 6a170336..9b82ad7c 100644 --- a/iOverlay/src/segm/offset.rs +++ b/iOverlay/src/segm/offset.rs @@ -9,18 +9,20 @@ pub struct ShapeCountOffset { impl WindingCount for ShapeCountOffset { #[inline(always)] - fn is_not_empty(&self) -> bool { self.subj != 0 } + fn is_not_empty(&self) -> bool { + self.subj != 0 + } #[inline(always)] fn new(subj: i32, _: i32) -> Self { - Self {subj, bold: true} + Self { subj, bold: true } } #[inline(always)] fn with_shape_type(shape_type: ShapeType) -> (Self, Self) { match shape_type { - ShapeType::Subject => (Self {subj: 1, bold: true}, Self {subj: -1, bold: true}), - ShapeType::Clip => (Self {subj: 0, bold: true}, Self {subj: 0, bold: true}), + ShapeType::Subject => (Self { subj: 1, bold: true }, Self { subj: -1, bold: true }), + ShapeType::Clip => (Self { subj: 0, bold: true }, Self { subj: 0, bold: true }), } } @@ -28,7 +30,7 @@ impl WindingCount for ShapeCountOffset { fn add(self, count: Self) -> Self { let subj = self.subj + count.subj; let bold = self.bold || count.bold; - Self {subj, bold} + Self { subj, bold } } #[inline(always)] @@ -40,6 +42,9 @@ impl WindingCount for ShapeCountOffset { #[inline(always)] fn invert(self) -> Self { let subj = -self.subj; - Self {subj, bold: self.bold} + Self { + subj, + bold: self.bold, + } } -} \ No newline at end of file +} diff --git a/iOverlay/src/segm/sort.rs b/iOverlay/src/segm/sort.rs index 52e0f90e..263265ea 100644 --- a/iOverlay/src/segm/sort.rs +++ b/iOverlay/src/segm/sort.rs @@ -1,5 +1,5 @@ -use i_key_sort::sort::two_keys_cmp::TwoKeysAndCmpSort; use crate::segm::segment::Segment; +use i_key_sort::sort::two_keys_cmp::TwoKeysAndCmpSort; pub(crate) trait ShapeSegmentsSort { fn sort_by_ab(&mut self, parallel: bool); @@ -12,7 +12,7 @@ impl ShapeSegmentsSort for [Segment] { parallel, |s| s.x_segment.a.x, |s| s.x_segment.a.y, - |s0, s1| s0.x_segment.b.cmp(&s1.x_segment.b) + |s0, s1| s0.x_segment.b.cmp(&s1.x_segment.b), ) } -} \ No newline at end of file +} diff --git a/iOverlay/src/segm/string.rs b/iOverlay/src/segm/string.rs index d7abfc8f..21bce440 100644 --- a/iOverlay/src/segm/string.rs +++ b/iOverlay/src/segm/string.rs @@ -1,6 +1,6 @@ -use core::cmp::Ordering; use crate::core::overlay::ShapeType; use crate::segm::winding::WindingCount; +use core::cmp::Ordering; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ShapeCountString { @@ -13,7 +13,9 @@ pub(crate) const STRING_BACK_CLIP: u8 = 0b1; impl WindingCount for ShapeCountString { #[inline(always)] - fn is_not_empty(&self) -> bool { self.subj != 0 || self.clip != 0 } + fn is_not_empty(&self) -> bool { + self.subj != 0 || self.clip != 0 + } #[inline(always)] fn new(subj: i32, clip: i32) -> Self { @@ -31,7 +33,16 @@ impl WindingCount for ShapeCountString { fn with_shape_type(shape_type: ShapeType) -> (Self, Self) { match shape_type { ShapeType::Subject => (Self { subj: 1, clip: 0 }, Self { subj: -1, clip: 0 }), - ShapeType::Clip => (Self { subj: 0, clip: STRING_FORWARD_CLIP }, Self { subj: 0, clip: STRING_BACK_CLIP }) + ShapeType::Clip => ( + Self { + subj: 0, + clip: STRING_FORWARD_CLIP, + }, + Self { + subj: 0, + clip: STRING_BACK_CLIP, + }, + ), } } @@ -55,6 +66,9 @@ impl WindingCount for ShapeCountString { let b1 = self.clip & 0b10; let clip = (b0 << 1) | (b1 >> 1); - Self { subj: -self.subj, clip } + Self { + subj: -self.subj, + clip, + } } -} \ No newline at end of file +} diff --git a/iOverlay/src/segm/winding.rs b/iOverlay/src/segm/winding.rs index 3b629003..81cc7b34 100644 --- a/iOverlay/src/segm/winding.rs +++ b/iOverlay/src/segm/winding.rs @@ -10,4 +10,4 @@ where fn add(self, count: Self) -> Self; fn apply(&mut self, count: Self); fn invert(self) -> Self; -} \ No newline at end of file +} diff --git a/iOverlay/src/split/cross_solver.rs b/iOverlay/src/split/cross_solver.rs index 7f233825..7b0c5447 100644 --- a/iOverlay/src/split/cross_solver.rs +++ b/iOverlay/src/split/cross_solver.rs @@ -1,8 +1,8 @@ +use crate::geom::x_segment::XSegment; use i_float::fix_vec::FixVec; use i_float::int::point::IntPoint; use i_float::triangle::Triangle; use i_float::u128::UInt128; -use crate::geom::x_segment::XSegment; pub(super) type CollinearMask = u8; @@ -21,7 +21,6 @@ const OTHER_A: u8 = 0b0100; const OTHER_B: u8 = 0b1000; impl EndMask for CollinearMask { - #[inline(always)] fn is_target_a(&self) -> bool { self & TARGET_A == TARGET_A @@ -69,7 +68,6 @@ pub(super) enum CrossType { pub(super) struct CrossSolver {} impl CrossSolver { - pub(super) fn cross(target: &XSegment, other: &XSegment, radius: i64) -> Option { let a0b0a1 = Triangle::clock_direction_point(target.a, target.b, other.a); let a0b0b1 = Triangle::clock_direction_point(target.a, target.b, other.b); @@ -136,7 +134,7 @@ impl CrossSolver { let ab0 = (a0 - b1).dot_product(v1).signum(); let ba0 = (b0 - a1).dot_product(v1).signum(); let bb0 = (b0 - b1).dot_product(v1).signum(); - + let aa1 = -aa0; let ab1 = -ba0; let ba1 = -ab0; @@ -309,8 +307,6 @@ trait RoundDivide { } impl RoundDivide for UInt128 { - - fn divide_with_rounding(&self, divisor: u64) -> u64 { if self.high == 0 { let result = self.low / divisor; @@ -353,9 +349,9 @@ impl RoundDivide for UInt128 { #[cfg(test)] mod tests { - use i_float::int::point::IntPoint; - use crate::split::cross_solver::{CrossSolver, CrossType}; use crate::geom::x_segment::XSegment; + use crate::split::cross_solver::{CrossSolver, CrossType}; + use i_float::int::point::IntPoint; impl XSegment { fn new(a: IntPoint, b: IntPoint) -> Self { @@ -579,4 +575,4 @@ mod tests { } } } -} \ No newline at end of file +} diff --git a/iOverlay/src/split/fragment.rs b/iOverlay/src/split/fragment.rs index 995a5102..63e898d7 100644 --- a/iOverlay/src/split/fragment.rs +++ b/iOverlay/src/split/fragment.rs @@ -1,5 +1,5 @@ -use i_float::int::rect::IntRect; use crate::geom::x_segment::XSegment; +use i_float::int::rect::IntRect; #[derive(Debug, Clone)] pub(super) struct Fragment { @@ -9,7 +9,6 @@ pub(super) struct Fragment { } impl Fragment { - #[inline] pub(super) fn with_index_and_segment(index: usize, x_segment: XSegment) -> Self { let (min_y, max_y) = if x_segment.a.y < x_segment.b.y { @@ -31,4 +30,4 @@ impl Fragment { x_segment, } } -} \ No newline at end of file +} diff --git a/iOverlay/src/split/grid_layout.rs b/iOverlay/src/split/grid_layout.rs index 9ae2ce13..7e7fcfa1 100644 --- a/iOverlay/src/split/grid_layout.rs +++ b/iOverlay/src/split/grid_layout.rs @@ -242,7 +242,6 @@ impl FragmentBuffer { } true } - } pub(super) struct GridLayout { @@ -289,11 +288,7 @@ impl GridLayout { let log = dx.ilog2(); let power = if log > max_power { log - max_power } else { 1 }; - Some(Self { - min_x, - max_x, - power, - }) + Some(Self { min_x, max_x, power }) } } @@ -1263,14 +1258,8 @@ mod tests { let mut buffer = FragmentBuffer::new(layout); let segment = XSegment { - a: IntPoint { - x: -83143, - y: 65289, - }, - b: IntPoint { - x: 45253, - y: -76778, - }, + a: IntPoint { x: -83143, y: 65289 }, + b: IntPoint { x: 45253, y: -76778 }, }; let segments = vec![segment]; buffer.init_fragment_buffer(segments.iter().copied()); @@ -1293,14 +1282,8 @@ mod tests { let mut buffer = FragmentBuffer::new(layout); let segment = XSegment { - a: IntPoint { - x: -78454, - y: -40819, - }, - b: IntPoint { - x: 47599, - y: -57780, - }, + a: IntPoint { x: -78454, y: -40819 }, + b: IntPoint { x: 47599, y: -57780 }, }; let segments = vec![segment]; buffer.init_fragment_buffer(segments.iter().copied()); diff --git a/iOverlay/src/split/line_mark.rs b/iOverlay/src/split/line_mark.rs index 6f6c360b..21e79318 100644 --- a/iOverlay/src/split/line_mark.rs +++ b/iOverlay/src/split/line_mark.rs @@ -9,20 +9,12 @@ pub(super) struct LineMark { } pub(super) trait SortMarkByIndexAndPoint { - fn sort_by_index_and_point( - &mut self, - parallel: bool, - reusable_buffer: &mut Vec, - ); + fn sort_by_index_and_point(&mut self, parallel: bool, reusable_buffer: &mut Vec); } impl SortMarkByIndexAndPoint for [LineMark] { #[inline] - fn sort_by_index_and_point( - &mut self, - parallel: bool, - reusable_buffer: &mut Vec, - ) { + fn sort_by_index_and_point(&mut self, parallel: bool, reusable_buffer: &mut Vec) { self.sort_by_one_key_then_by_and_buffer( parallel, reusable_buffer, diff --git a/iOverlay/src/split/mod.rs b/iOverlay/src/split/mod.rs index 394056c4..7371a0c6 100644 --- a/iOverlay/src/split/mod.rs +++ b/iOverlay/src/split/mod.rs @@ -2,9 +2,9 @@ pub(crate) mod solver; mod cross_solver; mod fragment; +mod grid_layout; +mod line_mark; +mod snap_radius; +mod solver_fragment; mod solver_list; mod solver_tree; -mod snap_radius; -mod line_mark; -mod grid_layout; -mod solver_fragment; \ No newline at end of file diff --git a/iOverlay/src/split/snap_radius.rs b/iOverlay/src/split/snap_radius.rs index d8a5222b..2a13b7ad 100644 --- a/iOverlay/src/split/snap_radius.rs +++ b/iOverlay/src/split/snap_radius.rs @@ -22,4 +22,4 @@ impl Solver { step: self.precision.progression, } } -} \ No newline at end of file +} diff --git a/iOverlay/src/split/solver.rs b/iOverlay/src/split/solver.rs index 63eaf04d..60ccc6fc 100644 --- a/iOverlay/src/split/solver.rs +++ b/iOverlay/src/split/solver.rs @@ -225,11 +225,7 @@ impl SplitSolver { #[inline] fn y_range(j0: usize, j1: usize, s: XSegment, marks: &[LineMark]) -> (i32, i32) { - let y0 = if j0 == 0 { - s.a.y - } else { - marks[j0 - 1].point.y - }; + let y0 = if j0 == 0 { s.a.y } else { marks[j0 - 1].point.y }; let y1 = if j1 == marks.len() { s.b.y } else { diff --git a/iOverlay/src/split/solver_fragment.rs b/iOverlay/src/split/solver_fragment.rs index dfbbcde5..24cef4e5 100644 --- a/iOverlay/src/split/solver_fragment.rs +++ b/iOverlay/src/split/solver_fragment.rs @@ -1,4 +1,3 @@ -use alloc::vec::Vec; use crate::core::solver::Solver; use crate::segm::segment::Segment; use crate::segm::winding::WindingCount; @@ -8,21 +7,21 @@ use crate::split::grid_layout::{BorderVSegment, FragmentBuffer, GridLayout}; use crate::split::line_mark::LineMark; use crate::split::snap_radius::SnapRadius; use crate::split::solver::SplitSolver; +use alloc::vec::Vec; impl SplitSolver { pub(super) fn fragment_split( &mut self, snap_radius: SnapRadius, segments: &mut Vec>, - solver: &Solver + solver: &Solver, ) -> bool { - let layout = if let Some(layout) = - GridLayout::new(segments.iter().map(|it| it.x_segment), segments.len()) - { - layout - } else { - return self.tree_split(snap_radius, segments, solver); - }; + let layout = + if let Some(layout) = GridLayout::new(segments.iter().map(|it| it.x_segment), segments.len()) { + layout + } else { + return self.tree_split(snap_radius, segments, solver); + }; let mut reusable_buffer = Vec::new(); let mut buffer = FragmentBuffer::new(layout); @@ -181,7 +180,7 @@ impl SplitSolver { &mut self, border_x: i32, fragments: &[Fragment], - vertical_segments: &mut [BorderVSegment] + vertical_segments: &mut [BorderVSegment], ) { let mut points = Vec::new(); for fragment in fragments.iter() { @@ -213,12 +212,7 @@ impl SplitSolver { } } - fn cross_fragments( - fi: &Fragment, - fj: &Fragment, - radius: i64, - marks: &mut Vec - ) -> bool { + fn cross_fragments(fi: &Fragment, fj: &Fragment, radius: i64, marks: &mut Vec) -> bool { let cross = if let Some(cross) = CrossSolver::cross(&fi.x_segment, &fj.x_segment, radius) { cross } else { diff --git a/iOverlay/src/split/solver_list.rs b/iOverlay/src/split/solver_list.rs index c9b9cec7..c048b170 100644 --- a/iOverlay/src/split/solver_list.rs +++ b/iOverlay/src/split/solver_list.rs @@ -1,16 +1,16 @@ -use alloc::vec::Vec; use crate::core::solver::Solver; use crate::segm::segment::Segment; use crate::segm::winding::WindingCount; use crate::split::snap_radius::SnapRadius; use crate::split::solver::SplitSolver; +use alloc::vec::Vec; impl SplitSolver { pub(super) fn list_split( &mut self, snap_radius: SnapRadius, segments: &mut Vec>, - solver: &Solver + solver: &Solver, ) -> bool { let mut need_to_fix = true; diff --git a/iOverlay/src/split/solver_tree.rs b/iOverlay/src/split/solver_tree.rs index 587f7f7e..83f9509e 100644 --- a/iOverlay/src/split/solver_tree.rs +++ b/iOverlay/src/split/solver_tree.rs @@ -1,14 +1,14 @@ -use alloc::vec::Vec; -use i_tree::ExpiredVal; +use crate::core::solver::Solver; use crate::geom::line_range::LineRange; use crate::geom::x_segment::XSegment; use crate::segm::segment::Segment; use crate::segm::winding::WindingCount; use crate::split::snap_radius::SnapRadius; use crate::split::solver::SplitSolver; +use alloc::vec::Vec; +use i_tree::ExpiredVal; use i_tree::seg::exp::{SegExpCollection, SegRange}; use i_tree::seg::tree::SegExpTree; -use crate::core::solver::Solver; #[derive(Debug, Clone, Copy)] struct IdSegment { @@ -28,7 +28,7 @@ impl SplitSolver { &mut self, snap_radius: SnapRadius, segments: &mut Vec>, - solver: &Solver + solver: &Solver, ) -> bool { let range: SegRange = segments.ver_range().into(); let mut tree: SegExpTree = if let Some(tree) = SegExpTree::new(range) { @@ -60,14 +60,8 @@ impl SplitSolver { (sj.id, i, &sj.x_segment, &si.x_segment) }; - let is_round = SplitSolver::cross( - this_index, - scan_index, - this, - scan, - &mut self.marks, - radius, - ); + let is_round = + SplitSolver::cross(this_index, scan_index, this, scan, &mut self.marks, radius); need_to_fix = is_round || need_to_fix; } diff --git a/iOverlay/src/string/clip.rs b/iOverlay/src/string/clip.rs index 3d9d9356..8066212a 100644 --- a/iOverlay/src/string/clip.rs +++ b/iOverlay/src/string/clip.rs @@ -1,15 +1,15 @@ -use alloc::vec::Vec; -use crate::segm::string::{STRING_BACK_CLIP, STRING_FORWARD_CLIP}; -use i_float::int::point::IntPoint; -use i_shape::int::path::IntPath; -use i_shape::int::shape::{IntShape, IntShapes}; use crate::core::fill_rule::FillRule; use crate::core::link::OverlayLink; use crate::geom::id_point::IdPoint; use crate::segm::segment::SegmentFill; +use crate::segm::string::{STRING_BACK_CLIP, STRING_FORWARD_CLIP}; use crate::string::graph::StringGraph; use crate::string::line::IntLine; use crate::string::overlay::StringOverlay; +use alloc::vec::Vec; +use i_float::int::point::IntPoint; +use i_shape::int::path::IntPath; +use i_shape::int::shape::{IntShape, IntShapes}; #[derive(Debug, Clone, Copy)] pub struct ClipRule { @@ -20,7 +20,6 @@ pub struct ClipRule { pub boundary_included: bool, } - impl StringGraph<'_> { #[inline] pub(super) fn into_clip_string_lines(self) -> Vec { @@ -60,7 +59,12 @@ impl StringGraph<'_> { } #[inline] - fn find_next_point(nodes: &[Vec], links: &mut [OverlayLink], a: IdPoint, is_out_node: bool) -> Option { + fn find_next_point( + nodes: &[Vec], + links: &mut [OverlayLink], + a: IdPoint, + is_out_node: bool, + ) -> Option { let node = unsafe { // SAFETY: a.id comes from an existing link endpoint, so it indexes nodes. nodes.get_unchecked(a.id) @@ -245,11 +249,11 @@ impl IntClip for [IntPoint] { #[cfg(test)] mod tests { + use crate::core::fill_rule::FillRule; + use crate::string::clip::{ClipRule, IntClip}; use alloc::vec; use i_float::int::point::IntPoint; use i_shape::int::path::IntPath; - use crate::core::fill_rule::FillRule; - use crate::string::clip::{ClipRule, IntClip}; #[test] fn test_empty_path() { @@ -257,13 +261,19 @@ mod tests { let result_0 = path.clip_line( [IntPoint::new(0, 0), IntPoint::new(0, 0)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); let result_1 = path.clip_line( [IntPoint::new(0, 0), IntPoint::new(10, 0)], FillRule::NonZero, - ClipRule { invert: true, boundary_included: false }, + ClipRule { + invert: true, + boundary_included: false, + }, ); assert!(result_0.is_empty()); @@ -282,13 +292,19 @@ mod tests { let result_0 = path.clip_line( [IntPoint::new(0, -15), IntPoint::new(0, 15)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); let result_1 = path.clip_line( [IntPoint::new(0, -15), IntPoint::new(0, 15)], FillRule::NonZero, - ClipRule { invert: true, boundary_included: false }, + ClipRule { + invert: true, + boundary_included: false, + }, ); assert_eq!(result_0.len(), 1); @@ -307,13 +323,19 @@ mod tests { let result_0 = path.clip_line( [IntPoint::new(-10, -15), IntPoint::new(-10, 15)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); let result_1 = path.clip_line( [IntPoint::new(-10, -15), IntPoint::new(-10, 15)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: true }, + ClipRule { + invert: false, + boundary_included: true, + }, ); assert_eq!(result_0.len(), 0); @@ -339,15 +361,25 @@ mod tests { IntPoint::new(5, -5), IntPoint::new(0, -10), IntPoint::new(-5, -5), - IntPoint::new(-15, -15) + IntPoint::new(-15, -15), ]; - let result_0 = rect.clip_path(&path, FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + let result_0 = rect.clip_path( + &path, + FillRule::NonZero, + ClipRule { + invert: false, + boundary_included: false, + }, ); - let result_1 = rect.clip_path(&path, FillRule::NonZero, - ClipRule { invert: false, boundary_included: true }, + let result_1 = rect.clip_path( + &path, + FillRule::NonZero, + ClipRule { + invert: false, + boundary_included: true, + }, ); assert_eq!(result_0.len(), 3); @@ -356,22 +388,24 @@ mod tests { #[test] fn test_tiny_shape() { - let path = vec![ - IntPoint::new(-1, 0), - IntPoint::new(1, 0), - IntPoint::new(0, 1), - ]; + let path = vec![IntPoint::new(-1, 0), IntPoint::new(1, 0), IntPoint::new(0, 1)]; let result_0 = path.clip_line( [IntPoint::new(0, -1), IntPoint::new(0, 2)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); let result_1 = path.clip_line( [IntPoint::new(0, -1), IntPoint::new(0, 2)], FillRule::NonZero, - ClipRule { invert: true, boundary_included: false }, + ClipRule { + invert: true, + boundary_included: false, + }, ); assert_eq!(result_0.len(), 1); @@ -390,13 +424,19 @@ mod tests { let result_0 = path.clip_line( [IntPoint::new(-1, -1), IntPoint::new(1, -1)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); let result_1 = path.clip_line( [IntPoint::new(-1, -1), IntPoint::new(1, -1)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: true }, + ClipRule { + invert: false, + boundary_included: true, + }, ); assert_eq!(result_0.len(), 0); @@ -419,12 +459,22 @@ mod tests { IntPoint::new(4, 1), ]; - let result_0 = contour.clip_path(&path, FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + let result_0 = contour.clip_path( + &path, + FillRule::NonZero, + ClipRule { + invert: false, + boundary_included: false, + }, ); - let result_1 = contour.clip_path(&path, FillRule::NonZero, - ClipRule { invert: false, boundary_included: true }, + let result_1 = contour.clip_path( + &path, + FillRule::NonZero, + ClipRule { + invert: false, + boundary_included: true, + }, ); assert_eq!(result_0.len(), 0); @@ -444,13 +494,19 @@ mod tests { let result_0 = path.clip_line( [IntPoint::new(-3, 2), IntPoint::new(3, 2)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); let result_1 = path.clip_line( [IntPoint::new(-3, 2), IntPoint::new(3, 2)], FillRule::NonZero, - ClipRule { invert: false, boundary_included: false }, + ClipRule { + invert: false, + boundary_included: false, + }, ); assert_eq!(result_0.len(), 0); diff --git a/iOverlay/src/string/extract.rs b/iOverlay/src/string/extract.rs index 594a698b..fdf22da1 100644 --- a/iOverlay/src/string/extract.rs +++ b/iOverlay/src/string/extract.rs @@ -37,11 +37,7 @@ impl StringGraph<'_> { /// - Each path `Vec` is a sequence of points, forming a closed path. /// /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. - pub fn extract_shapes_custom( - &self, - string_rule: StringRule, - options: IntOverlayOptions, - ) -> IntShapes { + pub fn extract_shapes_custom(&self, string_rule: StringRule, options: IntOverlayOptions) -> IntShapes { let clockwise = options.output_direction == ContourDirection::Clockwise; let mut fills = self.filter(string_rule); let mut shapes = Vec::new(); @@ -59,9 +55,11 @@ impl StringGraph<'_> { } let direction = fill & SUBJ_TOP == SUBJ_TOP; - let paths = self - .get_paths(link_index, direction, &mut fills) - .split_loops(options.min_output_area, &mut contour_buffer, &mut bin_store); + let paths = self.get_paths(link_index, direction, &mut fills).split_loops( + options.min_output_area, + &mut contour_buffer, + &mut bin_store, + ); for mut path in paths.into_iter() { let order = path.is_clockwise_ordered(); @@ -145,7 +143,10 @@ impl StringGraph<'_> { } let (link, fill) = unsafe { // SAFETY: link_index comes from the adjacency list; fills shares the same length as links. - (self.links.get_unchecked(link_index), *fills.get_unchecked(link_index)) + ( + self.links.get_unchecked(link_index), + *fills.get_unchecked(link_index), + ) }; if link.is_move_possible(fill, node_id, clockwise) { if is_first { @@ -162,7 +163,10 @@ impl StringGraph<'_> { if first_index == usize::MAX { let (link, fill) = unsafe { // SAFETY: target_index is the caller's current link id, so it is within bounds for both arrays. - (self.links.get_unchecked(target_index), *fills.get_unchecked(target_index)) + ( + self.links.get_unchecked(target_index), + *fills.get_unchecked(target_index), + ) }; if link.is_move_possible(fill, node_id, clockwise) { return target_index; @@ -175,7 +179,6 @@ impl StringGraph<'_> { return first_index; } - let target = unsafe { // SAFETY: target_index is either target_index or first_index; both were validated above. self.links.get_unchecked(target_index) @@ -208,7 +211,10 @@ impl StringGraph<'_> { for &link_index in indices.iter().skip(pos + 1) { let (link, fill) = unsafe { // SAFETY: link_index traverses the same adjacency slice; indices and arrays are aligned. - (self.links.get_unchecked(link_index), *fills.get_unchecked(link_index)) + ( + self.links.get_unchecked(link_index), + *fills.get_unchecked(link_index), + ) }; if link.is_move_possible(fill, node_id, clockwise) { let p = link.other(node_id).point; diff --git a/iOverlay/src/string/filter.rs b/iOverlay/src/string/filter.rs index 48db20fd..c02815ac 100644 --- a/iOverlay/src/string/filter.rs +++ b/iOverlay/src/string/filter.rs @@ -1,8 +1,8 @@ -use alloc::vec::Vec; use crate::core::link::OverlayLink; use crate::segm::segment::{SUBJ_BOTH, SUBJ_BOTTOM, SUBJ_TOP}; use crate::string::graph::StringGraph; use crate::string::rule::StringRule; +use alloc::vec::Vec; impl OverlayLink { #[inline] @@ -52,9 +52,6 @@ impl StringGraph<'_> { #[inline] fn filter_slice(&self) -> Vec { - self.links - .iter() - .map(|link| link.fill & SUBJ_BOTH) - .collect() + self.links.iter().map(|link| link.fill & SUBJ_BOTH).collect() } } diff --git a/iOverlay/src/string/graph.rs b/iOverlay/src/string/graph.rs index 307a43da..901c2393 100644 --- a/iOverlay/src/string/graph.rs +++ b/iOverlay/src/string/graph.rs @@ -1,6 +1,6 @@ -use alloc::vec::Vec; use crate::build::builder::GraphNode; use crate::core::link::OverlayLink; +use alloc::vec::Vec; pub struct StringGraph<'a> { pub(crate) nodes: &'a [Vec], @@ -12,4 +12,4 @@ impl GraphNode for Vec { fn with_indices(indices: &[usize]) -> Self { indices.to_vec() } -} \ No newline at end of file +} diff --git a/iOverlay/src/string/mod.rs b/iOverlay/src/string/mod.rs index dcbc4117..bf618102 100644 --- a/iOverlay/src/string/mod.rs +++ b/iOverlay/src/string/mod.rs @@ -1,9 +1,9 @@ -pub mod slice; +pub mod clip; +pub mod extract; +mod filter; +pub mod graph; pub mod line; -pub mod rule; pub mod overlay; -pub mod graph; +pub mod rule; +pub mod slice; pub mod split; -pub mod clip; -pub mod extract; -mod filter; \ No newline at end of file diff --git a/iOverlay/src/string/overlay.rs b/iOverlay/src/string/overlay.rs index b40f9d6f..631da415 100644 --- a/iOverlay/src/string/overlay.rs +++ b/iOverlay/src/string/overlay.rs @@ -1,11 +1,3 @@ -use alloc::vec::Vec; -use crate::segm::string::STRING_FORWARD_CLIP; -use crate::segm::string::STRING_BACK_CLIP; -use crate::segm::string::ShapeCountString; -use i_float::int::point::IntPoint; -use i_shape::int::count::PointsCount; -use i_shape::int::path::IntPath; -use i_shape::int::shape::{IntContour, IntShape}; use crate::build::builder::GraphBuilder; use crate::core::fill_rule::FillRule; use crate::core::overlay::{IntOverlayOptions, ShapeType}; @@ -13,16 +5,25 @@ use crate::core::solver::Solver; use crate::geom::x_segment::XSegment; use crate::segm::build::BuildSegments; use crate::segm::segment::Segment; +use crate::segm::string::STRING_BACK_CLIP; +use crate::segm::string::STRING_FORWARD_CLIP; +use crate::segm::string::ShapeCountString; use crate::split::solver::SplitSolver; use crate::string::clip::ClipRule; use crate::string::graph::StringGraph; use crate::string::line::IntLine; +use alloc::vec::Vec; +use core::cmp::Ordering; +use i_float::int::point::IntPoint; +use i_shape::int::count::PointsCount; +use i_shape::int::path::IntPath; +use i_shape::int::shape::{IntContour, IntShape}; pub struct StringOverlay { pub options: IntOverlayOptions, pub(super) segments: Vec>, pub(crate) split_solver: SplitSolver, - pub(crate) graph_builder: GraphBuilder> + pub(crate) graph_builder: GraphBuilder>, } impl StringOverlay { @@ -35,7 +36,7 @@ impl StringOverlay { options: Default::default(), segments: Vec::with_capacity(capacity), split_solver: SplitSolver::new(), - graph_builder: GraphBuilder::>::new() + graph_builder: GraphBuilder::>::new(), } } @@ -48,7 +49,7 @@ impl StringOverlay { options, segments: Vec::with_capacity(capacity), split_solver: SplitSolver::new(), - graph_builder: GraphBuilder::>::new() + graph_builder: GraphBuilder::>::new(), } } @@ -93,7 +94,7 @@ impl StringOverlay { /// when paths are not directly stored in a collection. /// - `iter`: An iterator over references to `IntPoint` that defines the path. #[inline] - pub fn add_shape_contour_iter>(&mut self, iter: I) { + pub fn add_shape_contour_iter>(&mut self, iter: I) { self.segments.append_path_iter(iter, ShapeType::Subject, false); } @@ -128,9 +129,21 @@ impl StringOverlay { let a = line[0]; let b = line[1]; let segment = match a.cmp(&b) { - core::cmp::Ordering::Less => Segment { x_segment: XSegment { a, b }, count: ShapeCountString { subj: 0, clip: STRING_BACK_CLIP } }, - core::cmp::Ordering::Greater => Segment { x_segment: XSegment { a: b, b: a }, count: ShapeCountString { subj: 0, clip: STRING_FORWARD_CLIP } }, - core::cmp::Ordering::Equal => return, + Ordering::Less => Segment { + x_segment: XSegment { a, b }, + count: ShapeCountString { + subj: 0, + clip: STRING_BACK_CLIP, + }, + }, + Ordering::Greater => Segment { + x_segment: XSegment { a: b, b: a }, + count: ShapeCountString { + subj: 0, + clip: STRING_FORWARD_CLIP, + }, + }, + Ordering::Equal => return, }; self.segments.push(segment); @@ -152,7 +165,11 @@ impl StringOverlay { if path.len() < 2 { return; } - let mut a = if let Some(&p) = path.first() { p } else { return; }; + let mut a = if let Some(&p) = path.first() { + p + } else { + return; + }; for &b in path.iter().skip(1) { self.add_string_line([a, b]); a = b; @@ -166,7 +183,11 @@ impl StringOverlay { if contour.len() < 2 { return; } - let mut a = if let Some(&p) = contour.last() { p } else { return; }; + let mut a = if let Some(&p) = contour.last() { + p + } else { + return; + }; for &b in contour.iter() { self.add_string_line([a, b]); a = b; @@ -209,7 +230,12 @@ impl StringOverlay { /// # Returns /// A vector of `IntPath` instances representing the clipped sections of the input lines. #[inline] - pub fn clip_string_lines_with_solver(mut self, fill_rule: FillRule, clip_rule: ClipRule, solver: Solver) -> Vec { + pub fn clip_string_lines_with_solver( + mut self, + fill_rule: FillRule, + clip_rule: ClipRule, + solver: Solver, + ) -> Vec { self.split_solver.split_segments(&mut self.segments, &solver); if self.segments.is_empty() { return Vec::new(); @@ -232,11 +258,18 @@ impl StringOverlay { /// - `fill_rule`: The rule that defines how to build shapes (e.g., non-zero, even-odd). /// - `solver`: A solver type to be used for advanced control over the graph building process. #[inline] - pub fn build_graph_view_with_solver(&mut self, fill_rule: FillRule, solver: Solver) -> Option> { + pub fn build_graph_view_with_solver( + &mut self, + fill_rule: FillRule, + solver: Solver, + ) -> Option> { self.split_solver.split_segments(&mut self.segments, &solver); if self.segments.is_empty() { return None; } - Some(self.graph_builder.build_string_all(fill_rule, &solver, &self.segments)) + Some( + self.graph_builder + .build_string_all(fill_rule, &solver, &self.segments), + ) } -} \ No newline at end of file +} diff --git a/iOverlay/src/string/rule.rs b/iOverlay/src/string/rule.rs index 75eb3c5c..7f1a2558 100644 --- a/iOverlay/src/string/rule.rs +++ b/iOverlay/src/string/rule.rs @@ -1,4 +1,4 @@ #[derive(Debug, Clone, Copy, PartialEq)] pub enum StringRule { - Slice -} \ No newline at end of file + Slice, +} diff --git a/iOverlay/src/string/slice.rs b/iOverlay/src/string/slice.rs index 140660d4..fe35fb0b 100644 --- a/iOverlay/src/string/slice.rs +++ b/iOverlay/src/string/slice.rs @@ -1,10 +1,10 @@ -use i_float::int::point::IntPoint; -use i_shape::int::path::IntPath; -use i_shape::int::shape::{IntShape, IntShapes}; use crate::core::fill_rule::FillRule; use crate::string::line::IntLine; use crate::string::overlay::StringOverlay; use crate::string::rule::StringRule; +use i_float::int::point::IntPoint; +use i_shape::int::path::IntPath; +use i_shape::int::shape::{IntShape, IntShapes}; pub trait IntSlice { fn slice_by_line(&self, line: IntLine, fill_rule: FillRule) -> IntShapes; @@ -141,10 +141,10 @@ impl IntSlice for [IntPoint] { #[cfg(test)] mod tests { - use alloc::vec; - use i_float::int::point::IntPoint; use crate::core::fill_rule::FillRule; use crate::string::slice::IntSlice; + use alloc::vec; + use i_float::int::point::IntPoint; #[test] fn test_empty_input() { @@ -166,10 +166,7 @@ mod tests { IntPoint::new(10, 10), ]]; - let result = paths.slice_by_line( - [IntPoint::new(-20, 0), IntPoint::new(20, 0)], - FillRule::NonZero, - ); + let result = paths.slice_by_line([IntPoint::new(-20, 0), IntPoint::new(20, 0)], FillRule::NonZero); assert_eq!(result.len(), 2); assert_eq!(result[0].len(), 1); @@ -195,10 +192,7 @@ mod tests { ], ]; - let result = paths.slice_by_line( - [IntPoint::new(-20, 0), IntPoint::new(20, 0)], - FillRule::NonZero, - ); + let result = paths.slice_by_line([IntPoint::new(-20, 0), IntPoint::new(20, 0)], FillRule::NonZero); assert_eq!(result.len(), 2); assert_eq!(result[0].len(), 1); @@ -230,10 +224,7 @@ mod tests { ], ]; - let result = paths.slice_by_line( - [IntPoint::new(15, 10), IntPoint::new(20, 10)], - FillRule::NonZero, - ); + let result = paths.slice_by_line([IntPoint::new(15, 10), IntPoint::new(20, 10)], FillRule::NonZero); assert_eq!(result.len(), 1); assert_eq!(result[0].len(), 3); @@ -341,7 +332,7 @@ mod tests { assert_eq!(shapes.len(), 2); assert_eq!(shapes[0][0].len(), 3); - assert_eq!(shapes[1][0].len(), 3); + assert_eq!(shapes[1][0].len(), 3); } #[test] @@ -414,4 +405,4 @@ mod tests { assert_eq!(shapes.len(), 1); } -} \ No newline at end of file +} diff --git a/iOverlay/src/string/split.rs b/iOverlay/src/string/split.rs index 7cefffbd..9e63705b 100644 --- a/iOverlay/src/string/split.rs +++ b/iOverlay/src/string/split.rs @@ -117,10 +117,7 @@ impl BinStore { let mut offset = 0; for bin in self.bins.iter_mut() { let next_offset = offset + bin.data; - *bin = Bin { - offset, - data: offset, - }; + *bin = Bin { offset, data: offset }; offset = next_offset; } } @@ -281,12 +278,7 @@ mod tests { assert_eq!(result.len(), 2); assert_eq!( result[0], - [ - IntPoint::new(3, 1), - IntPoint::new(3, -1), - IntPoint::new(2, 0), - ] - .to_vec() + [IntPoint::new(3, 1), IntPoint::new(3, -1), IntPoint::new(2, 0),].to_vec() ); assert_eq!( result[1], @@ -358,12 +350,7 @@ mod tests { assert_eq!(result.len(), 1); assert_eq!( result[0], - [ - IntPoint::new(1, 1), - IntPoint::new(2, 0), - IntPoint::new(0, 0), - ] - .to_vec() + [IntPoint::new(1, 1), IntPoint::new(2, 0), IntPoint::new(0, 0),].to_vec() ); } @@ -390,39 +377,19 @@ mod tests { assert_eq!(result.len(), 4); assert_eq!( result[0], - [ - IntPoint::new(-1, 2), - IntPoint::new(1, 2), - IntPoint::new(0, 0), - ] - .to_vec() + [IntPoint::new(-1, 2), IntPoint::new(1, 2), IntPoint::new(0, 0),].to_vec() ); assert_eq!( result[1], - [ - IntPoint::new(2, 1), - IntPoint::new(2, -1), - IntPoint::new(0, 0), - ] - .to_vec() + [IntPoint::new(2, 1), IntPoint::new(2, -1), IntPoint::new(0, 0),].to_vec() ); assert_eq!( result[2], - [ - IntPoint::new(1, -2), - IntPoint::new(-1, -2), - IntPoint::new(0, 0), - ] - .to_vec() + [IntPoint::new(1, -2), IntPoint::new(-1, -2), IntPoint::new(0, 0),].to_vec() ); assert_eq!( result[3], - [ - IntPoint::new(-2, -1), - IntPoint::new(-2, 1), - IntPoint::new(0, 0), - ] - .to_vec() + [IntPoint::new(-2, -1), IntPoint::new(-2, 1), IntPoint::new(0, 0),].to_vec() ); } } diff --git a/iOverlay/src/util/log.rs b/iOverlay/src/util/log.rs index 37ba835c..94e9bb36 100644 --- a/iOverlay/src/util/log.rs +++ b/iOverlay/src/util/log.rs @@ -1,10 +1,8 @@ - pub(crate) trait Int { fn log2_sqrt(&self) -> usize; } impl Int for usize { - #[inline] fn log2_sqrt(&self) -> usize { let z = self.leading_zeros(); @@ -16,21 +14,13 @@ impl Int for usize { #[cfg(test)] mod tests { + use crate::util::log::Int; use alloc::vec; use alloc::vec::Vec; - use crate::util::log::Int; #[test] fn test_0() { - let tests: Vec<[usize; 2]> = vec![ - [0, 1], - [1, 2], - [3, 2], - [15, 4], - [16, 8], - [255, 16], - [256, 32], - ]; + let tests: Vec<[usize; 2]> = vec![[0, 1], [1, 2], [3, 2], [15, 4], [16, 8], [255, 16], [256, 32]]; for test in tests { let a = test[0].log2_sqrt(); @@ -38,4 +28,4 @@ mod tests { assert_eq!(a, b); } } -} \ No newline at end of file +} diff --git a/iOverlay/src/util/mod.rs b/iOverlay/src/util/mod.rs index a7a35ee6..22484447 100644 --- a/iOverlay/src/util/mod.rs +++ b/iOverlay/src/util/mod.rs @@ -1 +1 @@ -pub(crate) mod log; \ No newline at end of file +pub(crate) mod log; diff --git a/iOverlay/src/vector/edge.rs b/iOverlay/src/vector/edge.rs index 82063303..a4eae6a1 100644 --- a/iOverlay/src/vector/edge.rs +++ b/iOverlay/src/vector/edge.rs @@ -35,11 +35,7 @@ pub struct VectorEdge { impl VectorEdge { pub(crate) fn new(fill: SideFill, a: IntPoint, b: IntPoint) -> Self { - let fill = if a < b { - fill - } else { - fill.reverse() - }; + let fill = if a < b { fill } else { fill.reverse() }; Self { a, b, fill } } @@ -53,4 +49,4 @@ impl ToPath for VectorPath { fn to_path(&self) -> IntPath { self.iter().map(|e| e.a).collect() } -} \ No newline at end of file +} diff --git a/iOverlay/src/vector/extract.rs b/iOverlay/src/vector/extract.rs index 170c1163..49454b7a 100644 --- a/iOverlay/src/vector/extract.rs +++ b/iOverlay/src/vector/extract.rs @@ -31,7 +31,8 @@ impl OverlayGraph<'_> { buffer: &mut BooleanExtractionBuffer, ) -> Vec { let clockwise = self.options.output_direction == ContourDirection::Clockwise; - self.links.filter_by_overlay_into(overlay_rule, &mut buffer.visited); + self.links + .filter_by_overlay_into(overlay_rule, &mut buffer.visited); let mut holes = Vec::new(); let mut shapes = Vec::new(); @@ -57,13 +58,13 @@ impl OverlayGraph<'_> { }; let is_hole = overlay_rule.is_fill_top(link.fill); - let visited_state = - [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; + let visited_state = [VisitState::HullVisited, VisitState::HoleVisited][is_hole as usize]; let direction = is_hole == clockwise; let start_data = StartVectorPathData::new(direction, link, left_top_link); - let mut contour = self.find_vector_contour(start_data, direction, visited_state, &mut buffer.visited); + let mut contour = + self.find_vector_contour(start_data, direction, visited_state, &mut buffer.visited); let (is_valid, is_modified) = contour.validate( self.options.min_output_area, self.options.preserve_output_collinear, @@ -130,8 +131,7 @@ impl OverlayGraph<'_> { // Find a closed tour while node_id != last_node_id { - link_id = - GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, visited); + link_id = GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, visited); let link = unsafe { // SAFETY: `link_id` is always a valid link index obtained from the @@ -182,21 +182,12 @@ impl StartVectorPathData { } trait JoinHoles { - fn join_sorted_holes( - &mut self, - holes: Vec, - anchors: Vec, - clockwise: bool); + fn join_sorted_holes(&mut self, holes: Vec, anchors: Vec, clockwise: bool); fn scan_join(&mut self, holes: Vec, hole_segments: Vec, clockwise: bool); } impl JoinHoles for Vec { - fn join_sorted_holes( - &mut self, - holes: Vec, - anchors: Vec, - clockwise: bool, - ) { + fn join_sorted_holes(&mut self, holes: Vec, anchors: Vec, clockwise: bool) { if self.is_empty() || holes.is_empty() { return; } @@ -220,23 +211,11 @@ impl JoinHoles for Vec { let capacity = self.iter().fold(0, |s, it| s + it[0].len()) / 2; let mut segments = Vec::with_capacity(capacity); for (i, shape) in self.iter().enumerate() { - shape[0].append_id_segments( - &mut segments, - ContourIndex::new_shape(i), - x_min, - x_max, - clockwise, - ); + shape[0].append_id_segments(&mut segments, ContourIndex::new_shape(i), x_min, x_max, clockwise); } for (i, hole) in holes.iter().enumerate() { - hole.append_id_segments( - &mut segments, - ContourIndex::new_hole(i), - x_min, - x_max, - clockwise, - ); + hole.append_id_segments(&mut segments, ContourIndex::new_hole(i), x_min, x_max, clockwise); } segments.sort_by_a_then_by_angle(); diff --git a/iOverlay/src/vector/simplify.rs b/iOverlay/src/vector/simplify.rs index 4576b14c..387cdfed 100644 --- a/iOverlay/src/vector/simplify.rs +++ b/iOverlay/src/vector/simplify.rs @@ -1,5 +1,5 @@ -use alloc::vec; use crate::vector::edge::{VectorEdge, VectorPath, VectorShape}; +use alloc::vec; use alloc::vec::Vec; use i_float::int::point::IntPoint; @@ -21,7 +21,6 @@ pub(super) trait VectorSimpleShape { fn simplified(&self) -> Option; } - impl VectorSimplify for VectorPath { #[inline] fn simplify_contour(&mut self) -> bool { @@ -121,13 +120,24 @@ impl VectorSimpleContour for [VectorEdge] { } let mut n = self.len(); - let mut nodes: Vec = vec![Node { next: 0, index: 0, prev: 0 }; n]; + let mut nodes: Vec = vec![ + Node { + next: 0, + index: 0, + prev: 0 + }; + n + ]; let mut validated: Vec = vec![false; n]; let mut i0 = n - 2; let mut i1 = n - 1; for i2 in 0..n { - nodes[i1] = Node { next: i2, index: i1, prev: i0 }; + nodes[i1] = Node { + next: i2, + index: i1, + prev: i0, + }; i0 = i1; i1 = i2; } @@ -236,10 +246,10 @@ fn direction(edge: &VectorEdge) -> IntPoint { #[cfg(test)] mod tests { + use crate::vector::edge::VectorEdge; use crate::vector::simplify::{IntPoint, VectorSimplify}; use alloc::vec; use i_float::int_pnt; - use crate::vector::edge::VectorEdge; #[test] fn test_0() { diff --git a/iOverlay/tests/data.rs b/iOverlay/tests/data.rs index a7604150..9c0e760d 100644 --- a/iOverlay/tests/data.rs +++ b/iOverlay/tests/data.rs @@ -2,11 +2,11 @@ pub mod overlay { // extern crate std; - use std::path::PathBuf; + use i_overlay::core::fill_rule::FillRule; use i_shape::int::path::IntPaths; use i_shape::int::shape::{IntContour, IntShapes}; use serde::{Deserialize, Deserializer}; - use i_overlay::core::fill_rule::FillRule; + use std::path::PathBuf; fn deserialize_fill_rule<'de, D>(deserializer: D) -> Result, D::Error> where @@ -49,9 +49,7 @@ pub mod overlay { path_buf.push(file_name); let data = match std::fs::read_to_string(path_buf.as_path()) { - Ok(data) => { - data - } + Ok(data) => data, Err(e) => { panic!("{:?}", e); } @@ -89,9 +87,7 @@ pub mod overlay { path_buf.push(file_name); let data = match std::fs::read_to_string(path_buf.as_path()) { - Ok(data) => { - data - } + Ok(data) => data, Err(e) => { panic!("{:?}", e); } diff --git a/iOverlay/tests/direction_tests.rs b/iOverlay/tests/direction_tests.rs index 67fbd783..284a0626 100644 --- a/iOverlay/tests/direction_tests.rs +++ b/iOverlay/tests/direction_tests.rs @@ -3,9 +3,9 @@ mod tests { use i_float::int::point::IntPoint; use i_overlay::core::fill_rule::FillRule; use i_overlay::core::overlay::{ContourDirection, IntOverlayOptions, Overlay}; + use i_overlay::core::overlay_rule::OverlayRule; use i_overlay::core::simplify::Simplify; use i_shape::int::area::Area; - use i_overlay::core::overlay_rule::OverlayRule; #[test] fn test_0() { @@ -71,7 +71,7 @@ mod tests { min_output_area: 0, ogc: false, }; - + let r0 = &path.simplify(FillRule::NonZero, op0)[0]; debug_assert!(r0[0].area_two() < 0); debug_assert!(r0[1].area_two() > 0); diff --git a/iOverlay/tests/doc_tests.rs b/iOverlay/tests/doc_tests.rs index 5243eb51..40e09da7 100644 --- a/iOverlay/tests/doc_tests.rs +++ b/iOverlay/tests/doc_tests.rs @@ -85,19 +85,9 @@ mod tests { #[test] fn test_slice() { - let polygon = [ - [1.0, 1.0], - [1.0, 4.0], - [4.0, 4.0], - [4.0, 1.0], - ]; + let polygon = [[1.0, 1.0], [1.0, 4.0], [4.0, 4.0], [4.0, 1.0]]; - let slicing_line = [ - [3.0, 5.0], - [2.0, 2.0], - [3.0, 3.0], - [2.0, 0.0], - ]; + let slicing_line = [[3.0, 5.0], [2.0, 2.0], [3.0, 3.0], [2.0, 0.0]]; let result = polygon.slice_by(&slicing_line, FillRule::NonZero); @@ -106,23 +96,16 @@ mod tests { #[test] fn test_clip() { - let polygon = [ - [1.0, 1.0], - [1.0, 4.0], - [4.0, 4.0], - [4.0, 1.0], - ]; + let polygon = [[1.0, 1.0], [1.0, 4.0], [4.0, 4.0], [4.0, 1.0]]; - let string_line = [ - [3.0, 5.0], - [2.0, 2.0], - [3.0, 3.0], - [2.0, 0.0], - ]; + let string_line = [[3.0, 5.0], [2.0, 2.0], [3.0, 3.0], [2.0, 0.0]]; - let clip_rule = ClipRule { invert: false, boundary_included: false }; + let clip_rule = ClipRule { + invert: false, + boundary_included: false, + }; let result = string_line.clip_by(&polygon, FillRule::NonZero, clip_rule); println!("result: {:?}", result); } -} \ No newline at end of file +} diff --git a/iOverlay/tests/dynamic_tests.rs b/iOverlay/tests/dynamic_tests.rs index f4d988ed..baf6b20c 100644 --- a/iOverlay/tests/dynamic_tests.rs +++ b/iOverlay/tests/dynamic_tests.rs @@ -46,9 +46,8 @@ mod tests { let mut a = 0.0; while a < 4.0 * PI { let subj = create_star(200.0, 30.0, 7, a); - if let Some(graph) = - Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let _ = graph.extract_shapes(OverlayRule::Xor, &mut Default::default()); @@ -66,9 +65,8 @@ mod tests { while a < 2.0 * PI { let subj = create_star(202.5, 33.75, 24, a); - if let Some(graph) = - Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let _ = graph.extract_shapes(OverlayRule::Xor, &mut Default::default()); @@ -86,9 +84,8 @@ mod tests { while a < 4.0 * PI { let subj = create_star(100.0, 10.0, 17, a); - if let Some(graph) = - Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let _ = graph.extract_shapes(OverlayRule::Xor, &mut Default::default()); @@ -106,9 +103,8 @@ mod tests { while a < 0.000_001 { let subj = create_star(202.5, 33.75, 24, a); - if let Some(graph) = - Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let _ = graph.extract_shapes(OverlayRule::Xor, &mut Default::default()); @@ -126,9 +122,8 @@ mod tests { // println!("subj {:?}", subj); for &solver in SOLVERS.iter() { - if let Some(graph) = - Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let result = graph.extract_shapes(OverlayRule::Xor, &mut Default::default()); @@ -145,9 +140,8 @@ mod tests { while a < 0.000_001 { let subj = create_star(100.0, 50.0, 24, a); - if let Some(graph) = - Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let _ = graph.extract_shapes(OverlayRule::Xor, &mut Default::default()); @@ -205,8 +199,9 @@ mod tests { let mut a = 0.0; while a < 2.0 * PI { let subj = create_star(r0, r, 4, a); - if let Some(graph) = Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) - .build_graph_view(FillRule::NonZero) + if let Some(graph) = + Overlay::with_contours_custom(&subj, &clip, Default::default(), solver) + .build_graph_view(FillRule::NonZero) { graph.validate(); let result = graph.extract_shapes(OverlayRule::Union, &mut Default::default()); @@ -247,9 +242,7 @@ mod tests { overlay.add_contour(&subj_path, ShapeType::Subject); overlay.add_contour(&clip_path, ShapeType::Clip); - if let Some(graph) = - overlay.build_graph_view(FillRule::NonZero) - { + if let Some(graph) = overlay.build_graph_view(FillRule::NonZero) { graph.validate(); let result = graph.extract_shapes(OverlayRule::Union, &mut Default::default()); assert!(result.len() > 0); @@ -264,9 +257,7 @@ mod tests { let subj_path = random(10, n); let mut overlay = Overlay::new(2 * n); overlay.add_contour(&subj_path, ShapeType::Subject); - if let Some(graph) = - overlay.build_graph_view(FillRule::NonZero) - { + if let Some(graph) = overlay.build_graph_view(FillRule::NonZero) { graph.validate(); let result = graph.extract_shapes(OverlayRule::Subject, &mut Default::default()); assert!(result.len() > 0); @@ -281,9 +272,7 @@ mod tests { let r = i as f64; let subj_path = random_float(r, n); let mut overlay = FloatOverlay::with_subj(&subj_path); - if let Some(graph) = - overlay.build_graph_view(FillRule::NonZero) - { + if let Some(graph) = overlay.build_graph_view(FillRule::NonZero) { graph.graph.validate(); let result = graph.extract_shapes(OverlayRule::Subject, &mut Default::default()); assert!(result.len() > 0); @@ -322,21 +311,9 @@ mod tests { #[test] fn test_15() { let subj_paths = [ - vec![ - IntPoint::new(0, 0), - IntPoint::new(1, 6), - IntPoint::new(6, 4), - ], - vec![ - IntPoint::new(0, 0), - IntPoint::new(6, 5), - IntPoint::new(2, -2), - ], - vec![ - IntPoint::new(0, 0), - IntPoint::new(3, -1), - IntPoint::new(1, 3), - ], + vec![IntPoint::new(0, 0), IntPoint::new(1, 6), IntPoint::new(6, 4)], + vec![IntPoint::new(0, 0), IntPoint::new(6, 5), IntPoint::new(2, -2)], + vec![IntPoint::new(0, 0), IntPoint::new(3, -1), IntPoint::new(1, 3)], ]; let mut overlay = Overlay::new(4); overlay.add_contours(&subj_paths, ShapeType::Subject); diff --git a/iOverlay/tests/empty_tests.rs b/iOverlay/tests/empty_tests.rs index 0a05da0a..b75085e2 100644 --- a/iOverlay/tests/empty_tests.rs +++ b/iOverlay/tests/empty_tests.rs @@ -21,4 +21,4 @@ mod tests { let graph = overlay.build_graph_view(FillRule::NonZero); assert!(graph.is_none()); } -} \ No newline at end of file +} diff --git a/iOverlay/tests/fill_rule_tests.rs b/iOverlay/tests/fill_rule_tests.rs index 293b1c0c..605a40a9 100644 --- a/iOverlay/tests/fill_rule_tests.rs +++ b/iOverlay/tests/fill_rule_tests.rs @@ -1,10 +1,10 @@ #[cfg(test)] mod tests { use i_float::int::point::IntPoint; - use i_shape::int::path::IntPath; use i_overlay::core::fill_rule::FillRule; use i_overlay::core::overlay::{Overlay, ShapeType}; use i_overlay::core::overlay_rule::OverlayRule; + use i_shape::int::path::IntPath; #[test] fn test_both_clock_wise() { @@ -19,10 +19,22 @@ mod tests { let mut buffer = Default::default(); - let even_odd = overlay().build_graph_view(FillRule::EvenOdd).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let non_zero = overlay().build_graph_view(FillRule::NonZero).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let positive = overlay().build_graph_view(FillRule::Positive).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let negative = overlay().build_graph_view(FillRule::Negative).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); + let even_odd = overlay() + .build_graph_view(FillRule::EvenOdd) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let non_zero = overlay() + .build_graph_view(FillRule::NonZero) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let positive = overlay() + .build_graph_view(FillRule::Positive) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let negative = overlay() + .build_graph_view(FillRule::Negative) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); assert_eq!(even_odd.len(), 1); assert_eq!(even_odd[0].len(), 2); @@ -49,10 +61,22 @@ mod tests { let mut buffer = Default::default(); - let even_odd = overlay().build_graph_view(FillRule::EvenOdd).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let non_zero = overlay().build_graph_view(FillRule::NonZero).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let positive = overlay().build_graph_view(FillRule::Positive).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let negative = overlay().build_graph_view(FillRule::Negative).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); + let even_odd = overlay() + .build_graph_view(FillRule::EvenOdd) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let non_zero = overlay() + .build_graph_view(FillRule::NonZero) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let positive = overlay() + .build_graph_view(FillRule::Positive) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let negative = overlay() + .build_graph_view(FillRule::Negative) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); assert_eq!(even_odd.len(), 1); assert_eq!(even_odd[0].len(), 2); @@ -79,10 +103,22 @@ mod tests { let mut buffer = Default::default(); - let even_odd = overlay().build_graph_view(FillRule::EvenOdd).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let non_zero = overlay().build_graph_view(FillRule::NonZero).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let positive = overlay().build_graph_view(FillRule::Positive).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let negative = overlay().build_graph_view(FillRule::Negative).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); + let even_odd = overlay() + .build_graph_view(FillRule::EvenOdd) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let non_zero = overlay() + .build_graph_view(FillRule::NonZero) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let positive = overlay() + .build_graph_view(FillRule::Positive) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let negative = overlay() + .build_graph_view(FillRule::Negative) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); assert_eq!(even_odd.len(), 1); assert_eq!(even_odd[0].len(), 2); @@ -96,8 +132,6 @@ mod tests { assert_eq!(positive.len(), 0); } - - #[test] fn test_ccw_and_cw() { fn overlay() -> Overlay { @@ -111,10 +145,22 @@ mod tests { let mut buffer = Default::default(); - let even_odd = overlay().build_graph_view(FillRule::EvenOdd).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let non_zero = overlay().build_graph_view(FillRule::NonZero).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let positive = overlay().build_graph_view(FillRule::Positive).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); - let negative = overlay().build_graph_view(FillRule::Negative).unwrap().extract_shapes(OverlayRule::Subject, &mut buffer); + let even_odd = overlay() + .build_graph_view(FillRule::EvenOdd) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let non_zero = overlay() + .build_graph_view(FillRule::NonZero) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let positive = overlay() + .build_graph_view(FillRule::Positive) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); + let negative = overlay() + .build_graph_view(FillRule::Negative) + .unwrap() + .extract_shapes(OverlayRule::Subject, &mut buffer); assert_eq!(even_odd.len(), 1); assert_eq!(even_odd[0].len(), 2); @@ -133,8 +179,9 @@ mod tests { IntPoint::new(-radius, -radius), IntPoint::new(-radius, radius), IntPoint::new(radius, radius), - IntPoint::new(radius, -radius) - ].to_vec(); + IntPoint::new(radius, -radius), + ] + .to_vec(); if !is_clockwise { square.reverse() @@ -142,5 +189,4 @@ mod tests { square } - -} \ No newline at end of file +} diff --git a/iOverlay/tests/float_overlay_tests.rs b/iOverlay/tests/float_overlay_tests.rs index 30ab193a..0d484ebe 100644 --- a/iOverlay/tests/float_overlay_tests.rs +++ b/iOverlay/tests/float_overlay_tests.rs @@ -53,7 +53,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -79,7 +80,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -106,7 +108,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -133,7 +136,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -159,7 +163,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -185,7 +190,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -211,7 +217,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -235,7 +242,8 @@ mod tests { ]]; let union = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) - .build_graph_view(FillRule::NonZero).unwrap() + .build_graph_view(FillRule::NonZero) + .unwrap() .extract_shapes(OverlayRule::Union, &mut Default::default()); assert_eq!(union.len(), 1); @@ -262,10 +270,11 @@ mod tests { fn test_empty_0() { let path = vec![FPoint::new(-10.0, -10.0), FPoint::new(-10.0, 10.0)]; - let shapes = - FloatOverlay::with_adapter(FloatPointAdapter::with_iter(path.iter()), path.len()) - .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + let shapes = FloatOverlay::with_adapter(FloatPointAdapter::with_iter(path.iter()), path.len()) + .build_graph_view(FillRule::NonZero) + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.is_empty(), true); } @@ -280,13 +289,13 @@ mod tests { ] .to_vec()]; - let shapes = FloatOverlay::with_adapter( - FloatPointAdapter::with_iter(shape.iter().flatten()), - shape.len(), - ) - .unsafe_add_source(&shape, ShapeType::Subject) - .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + let shapes = + FloatOverlay::with_adapter(FloatPointAdapter::with_iter(shape.iter().flatten()), shape.len()) + .unsafe_add_source(&shape, ShapeType::Subject) + .build_graph_view(FillRule::NonZero) + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -306,7 +315,9 @@ mod tests { let shapes = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -322,14 +333,13 @@ mod tests { FPoint::new(10.0, -10.0), ]]; - let shape_1 = vec![vec![ - FPoint::new(-500.0, -500.0), - FPoint::new(-500.0, 500.0), - ]]; + let shape_1 = vec![vec![FPoint::new(-500.0, -500.0), FPoint::new(-500.0, 500.0)]]; let shapes = FloatOverlay::with_subj_and_clip(&shape_0, &shape_1) .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.len(), 1); assert_eq!(shapes[0].len(), 1); @@ -339,23 +349,24 @@ mod tests { #[test] fn test_empty_4() { let path = vec![FPoint::new(0.0, 0.0)]; - let shapes = - FloatOverlay::with_adapter(FloatPointAdapter::with_iter(path.iter()), path.len()) - .unsafe_add_contour(&path, ShapeType::Subject) - .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + let shapes = FloatOverlay::with_adapter(FloatPointAdapter::with_iter(path.iter()), path.len()) + .unsafe_add_contour(&path, ShapeType::Subject) + .build_graph_view(FillRule::NonZero) + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.len(), 0); } #[test] fn test_empty_5() { - let shapes = FloatOverlay::with_subj_and_clip( - &vec![FPoint::new(0.0, 0.0)], - &vec![FPoint::new(1.0, 0.0)], - ) - .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + let shapes = + FloatOverlay::with_subj_and_clip(&vec![FPoint::new(0.0, 0.0)], &vec![FPoint::new(1.0, 0.0)]) + .build_graph_view(FillRule::NonZero) + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.len(), 0); } @@ -363,11 +374,12 @@ mod tests { #[test] fn test_empty_6() { let path = vec![FPoint::new(0.0, 0.0), FPoint::new(1.0, 0.0)]; - let shapes = - FloatOverlay::with_adapter(FloatPointAdapter::with_iter(path.iter()), path.len()) - .unsafe_add_contour(&path, ShapeType::Subject) - .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut Default::default())); + let shapes = FloatOverlay::with_adapter(FloatPointAdapter::with_iter(path.iter()), path.len()) + .unsafe_add_contour(&path, ShapeType::Subject) + .build_graph_view(FillRule::NonZero) + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut Default::default()) + }); assert_eq!(shapes.len(), 0); } @@ -685,12 +697,10 @@ mod tests { ogc: false, clean_result: false, }; - - let result_with_filter = FloatOverlay::with_subj_and_clip_custom(&shape_0, &shape_1, opt, Default::default()) - .overlay( - OverlayRule::Intersect, - FillRule::EvenOdd, - ); + + let result_with_filter = + FloatOverlay::with_subj_and_clip_custom(&shape_0, &shape_1, opt, Default::default()) + .overlay(OverlayRule::Intersect, FillRule::EvenOdd); assert_eq!(result_no_filter.len(), 1); assert_eq!(result_with_filter.len(), 2); diff --git a/iOverlay/tests/float_point_adapter.rs b/iOverlay/tests/float_point_adapter.rs index ae62796c..22d469ea 100644 --- a/iOverlay/tests/float_point_adapter.rs +++ b/iOverlay/tests/float_point_adapter.rs @@ -2,11 +2,11 @@ mod tests { use i_float::adapter::FloatPointAdapter; use i_float::float::rect::FloatRect; - use i_shape::source::resource::ShapeResource; use i_overlay::core::fill_rule::FillRule; use i_overlay::core::overlay::ShapeType; use i_overlay::core::overlay_rule::OverlayRule; use i_overlay::float::overlay::FloatOverlay; + use i_shape::source::resource::ShapeResource; #[test] fn test_adapter_with_rect() { @@ -79,4 +79,4 @@ mod tests { println!("100: {:?}", c100); println!("1000: {:?}", c1000); } -} \ No newline at end of file +} diff --git a/iOverlay/tests/fragment_tests.rs b/iOverlay/tests/fragment_tests.rs index 23db8cc5..a9c4ffce 100644 --- a/iOverlay/tests/fragment_tests.rs +++ b/iOverlay/tests/fragment_tests.rs @@ -2,14 +2,14 @@ mod util; #[cfg(test)] mod tests { + use crate::util::overlay::JsonPrint; use i_float::int::point::IntPoint; - use i_shape::int::path::IntPath; use i_overlay::core::fill_rule::FillRule; use i_overlay::core::overlay::{Overlay, ShapeType}; use i_overlay::core::overlay_rule::OverlayRule; use i_overlay::core::solver::Solver; + use i_shape::int::path::IntPath; use i_shape::int::shape::IntContour; - use crate::util::overlay::JsonPrint; #[test] fn test_many_squares() { @@ -20,14 +20,17 @@ mod tests { let subj_paths = many_squares(IntPoint::new(0, 0), 20, 30, n); let clip_paths = many_squares(IntPoint::new(15, 15), 20, 30, n - 1); - let list_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::LIST) - .overlay(rule, fill); + let list_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::LIST) + .overlay(rule, fill); - let tree_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::TREE) - .overlay(rule, fill); + let tree_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::TREE) + .overlay(rule, fill); - let frag_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::FRAG) - .overlay(rule, fill); + let frag_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::FRAG) + .overlay(rule, fill); assert_eq!(list_result, tree_result); assert_eq!(list_result, frag_result); @@ -43,14 +46,17 @@ mod tests { let subj_paths = repeat_xy(square(0, 0, 2), 0, 0, 10, 10, n); let clip_paths = repeat_xy(romb(0, 0, 4), 5, 5, 10, 10, n - 1); - let list_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::LIST) - .overlay(rule, fill); + let list_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::LIST) + .overlay(rule, fill); - let tree_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::TREE) - .overlay(rule, fill); + let tree_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::TREE) + .overlay(rule, fill); - let frag_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::FRAG) - .overlay(rule, fill); + let frag_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::FRAG) + .overlay(rule, fill); assert_eq!(list_result, tree_result); assert_eq!(list_result, frag_result); @@ -67,14 +73,17 @@ mod tests { let subj_paths = many_lines_x(20, n); let clip_paths = many_lines_y(20, n); - let list_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::LIST) - .overlay(rule, fill); + let list_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::LIST) + .overlay(rule, fill); - let tree_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::TREE) - .overlay(rule, fill); + let tree_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::TREE) + .overlay(rule, fill); - let frag_result = Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::FRAG) - .overlay(rule, fill); + let frag_result = + Overlay::with_contours_custom(&subj_paths, &clip_paths, Default::default(), Solver::FRAG) + .overlay(rule, fill); assert_eq!(list_result, tree_result); assert_eq!(list_result, frag_result); @@ -195,7 +204,6 @@ mod tests { println!("clip: {}", clip.json_print()); } - fn many_squares(start: IntPoint, size: i32, offset: i32, n: usize) -> Vec { let mut result = Vec::with_capacity(n * n); let mut y = start.y; @@ -265,7 +273,6 @@ mod tests { // horizontal rects let mut r = 0; for _ in 0..count { - // bottom let r0x0 = -r; let r0x1 = r0x0; @@ -312,10 +319,30 @@ mod tests { r += a4; - rects.push(vec![IntPoint::new(r0x0, r0y0), IntPoint::new(r0x1, r0y1), IntPoint::new(r0x2, r0y2), IntPoint::new(r0x3, r0y3)]); - rects.push(vec![IntPoint::new(r1x0, r1y0), IntPoint::new(r1x1, r1y1), IntPoint::new(r1x2, r1y2), IntPoint::new(r1x3, r1y3)]); - rects.push(vec![IntPoint::new(r2x0, r2y0), IntPoint::new(r2x1, r2y1), IntPoint::new(r2x2, r2y2), IntPoint::new(r2x3, r2y3)]); - rects.push(vec![IntPoint::new(r3x0, r3y0), IntPoint::new(r3x1, r3y1), IntPoint::new(r3x2, r3y2), IntPoint::new(r3x3, r3y3)]); + rects.push(vec![ + IntPoint::new(r0x0, r0y0), + IntPoint::new(r0x1, r0y1), + IntPoint::new(r0x2, r0y2), + IntPoint::new(r0x3, r0y3), + ]); + rects.push(vec![ + IntPoint::new(r1x0, r1y0), + IntPoint::new(r1x1, r1y1), + IntPoint::new(r1x2, r1y2), + IntPoint::new(r1x3, r1y3), + ]); + rects.push(vec![ + IntPoint::new(r2x0, r2y0), + IntPoint::new(r2x1, r2y1), + IntPoint::new(r2x2, r2y2), + IntPoint::new(r2x3, r2y3), + ]); + rects.push(vec![ + IntPoint::new(r3x0, r3y0), + IntPoint::new(r3x1, r3y1), + IntPoint::new(r3x2, r3y2), + IntPoint::new(r3x3, r3y3), + ]); rects.push(romb(-r, r, a2)); rects.push(romb(-r, -r, a2)); @@ -395,4 +422,4 @@ mod tests { contours } -} \ No newline at end of file +} diff --git a/iOverlay/tests/ocg_tests.rs b/iOverlay/tests/ocg_tests.rs index a9b69f26..12486458 100644 --- a/iOverlay/tests/ocg_tests.rs +++ b/iOverlay/tests/ocg_tests.rs @@ -201,12 +201,8 @@ mod tests { subj_paths.push(hz_line); } - let mut overlay = Overlay::with_contours_custom( - &subj_paths, - &[], - IntOverlayOptions::ogc(), - Default::default(), - ); + let mut overlay = + Overlay::with_contours_custom(&subj_paths, &[], IntOverlayOptions::ogc(), Default::default()); let result = overlay.overlay(OverlayRule::Subject, FillRule::EvenOdd); @@ -266,12 +262,8 @@ mod tests { y += 1; } - let mut overlay = Overlay::with_contours_custom( - &subj_paths, - &[], - IntOverlayOptions::ogc(), - Default::default(), - ); + let mut overlay = + Overlay::with_contours_custom(&subj_paths, &[], IntOverlayOptions::ogc(), Default::default()); let result = overlay.overlay(OverlayRule::Subject, FillRule::EvenOdd); diff --git a/iOverlay/tests/overlay_tests.rs b/iOverlay/tests/overlay_tests.rs index 84872faa..3c388dea 100644 --- a/iOverlay/tests/overlay_tests.rs +++ b/iOverlay/tests/overlay_tests.rs @@ -30,7 +30,7 @@ mod tests { } let mut buffer = Default::default(); - + for solver in SOLVERS { let mut ovr = overlay(&test, options, solver); let graph = if let Some(graph) = ovr.build_graph_view(fill_rule) { @@ -40,47 +40,26 @@ mod tests { }; let subject_0 = graph.extract_shapes(OverlayRule::Subject, &mut buffer); - let subject_1 = overlay(&test, options, solver).overlay( - OverlayRule::Subject, - fill_rule - ); + let subject_1 = overlay(&test, options, solver).overlay(OverlayRule::Subject, fill_rule); let clip_0 = graph.extract_shapes(OverlayRule::Clip, &mut buffer); - let clip_1 = overlay(&test, options, solver).overlay( - OverlayRule::Clip, - fill_rule, - ); + let clip_1 = overlay(&test, options, solver).overlay(OverlayRule::Clip, fill_rule); let difference_0 = graph.extract_shapes(OverlayRule::Difference, &mut buffer); - let difference_1 = overlay(&test, options, solver).overlay( - OverlayRule::Difference, - fill_rule, - ); + let difference_1 = overlay(&test, options, solver).overlay(OverlayRule::Difference, fill_rule); - let inverse_difference_0 = - graph.extract_shapes(OverlayRule::InverseDifference, &mut buffer); - let inverse_difference_1 = overlay(&test, options, solver).overlay( - OverlayRule::InverseDifference, - fill_rule, - ); + let inverse_difference_0 = graph.extract_shapes(OverlayRule::InverseDifference, &mut buffer); + let inverse_difference_1 = + overlay(&test, options, solver).overlay(OverlayRule::InverseDifference, fill_rule); let intersect_0 = graph.extract_shapes(OverlayRule::Intersect, &mut buffer); - let intersect_1 = overlay(&test, options, solver).overlay( - OverlayRule::Intersect, - fill_rule, - ); + let intersect_1 = overlay(&test, options, solver).overlay(OverlayRule::Intersect, fill_rule); let union_0 = graph.extract_shapes(OverlayRule::Union, &mut buffer); - let union_1 = overlay(&test, options, solver).overlay( - OverlayRule::Union, - fill_rule, - ); + let union_1 = overlay(&test, options, solver).overlay(OverlayRule::Union, fill_rule); let xor_0 = graph.extract_shapes(OverlayRule::Xor, &mut buffer); - let xor_1 = overlay(&test, options, solver).overlay( - OverlayRule::Xor, - fill_rule, - ); + let xor_1 = overlay(&test, options, solver).overlay(OverlayRule::Xor, fill_rule); assert_eq!(subject_0, subject_1); assert_eq!(clip_0, clip_1); @@ -90,10 +69,7 @@ mod tests { assert_eq!(union_0, union_1); assert_eq!(xor_0, xor_1); - assert_eq!( - true, - overlay::is_group_of_shapes_one_of(&clip_0, &test.clip) - ); + assert_eq!(true, overlay::is_group_of_shapes_one_of(&clip_0, &test.clip)); assert_eq!( true, overlay::is_group_of_shapes_one_of(&subject_0, &test.subject) @@ -110,10 +86,7 @@ mod tests { true, overlay::is_group_of_shapes_one_of(&intersect_0, &test.intersect) ); - assert_eq!( - true, - overlay::is_group_of_shapes_one_of(&union_0, &test.union) - ); + assert_eq!(true, overlay::is_group_of_shapes_one_of(&union_0, &test.union)); assert_eq!(true, overlay::is_group_of_shapes_one_of(&xor_0, &test.xor)); } } @@ -121,28 +94,21 @@ mod tests { #[allow(dead_code)] fn debug_execute(index: usize, overlay_rule: OverlayRule, fill_rule: FillRule, solver: Solver) { let test = BooleanTest::load(index); - let mut overlay = Overlay::with_contours_custom(&test.subj_paths, &test.clip_paths, Default::default(), solver); + let mut overlay = + Overlay::with_contours_custom(&test.subj_paths, &test.clip_paths, Default::default(), solver); let graph = overlay.build_graph_view(fill_rule).unwrap(); let result = graph.extract_shapes(overlay_rule, &mut Default::default()); println!("{}: {}", &overlay_rule, result.json_print()); match overlay_rule { - OverlayRule::Subject => assert_eq!( - true, - overlay::is_group_of_shapes_one_of(&result, &test.subject) - ), - OverlayRule::Clip => assert_eq!( - true, - overlay::is_group_of_shapes_one_of(&result, &test.clip) - ), - OverlayRule::Intersect => assert_eq!( - true, - overlay::is_group_of_shapes_one_of(&result, &test.intersect) - ), - OverlayRule::Union => assert_eq!( - true, - overlay::is_group_of_shapes_one_of(&result, &test.union) - ), + OverlayRule::Subject => { + assert_eq!(true, overlay::is_group_of_shapes_one_of(&result, &test.subject)) + } + OverlayRule::Clip => assert_eq!(true, overlay::is_group_of_shapes_one_of(&result, &test.clip)), + OverlayRule::Intersect => { + assert_eq!(true, overlay::is_group_of_shapes_one_of(&result, &test.intersect)) + } + OverlayRule::Union => assert_eq!(true, overlay::is_group_of_shapes_one_of(&result, &test.union)), OverlayRule::Difference => assert_eq!( true, overlay::is_group_of_shapes_one_of(&result, &test.difference) @@ -183,10 +149,7 @@ mod tests { println!("\"union\": [{}],", union.json_print()); println!("\"intersect\": [{}],", intersect.json_print()); println!("\"difference\": [{}],", difference.json_print()); - println!( - "\"inverseDifference\": [{}],", - inverse_difference.json_print() - ); + println!("\"inverseDifference\": [{}],", inverse_difference.json_print()); println!("\"xor\": [{}]", xor.json_print()); } diff --git a/iOverlay/tests/simplify_tests.rs b/iOverlay/tests/simplify_tests.rs index 7a98a8f8..4e35f9c9 100644 --- a/iOverlay/tests/simplify_tests.rs +++ b/iOverlay/tests/simplify_tests.rs @@ -1,24 +1,23 @@ #[cfg(test)] mod tests { use i_float::int::point::IntPoint; - use i_shape::int::shape::IntShape; use i_overlay::core::fill_rule::FillRule; use i_overlay::core::overlay::{ContourDirection, IntOverlayOptions, Overlay, ShapeType}; use i_overlay::core::overlay_rule::OverlayRule; use i_overlay::core::simplify::Simplify; use i_overlay::core::solver::{Precision, Solver}; + use i_shape::int::shape::IntShape; #[test] fn test_0() { - let paths = - [ - [ - IntPoint::new(10614, 4421), - IntPoint::new(10609, 4421), - IntPoint::new(10609, 4415), - IntPoint::new(10614, 4415) - ].to_vec() - ].to_vec(); + let paths = [[ + IntPoint::new(10614, 4421), + IntPoint::new(10609, 4421), + IntPoint::new(10609, 4415), + IntPoint::new(10614, 4415), + ] + .to_vec()] + .to_vec(); let op = IntOverlayOptions { preserve_input_collinear: true, @@ -36,17 +35,17 @@ mod tests { #[test] fn test_1() { - let paths = - [ - square(IntPoint::new(-10, -10)), - square(IntPoint::new(-10, 0)), - square(IntPoint::new(-10, 10)), - square(IntPoint::new(0, -10)), - square(IntPoint::new(0, 10)), - square(IntPoint::new(10, -10)), - square(IntPoint::new(10, 0)), - square(IntPoint::new(10, 10)) - ].to_vec(); + let paths = [ + square(IntPoint::new(-10, -10)), + square(IntPoint::new(-10, 0)), + square(IntPoint::new(-10, 10)), + square(IntPoint::new(0, -10)), + square(IntPoint::new(0, 10)), + square(IntPoint::new(10, -10)), + square(IntPoint::new(10, 0)), + square(IntPoint::new(10, 10)), + ] + .to_vec(); let op = IntOverlayOptions { preserve_input_collinear: true, @@ -64,17 +63,17 @@ mod tests { #[test] fn test_2() { - let shapes = - [ - square_shape(IntPoint::new(-10, -10)), - square_shape(IntPoint::new(-10, 0)), - square_shape(IntPoint::new(-10, 10)), - square_shape(IntPoint::new(0, -10)), - square_shape(IntPoint::new(0, 10)), - square_shape(IntPoint::new(10, -10)), - square_shape(IntPoint::new(10, 0)), - square_shape(IntPoint::new(10, 10)) - ].to_vec(); + let shapes = [ + square_shape(IntPoint::new(-10, -10)), + square_shape(IntPoint::new(-10, 0)), + square_shape(IntPoint::new(-10, 10)), + square_shape(IntPoint::new(0, -10)), + square_shape(IntPoint::new(0, 10)), + square_shape(IntPoint::new(10, -10)), + square_shape(IntPoint::new(10, 0)), + square_shape(IntPoint::new(10, 10)), + ] + .to_vec(); let op = IntOverlayOptions { preserve_input_collinear: true, @@ -92,13 +91,13 @@ mod tests { #[test] fn test_3() { - let path = - [ - IntPoint::new(0, 0), - IntPoint::new(3, 1), - IntPoint::new(0, 3), - IntPoint::new(3, 0) - ].to_vec(); + let path = [ + IntPoint::new(0, 0), + IntPoint::new(3, 1), + IntPoint::new(0, 3), + IntPoint::new(3, 0), + ] + .to_vec(); let mut buffer = Default::default(); @@ -116,11 +115,15 @@ mod tests { let simple_0 = overlay_0 .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut buffer)); + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut buffer) + }); let simple_1 = overlay_1 .build_graph_view(FillRule::NonZero) - .map_or(Default::default(), |graph|graph.extract_shapes(OverlayRule::Subject, &mut buffer)); + .map_or(Default::default(), |graph| { + graph.extract_shapes(OverlayRule::Subject, &mut buffer) + }); assert_eq!(simple_0.len(), 1); assert_eq!(simple_0[0].len(), 1); @@ -131,16 +134,8 @@ mod tests { #[test] fn test_4() { let paths = vec![ - vec![ - IntPoint::new(-5, 0), - IntPoint::new(0, 0), - IntPoint::new(0, 5) - ], - vec![ - IntPoint::new(-3, 2), - IntPoint::new(-1, 2), - IntPoint::new(-1, 1) - ] + vec![IntPoint::new(-5, 0), IntPoint::new(0, 0), IntPoint::new(0, 5)], + vec![IntPoint::new(-3, 2), IntPoint::new(-1, 2), IntPoint::new(-1, 1)], ]; let op = IntOverlayOptions { @@ -164,8 +159,9 @@ mod tests { IntPoint::new(-5 + pos.x, -5 + pos.y), IntPoint::new(-5 + pos.x, 5 + pos.y), IntPoint::new(5 + pos.x, 5 + pos.y), - IntPoint::new(5 + pos.x, -5 + pos.y) - ].to_vec() + IntPoint::new(5 + pos.x, -5 + pos.y), + ] + .to_vec() } fn square_shape(pos: IntPoint) -> IntShape { diff --git a/iOverlay/tests/slice_tests.rs b/iOverlay/tests/slice_tests.rs index 667c2164..9c432eb6 100644 --- a/iOverlay/tests/slice_tests.rs +++ b/iOverlay/tests/slice_tests.rs @@ -54,10 +54,7 @@ mod tests { IntPoint::new(-10, -10), ]; - let result = path.slice_by_line( - [IntPoint::new(0, -5), IntPoint::new(0, 5)], - FillRule::NonZero, - ); + let result = path.slice_by_line([IntPoint::new(0, -5), IntPoint::new(0, 5)], FillRule::NonZero); assert_eq!(result.len(), 1); assert_eq!(result[0].len(), 1); @@ -73,10 +70,7 @@ mod tests { IntPoint::new(10, -10), ]; - let result = path.slice_by_line( - [IntPoint::new(0, -20), IntPoint::new(0, 20)], - FillRule::NonZero, - ); + let result = path.slice_by_line([IntPoint::new(0, -20), IntPoint::new(0, 20)], FillRule::NonZero); assert_eq!(result.len(), 2); assert_eq!(result[0].len(), 1); @@ -305,11 +299,7 @@ mod tests { #[test] fn test_0() { - let path = [ - IntPoint::new(2, -2), - IntPoint::new(0, -1), - IntPoint::new(1, 2), - ]; + let path = [IntPoint::new(2, -2), IntPoint::new(0, -1), IntPoint::new(1, 2)]; let line = [IntPoint::new(2, 1), IntPoint::new(-1, -2)]; let result = path.slice_by_line(line, FillRule::NonZero); @@ -321,12 +311,7 @@ mod tests { #[test] fn test_1() { - let path = [ - IntPoint::new(0, 2), - IntPoint::new(0, -1), - IntPoint::new(-1, -2), - ] - .to_vec(); + let path = [IntPoint::new(0, 2), IntPoint::new(0, -1), IntPoint::new(-1, -2)].to_vec(); let lines = [ [IntPoint::new(-1, -2), IntPoint::new(-1, -1)], @@ -343,11 +328,7 @@ mod tests { #[test] fn test_2() { - let path = [ - IntPoint::new(1, 4), - IntPoint::new(-4, 4), - IntPoint::new(-2, -4), - ]; + let path = [IntPoint::new(1, 4), IntPoint::new(-4, 4), IntPoint::new(-2, -4)]; let lines = [ [IntPoint::new(1, 4), IntPoint::new(-2, 2)], @@ -366,11 +347,7 @@ mod tests { #[test] fn test_3() { - let path = [ - IntPoint::new(-4, -2), - IntPoint::new(2, 2), - IntPoint::new(3, -3), - ]; + let path = [IntPoint::new(-4, -2), IntPoint::new(2, 2), IntPoint::new(3, -3)]; let lines = [ [IntPoint::new(-1, -2), IntPoint::new(1, 0)], @@ -413,11 +390,7 @@ mod tests { #[test] fn test_5() { - let path = [ - IntPoint::new(1, -1), - IntPoint::new(-1, -1), - IntPoint::new(-2, -1), - ]; + let path = [IntPoint::new(1, -1), IntPoint::new(-1, -1), IntPoint::new(-2, -1)]; let lines = vec![ [IntPoint::new(1, 1), IntPoint::new(0, 0)], diff --git a/iOverlay/tests/string_tests.rs b/iOverlay/tests/string_tests.rs index eb7d10db..9c984566 100644 --- a/iOverlay/tests/string_tests.rs +++ b/iOverlay/tests/string_tests.rs @@ -3,12 +3,12 @@ mod util; #[cfg(test)] mod tests { - use i_overlay::core::fill_rule::FillRule; - use i_overlay::string::clip::{ClipRule, IntClip}; - use i_overlay::string::slice::IntSlice; use crate::data::overlay::StringTest; use crate::util::overlay; use crate::util::overlay::JsonPrint; + use i_overlay::core::fill_rule::FillRule; + use i_overlay::string::clip::{ClipRule, IntClip}; + use i_overlay::string::slice::IntSlice; fn execute(index: usize) { let test = StringTest::load(index); @@ -17,10 +17,24 @@ mod tests { let slice = test.body.slice_by_paths(&test.string, fill_rule); assert_eq!(true, overlay::is_group_of_shapes_one_of(&slice, &test.slice)); - let clip_direct = test.body.clip_paths(&test.string, fill_rule, ClipRule { invert: false, boundary_included: false }); + let clip_direct = test.body.clip_paths( + &test.string, + fill_rule, + ClipRule { + invert: false, + boundary_included: false, + }, + ); assert_eq!(true, overlay::is_paths_one_of(&clip_direct, &test.clip_direct)); - let clip_invert = test.body.clip_paths(&test.string, fill_rule, ClipRule { invert: true, boundary_included: false }); + let clip_invert = test.body.clip_paths( + &test.string, + fill_rule, + ClipRule { + invert: true, + boundary_included: false, + }, + ); assert_eq!(true, overlay::is_paths_one_of(&clip_invert, &test.clip_invert)); } @@ -36,7 +50,14 @@ mod tests { let test = StringTest::load(index); let fill_rule = test.fill_rule.unwrap_or(FillRule::EvenOdd); - let clip = test.body.clip_paths(&test.string, fill_rule, ClipRule { invert, boundary_included: false }); + let clip = test.body.clip_paths( + &test.string, + fill_rule, + ClipRule { + invert, + boundary_included: false, + }, + ); println!("clip {}: {}", invert, clip.json_print()); } @@ -108,4 +129,4 @@ mod tests { debug_execute_clip(index, false); debug_execute_clip(index, true); } -} \ No newline at end of file +} diff --git a/iOverlay/tests/util.rs b/iOverlay/tests/util.rs index 4727aa2b..3a92e8c2 100644 --- a/iOverlay/tests/util.rs +++ b/iOverlay/tests/util.rs @@ -137,4 +137,3 @@ pub mod overlay { } } } - diff --git a/iOverlay/tests/vector_tests.rs b/iOverlay/tests/vector_tests.rs index 8995ccdf..9724cf54 100644 --- a/iOverlay/tests/vector_tests.rs +++ b/iOverlay/tests/vector_tests.rs @@ -12,14 +12,14 @@ mod tests { IntPoint::new(-10240, -10240), IntPoint::new(-10240, 10240), IntPoint::new(10240, 10240), - IntPoint::new(10240, -10240) + IntPoint::new(10240, -10240), ]; let clip = [ IntPoint::new(-5120, -5120), IntPoint::new(-5120, 5120), IntPoint::new(5120, 5120), - IntPoint::new(5120, -5120) + IntPoint::new(5120, -5120), ]; let mut overlay = Overlay::new(2); @@ -34,25 +34,25 @@ mod tests { let vectors = &shapes[0][0]; let template = [ VectorEdge { - a: IntPoint::new(-10240,10240), - b: IntPoint::new(-10240,-10240), - fill: 1 + a: IntPoint::new(-10240, 10240), + b: IntPoint::new(-10240, -10240), + fill: 1, }, VectorEdge { - a: IntPoint::new(-10240,-10240), - b: IntPoint::new(10240,-10240), - fill: 1 + a: IntPoint::new(-10240, -10240), + b: IntPoint::new(10240, -10240), + fill: 1, }, VectorEdge { - a: IntPoint::new(10240,-10240), - b: IntPoint::new(10240,10240), - fill: 1 + a: IntPoint::new(10240, -10240), + b: IntPoint::new(10240, 10240), + fill: 1, }, VectorEdge { - a: IntPoint::new(10240,10240), - b: IntPoint::new(-10240,10240), - fill: 1 - } + a: IntPoint::new(10240, 10240), + b: IntPoint::new(-10240, 10240), + fill: 1, + }, ]; assert_eq!(vectors.as_slice(), template.as_slice()); @@ -64,14 +64,14 @@ mod tests { IntPoint::new(-10240, -10240), IntPoint::new(-10240, 10240), IntPoint::new(10240, 10240), - IntPoint::new(10240, -10240) + IntPoint::new(10240, -10240), ]; let clip = [ - IntPoint::new(-5120,-5120), - IntPoint::new(-5120,15360), - IntPoint::new(15360,15360), - IntPoint::new(15360,-5120) + IntPoint::new(-5120, -5120), + IntPoint::new(-5120, 15360), + IntPoint::new(15360, 15360), + IntPoint::new(15360, -5120), ]; let mut overlay = Overlay::new(2); @@ -86,37 +86,37 @@ mod tests { let vectors = &shapes[0][0]; let template = [ VectorEdge { - a: IntPoint::new(-10240,10240), - b: IntPoint::new(-10240,-10240), - fill: 1 + a: IntPoint::new(-10240, 10240), + b: IntPoint::new(-10240, -10240), + fill: 1, }, VectorEdge { - a: IntPoint::new(-10240,-10240), - b: IntPoint::new(10240,-10240), - fill: 1 + a: IntPoint::new(-10240, -10240), + b: IntPoint::new(10240, -10240), + fill: 1, }, VectorEdge { - a: IntPoint::new(10240,-10240), - b: IntPoint::new(10240,-5120), - fill: 1 + a: IntPoint::new(10240, -10240), + b: IntPoint::new(10240, -5120), + fill: 1, }, VectorEdge { - a: IntPoint::new(10240,-5120), - b: IntPoint::new(-5120,-5120), - fill: 11 + a: IntPoint::new(10240, -5120), + b: IntPoint::new(-5120, -5120), + fill: 11, }, VectorEdge { - a: IntPoint::new(-5120,-5120), - b: IntPoint::new(-5120,10240), - fill: 11 + a: IntPoint::new(-5120, -5120), + b: IntPoint::new(-5120, 10240), + fill: 11, }, VectorEdge { - a: IntPoint::new(-5120,10240), - b: IntPoint::new(-10240,10240), - fill: 1 - } + a: IntPoint::new(-5120, 10240), + b: IntPoint::new(-10240, 10240), + fill: 1, + }, ]; assert_eq!(vectors.as_slice(), template.as_slice()); } -} \ No newline at end of file +} From 2a3a045f408d47e6e9c3a407e8c124c0e1fded99 Mon Sep 17 00:00:00 2001 From: Nail Sharipov Date: Sun, 1 Feb 2026 16:40:59 +0300 Subject: [PATCH 2/2] add scenario --- .github/workflows/tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6d0d816f..da083e86 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,6 +13,11 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - name: Run fmt check + working-directory: iOverlay + run: cargo fmt --all -- --check - name: Run tests working-directory: iOverlay run: cargo test