@@ -65,6 +65,7 @@ new_key_type! {
65
65
66
66
use crate :: aabb:: { bounding_box_around_point, bounding_box_max_extent, expand_bounding_box, extend_bounding_box, merge_bounding_boxes, Aabb } ;
67
67
use crate :: epsilons:: Epsilons ;
68
+ use crate :: grid:: { BitVec , Grid } ;
68
69
use crate :: intersection_path_segment:: { path_segment_intersection, segments_equal} ;
69
70
use crate :: path:: Path ;
70
71
use crate :: path_cubic_segment_self_intersection:: path_cubic_segment_self_intersection;
@@ -431,29 +432,42 @@ fn split_at_self_intersections(edges: &mut Vec<MajorGraphEdgeStage1>) {
431
432
/// A tuple containing:
432
433
/// * A vector of split edges (MajorGraphEdgeStage2).
433
434
/// * An optional overall bounding box (AaBb) for all edges.
434
- fn split_at_intersections ( edges : & [ MajorGraphEdgeStage1 ] ) -> ( Vec < MajorGraphEdgeStage1 > , Option < Aabb > ) {
435
- if edges. is_empty ( ) {
436
- return ( Vec :: new ( ) , None ) ;
437
- }
438
-
435
+ fn split_at_intersections ( edges : & [ MajorGraphEdgeStage1 ] ) -> Vec < MajorGraphEdgeStage1 > {
439
436
// Step 1: Add bounding boxes to edges
440
437
let with_bounding_box: Vec < MajorGraphEdgeStage2 > = edges. iter ( ) . map ( |( seg, parent) | ( * seg, * parent, seg. approx_bounding_box ( ) ) ) . collect ( ) ;
441
438
// Step 2: Calculate total bounding box
442
- let total_bounding_box = with_bounding_box. iter ( ) . fold ( Default :: default ( ) , |acc, ( _, _, bb) | merge_bounding_boxes ( & acc, & bb) ) ;
439
+ let total_bounding_box = with_bounding_box. iter ( ) . fold ( Default :: default ( ) , |acc, ( _, _, bb) | merge_bounding_boxes ( & acc, bb) ) ;
440
+
441
+ let max_extent = bounding_box_max_extent ( & total_bounding_box) ;
442
+ let cell_size = max_extent / ( edges. len ( ) as f64 ) . sqrt ( ) ;
443
+
444
+ // Step 3: Create grid for efficient intersection checks
445
+ let mut grid = Grid :: new ( cell_size, edges. len ( ) ) ;
443
446
444
447
// Step 3: Create edge tree for efficient intersection checks
445
- let mut edge_tree = QuadTree :: new ( total_bounding_box, INTERSECTION_TREE_DEPTH , 8 ) ;
448
+ // let mut edge_tree = QuadTree::new(total_bounding_box, INTERSECTION_TREE_DEPTH, 16);
449
+ // let mut rtree = crate::util::rtree::RTree::new(24);
446
450
447
- let mut splits_per_edge: HashMap < usize , Vec < f64 > > = HashMap :: default ( ) ;
451
+ let mut splits_per_edge: Vec < Vec < f64 > > = vec ! [ Vec :: new ( ) ; edges . len ( ) ] ;
448
452
449
- fn add_split ( splits_per_edge : & mut HashMap < usize , Vec < f64 > > , i : usize , t : f64 ) {
450
- splits_per_edge. entry ( i ) . or_default ( ) . push ( t) ;
453
+ fn add_split ( splits_per_edge : & mut [ Vec < f64 > ] , i : usize , t : f64 ) {
454
+ splits_per_edge[ i ] . push ( t) ;
451
455
}
456
+ // let mut candidates = Vec::with_capacity(8);
457
+ let mut candidates = BitVec :: new ( edges. len ( ) ) ;
452
458
453
459
// Step 4: Find intersections and record split points
454
460
for ( i, edge) in with_bounding_box. iter ( ) . enumerate ( ) {
455
- let candidates = edge_tree. find ( & edge. 2 ) ;
456
- for & j in & candidates {
461
+ // let candidates = edge_tree.find(&edge.2);
462
+ // let mut quad_candidates: Vec<_> = quad_candidates.into_iter().collect();
463
+ // quad_candidates.sort_unstable();
464
+ // let mut candidates = rtree.query(&edge.2);
465
+ // candidates.sort_unstable();
466
+ // assert_eq!(candidates, quad_candidates);
467
+ candidates. clear ( ) ;
468
+ grid. query ( & edge. 2 , & mut candidates) ;
469
+
470
+ for j in candidates. iter_set_bits ( ) {
457
471
let candidate: & ( PathSegment , u8 ) = & edges[ j] ;
458
472
let include_endpoints = edge. 1 != candidate. 1 || !( candidate. 0 . end ( ) . abs_diff_eq ( edge. 0 . start ( ) , EPS . point ) || candidate. 0 . start ( ) . abs_diff_eq ( edge. 0 . end ( ) , EPS . point ) ) ;
459
473
let intersection = path_segment_intersection ( & edge. 0 , & candidate. 0 , include_endpoints, & EPS ) ;
@@ -462,14 +476,16 @@ fn split_at_intersections(edges: &[MajorGraphEdgeStage1]) -> (Vec<MajorGraphEdge
462
476
add_split ( & mut splits_per_edge, j, t1) ;
463
477
}
464
478
}
465
- edge_tree. insert ( edge. 2 , i) ;
479
+ grid. insert ( & edge. 2 , i) ;
480
+ // edge_tree.insert(edge.2, i);
481
+ // rtree.insert(edge.2, i);
466
482
}
467
483
468
484
// Step 5: Apply splits to create new edges
469
485
let mut new_edges = Vec :: new ( ) ;
470
486
471
487
for ( i, ( seg, parent, _) ) in with_bounding_box. into_iter ( ) . enumerate ( ) {
472
- if let Some ( splits) = splits_per_edge. get ( & i) {
488
+ if let Some ( splits) = splits_per_edge. get ( i) {
473
489
let mut splits = splits. clone ( ) ;
474
490
splits. sort_by ( |a, b| a. partial_cmp ( b) . unwrap ( ) ) ;
475
491
let mut tmp_seg = seg;
@@ -496,7 +512,7 @@ fn split_at_intersections(edges: &[MajorGraphEdgeStage1]) -> (Vec<MajorGraphEdge
496
512
}
497
513
}
498
514
499
- ( new_edges, Some ( total_bounding_box ) )
515
+ new_edges
500
516
}
501
517
502
518
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -539,7 +555,7 @@ fn round_point(point: DVec2) -> I64Vec2 {
539
555
}
540
556
541
557
// TODO: Using 32bit values here might lead to incorrect results when the values collide. Even though this is very unlikely we should think about this case
542
- fn find_vertices ( edges : & [ MajorGraphEdgeStage1 ] , total_bounding_box : Aabb ) -> MajorGraph {
558
+ fn find_vertices ( edges : & [ MajorGraphEdgeStage1 ] ) -> MajorGraph {
543
559
let mut graph = MajorGraph {
544
560
edges : SlotMap :: with_capacity_and_key ( edges. len ( ) * 2 ) ,
545
561
vertices : SlotMap :: with_capacity_and_key ( edges. len ( ) ) ,
@@ -1729,21 +1745,19 @@ impl Display for BooleanError {
1729
1745
pub fn path_boolean ( a : & Path , a_fill_rule : FillRule , b : & Path , b_fill_rule : FillRule , op : PathBooleanOperation ) -> Result < Vec < Path > , BooleanError > {
1730
1746
let mut unsplit_edges: Vec < MajorGraphEdgeStage1 > = a. iter ( ) . map ( segment_to_edge ( 1 ) ) . chain ( b. iter ( ) . map ( segment_to_edge ( 2 ) ) ) . flatten ( ) . collect ( ) ;
1731
1747
1748
+ if unsplit_edges. is_empty ( ) {
1749
+ return Ok ( Vec :: new ( ) ) ;
1750
+ }
1732
1751
split_at_self_intersections ( & mut unsplit_edges) ;
1733
1752
1734
- let ( split_edges, total_bounding_box ) = split_at_intersections ( & unsplit_edges) ;
1753
+ let split_edges = split_at_intersections ( & unsplit_edges) ;
1735
1754
1736
1755
#[ cfg( feature = "logging" ) ]
1737
1756
for ( edge, _) in split_edges. iter ( ) {
1738
1757
eprintln ! ( "{}" , path_to_path_data( & vec![ * edge] , 0.001 ) ) ;
1739
1758
}
1740
1759
1741
- let total_bounding_box = match total_bounding_box {
1742
- Some ( bb) => bb,
1743
- None => return Ok ( Vec :: new ( ) ) , // Input geometry is empty
1744
- } ;
1745
-
1746
- let major_graph = find_vertices ( & split_edges, total_bounding_box) ;
1760
+ let major_graph = find_vertices ( & split_edges) ;
1747
1761
1748
1762
#[ cfg( feature = "logging" ) ]
1749
1763
eprintln ! ( "Major graph:" ) ;
@@ -1829,10 +1843,7 @@ mod tests {
1829
1843
#[ test]
1830
1844
fn test_split_at_intersections ( ) {
1831
1845
let unsplit_edges = unsplit_edges ( ) ;
1832
- let ( split_edges, total_bounding_box) = split_at_intersections ( & unsplit_edges) ;
1833
-
1834
- // Check that we have a valid bounding box
1835
- assert ! ( total_bounding_box. is_some( ) ) ;
1846
+ let split_edges = split_at_intersections ( & unsplit_edges) ;
1836
1847
1837
1848
// Check that we have more edges after splitting (due to intersections)
1838
1849
assert ! ( split_edges. len( ) >= unsplit_edges. len( ) ) ;
@@ -1859,8 +1870,8 @@ mod tests {
1859
1870
fn test_compute_minor ( ) {
1860
1871
// Set up the initial graph
1861
1872
let unsplit_edges = unsplit_edges ( ) ;
1862
- let ( split_edges, total_bounding_box ) = split_at_intersections ( & unsplit_edges) ;
1863
- let major_graph = find_vertices ( & split_edges, total_bounding_box . unwrap ( ) ) ;
1873
+ let split_edges = split_at_intersections ( & unsplit_edges) ;
1874
+ let major_graph = find_vertices ( & split_edges) ;
1864
1875
1865
1876
// Compute minor graph
1866
1877
let minor_graph = compute_minor ( & major_graph) ;
@@ -1914,8 +1925,8 @@ mod tests {
1914
1925
fn test_sort_outgoing_edges_by_angle ( ) {
1915
1926
// Set up the initial graph
1916
1927
let unsplit_edges = unsplit_edges ( ) ;
1917
- let ( split_edges, total_bounding_box ) = split_at_intersections ( & unsplit_edges) ;
1918
- let major_graph = find_vertices ( & split_edges, total_bounding_box . unwrap ( ) ) ;
1928
+ let split_edges = split_at_intersections ( & unsplit_edges) ;
1929
+ let major_graph = find_vertices ( & split_edges) ;
1919
1930
let mut minor_graph = compute_minor ( & major_graph) ;
1920
1931
1921
1932
// Print initial state
0 commit comments