@@ -140,20 +140,20 @@ returns are the fully updated vectors of PolyNodes that represent the rings 'pol
140
140
'poly_b', respectively. This function also returns 'a_idx_list', which at its "ith" index
141
141
stores the index in 'a_list' at which the "ith" intersection point lies.
142
142
=#
143
- function _build_ab_list (:: Type{T} , poly_a, poly_b, delay_cross_f:: F1 , delay_bounce_f:: F2 ; exact) where {T, F1, F2}
143
+ function _build_ab_list (alg :: FosterHormannClipping , :: Type{T} , poly_a, poly_b, delay_cross_f:: F1 , delay_bounce_f:: F2 ; exact) where {T, F1, F2}
144
144
# Make a list for nodes of each polygon
145
- a_list, a_idx_list, n_b_intrs = _build_a_list (T, poly_a, poly_b; exact)
146
- b_list = _build_b_list (T, a_idx_list, a_list, n_b_intrs, poly_b)
145
+ a_list, a_idx_list, n_b_intrs = _build_a_list (alg, T, poly_a, poly_b; exact)
146
+ b_list = _build_b_list (alg, T, a_idx_list, a_list, n_b_intrs, poly_b)
147
147
148
148
# Flag crossings
149
- _classify_crossing! (T, a_list, b_list; exact)
149
+ _classify_crossing! (alg, T, a_list, b_list; exact)
150
150
151
151
# Flag the entry and exits
152
- _flag_ent_exit! (T, GI. LinearRingTrait (), poly_b, a_list, delay_cross_f, Base. Fix2 (delay_bounce_f, true ); exact)
153
- _flag_ent_exit! (T, GI. LinearRingTrait (), poly_a, b_list, delay_cross_f, Base. Fix2 (delay_bounce_f, false ); exact)
152
+ _flag_ent_exit! (alg, T, GI. LinearRingTrait (), poly_b, a_list, delay_cross_f, Base. Fix2 (delay_bounce_f, true ); exact)
153
+ _flag_ent_exit! (alg, T, GI. LinearRingTrait (), poly_a, b_list, delay_cross_f, Base. Fix2 (delay_bounce_f, false ); exact)
154
154
155
155
# Set node indices and filter a_idx_list to just crossing points
156
- _index_crossing_intrs! (a_list, b_list, a_idx_list)
156
+ _index_crossing_intrs! (alg, a_list, b_list, a_idx_list)
157
157
158
158
return a_list, b_list, a_idx_list
159
159
end
@@ -172,7 +172,7 @@ not update the entry and exit flags for a_list.
172
172
The a_idx_list is a list of the indices of intersection points in a_list. The value at
173
173
index i of a_idx_list is the location in a_list where the ith intersection point lies.
174
174
=#
175
- function _build_a_list (:: Type{T} , poly_a, poly_b; exact) where T
175
+ function _build_a_list (alg :: FosterHormannClipping{M, A} , :: Type{T} , poly_a, poly_b; exact) where {T, M, A}
176
176
n_a_edges = _nedge (poly_a)
177
177
a_list = PolyNode{T}[] # list of points in poly_a
178
178
sizehint! (a_list, n_a_edges)
@@ -273,7 +273,7 @@ is needed for clipping using the Greiner-Hormann clipping algorithm.
273
273
Note: after calling this function, b_list is not fully updated. The entry/exit flags still
274
274
need to be updated. However, the neighbor value in a_list is now updated.
275
275
=#
276
- function _build_b_list (:: Type{T} , a_idx_list, a_list, n_b_intrs, poly_b) where T
276
+ function _build_b_list (alg :: FosterHormannClipping{M, A} , :: Type{T} , a_idx_list, a_list, n_b_intrs, poly_b) where {T, M, A}
277
277
# Sort intersection points by insertion order in b_list
278
278
sort! (a_idx_list, by = x-> a_list[x]. neighbor + a_list[x]. fracs[2 ])
279
279
# Initialize needed values and lists
@@ -333,7 +333,7 @@ chain is crossing and delayed otherwise and all middle points are marked as boun
333
333
Additionally, the start and end points of the chain are marked as endpoints using the
334
334
endpoints field.
335
335
=#
336
- function _classify_crossing! (:: Type{T} , a_list, b_list; exact) where T
336
+ function _classify_crossing! (alg :: FosterHormannClipping{M, A} , :: Type{T} , a_list, b_list; exact) where {T, M, A}
337
337
napts = length (a_list)
338
338
nbpts = length (b_list)
339
339
# start centered on last point
@@ -357,7 +357,7 @@ function _classify_crossing!(::Type{T}, a_list, b_list; exact) where T
357
357
a_next_is_b_prev = a_next. inter && equals (a_next, b_prev)
358
358
a_next_is_b_next = a_next. inter && equals (a_next, b_next)
359
359
# determine which side of a segments the p points are on
360
- b_prev_side, b_next_side = _get_sides (b_prev, b_next, a_prev, curr_pt, a_next,
360
+ b_prev_side, b_next_side = _get_sides (#= TODO : alg.manifold, =# b_prev, b_next, a_prev, curr_pt, a_next,
361
361
i, j, a_list, b_list; exact)
362
362
# no sides overlap
363
363
if ! a_prev_is_b_prev && ! a_prev_is_b_next && ! a_next_is_b_prev && ! a_next_is_b_next
@@ -499,7 +499,7 @@ all points are intersection points, find the first element that either is the en
499
499
or a crossing point that isn't in a chain. Then take the midpoint of this point and the next
500
500
point in the list and perform the in/out check. If none of these points exist, return
501
501
a `next_idx` of `nothing`. =#
502
- function _pt_off_edge_status (:: Type{T} , pt_list, poly, npts; exact) where T
502
+ function _pt_off_edge_status (alg :: FosterHormannClipping{M, A} , :: Type{T} , pt_list, poly, npts; exact) where {T, M, A}
503
503
start_idx, is_non_intr_pt = findfirst (_is_not_intr, pt_list), true
504
504
if isnothing (start_idx)
505
505
start_idx, is_non_intr_pt = findfirst (_next_edge_off, pt_list), false
@@ -511,7 +511,7 @@ function _pt_off_edge_status(::Type{T}, pt_list, poly, npts; exact) where T
511
511
else
512
512
(pt_list[start_idx]. point .+ pt_list[next_idx]. point) ./ 2
513
513
end
514
- start_status = ! _point_filled_curve_orientation (start_pt, poly; in = true , on = false , out = false , exact)
514
+ start_status = ! _point_filled_curve_orientation (alg . manifold, start_pt, poly; in = true , on = false , out = false , exact)
515
515
return next_idx, start_status
516
516
end
517
517
# Check if a PolyNode is an intersection point
@@ -537,10 +537,10 @@ bounce will be the same.
537
537
538
538
Used for clipping polygons by other polygons.
539
539
=#
540
- function _flag_ent_exit! (:: Type{T} , :: GI.LinearRingTrait , poly, pt_list, delay_cross_f, delay_bounce_f; exact) where T
540
+ function _flag_ent_exit! (alg :: FosterHormannClipping{M, A} , :: Type{T} , :: GI.LinearRingTrait , poly, pt_list, delay_cross_f, delay_bounce_f; exact) where {T, M, A}
541
541
npts = length (pt_list)
542
542
# Find starting index if there is one
543
- next_idx, status = _pt_off_edge_status (T, pt_list, poly, npts; exact)
543
+ next_idx, status = _pt_off_edge_status (alg, T, pt_list, poly, npts; exact)
544
544
isnothing (next_idx) && return
545
545
start_idx = next_idx - 1
546
546
# Loop over points and mark entry and exit status
@@ -560,7 +560,7 @@ function _flag_ent_exit!(::Type{T}, ::GI.LinearRingTrait, poly, pt_list, delay_c
560
560
else # delayed bouncing
561
561
next_idx = ii < npts ? (ii + 1 ) : 1
562
562
next_val = (curr_pt. point .+ pt_list[next_idx]. point) ./ 2
563
- pt_in_poly = _point_filled_curve_orientation (next_val, poly; in = true , on = false , out = false , exact)
563
+ pt_in_poly = _point_filled_curve_orientation (alg . manifold, next_val, poly; in = true , on = false , out = false , exact)
564
564
#= start and end crossing status are the same and depend on if adjacent
565
565
edges of pt_list are within poly =#
566
566
start_crossing = delay_bounce_f (pt_in_poly)
@@ -588,8 +588,8 @@ returns false. Used for cutting polygons by lines.
588
588
589
589
Assumes that the first point is outside of the polygon and not on an edge.
590
590
=#
591
- function _flag_ent_exit! (:: GI.LineTrait , poly, pt_list; exact)
592
- status = ! _point_filled_curve_orientation (pt_list[1 ]. point, poly; in = true , on = false , out = false , exact)
591
+ function _flag_ent_exit! (alg :: FosterHormannClipping{M, A} , :: GI.LineTrait , poly, pt_list; exact) where {M, A}
592
+ status = ! _point_filled_curve_orientation (#= TODO : alg.manifold =# pt_list[1 ]. point, poly; in = true , on = false , out = false , exact)
593
593
# Loop over points and mark entry and exit status
594
594
for (ii, curr_pt) in enumerate (pt_list)
595
595
if curr_pt. crossing
602
602
603
603
#= Filters a_idx_list to just include crossing points and sets the index of all crossing
604
604
points (which element they correspond to within a_idx_list). =#
605
- function _index_crossing_intrs! (a_list, b_list, a_idx_list)
605
+ function _index_crossing_intrs! (alg :: FosterHormannClipping{M, A} , a_list, b_list, a_idx_list) where {M, A}
606
606
filter! (x -> a_list[x]. crossing, a_idx_list)
607
607
for (i, a_idx) in enumerate (a_idx_list)
608
608
curr_node = a_list[a_idx]
@@ -631,7 +631,7 @@ A list of GeoInterface polygons is returned from this function.
631
631
Note: `poly_a` and `poly_b` are temporary inputs used for debugging and can be removed
632
632
eventually.
633
633
=#
634
- function _trace_polynodes (:: Type{T} , a_list, b_list, a_idx_list, f_step, poly_a, poly_b) where T
634
+ function _trace_polynodes (alg :: FosterHormannClipping{M, A} , :: Type{T} , a_list, b_list, a_idx_list, f_step, poly_a, poly_b) where {T, M, A}
635
635
n_a_pts, n_b_pts = length (a_list), length (b_list)
636
636
total_pts = n_a_pts + n_b_pts
637
637
n_cross_pts = length (a_idx_list)
@@ -707,7 +707,7 @@ or they are separate polygons with no intersection (other than an edge or point)
707
707
Return two booleans that represent if a is inside b (potentially with shared edges / points)
708
708
and visa versa if b is inside of a.
709
709
=#
710
- function _find_non_cross_orientation (a_list, b_list, a_poly, b_poly; exact)
710
+ function _find_non_cross_orientation (m :: M , a_list, b_list, a_poly, b_poly; exact) where {M <: Manifold }
711
711
non_intr_a_idx = findfirst (x -> ! x. inter, a_list)
712
712
non_intr_b_idx = findfirst (x -> ! x. inter, b_list)
713
713
#= Determine if non-intersection point is in or outside of polygon - if there isn't A
@@ -721,14 +721,17 @@ function _find_non_cross_orientation(a_list, b_list, a_poly, b_poly; exact)
721
721
return a_in_b, b_in_a
722
722
end
723
723
724
+ _find_non_cross_orientation (alg:: FosterHormannClipping{M} , a_list, b_list, a_poly, b_poly; exact) where {M <: Manifold } =
725
+ _find_non_cross_orientation (alg. manifold, a_list, b_list, a_poly, b_poly; exact)
726
+
724
727
#=
725
728
_add_holes_to_polys!(::Type{T}, return_polys, hole_iterator, remove_poly_idx; exact)
726
729
727
730
The holes specified by the hole iterator are added to the polygons in the return_polys list.
728
731
If this creates more polygons, they are added to the end of the list. If this removes
729
732
polygons, they are removed from the list
730
733
=#
731
- function _add_holes_to_polys! (:: Type{T} , return_polys, hole_iterator, remove_poly_idx; exact) where T
734
+ function _add_holes_to_polys! (alg :: FosterHormannClipping{M, A} , :: Type{T} , return_polys, hole_iterator, remove_poly_idx; exact) where {T, M, A}
732
735
n_polys = length (return_polys)
733
736
remove_hole_idx = Int[]
734
737
# Remove set of holes from all polygons
@@ -741,17 +744,17 @@ function _add_holes_to_polys!(::Type{T}, return_polys, hole_iterator, remove_pol
741
744
curr_poly = return_polys[j]
742
745
remove_poly_idx[j] && continue
743
746
curr_poly_ext = GI. nhole (curr_poly) > 0 ? GI. Polygon (StaticArrays. SVector (GI. getexterior (curr_poly))) : curr_poly
744
- in_ext, on_ext, out_ext = _line_polygon_interactions (curr_hole, curr_poly_ext; exact, closed_line = true )
747
+ in_ext, on_ext, out_ext = _line_polygon_interactions (#= TODO : alg.manifold =# curr_hole, curr_poly_ext; exact, closed_line = true )
745
748
if in_ext # hole is at least partially within the polygon's exterior
746
- new_hole, new_hole_poly, n_new_pieces = _combine_holes! (T, curr_hole, curr_poly, return_polys, remove_hole_idx)
749
+ new_hole, new_hole_poly, n_new_pieces = _combine_holes! (alg, T, curr_hole, curr_poly, return_polys, remove_hole_idx)
747
750
if n_new_pieces > 0
748
751
append! (remove_poly_idx, falses (n_new_pieces))
749
752
n_new_per_poly += n_new_pieces
750
753
end
751
754
if ! on_ext && ! out_ext # hole is completely within exterior
752
755
push! (curr_poly. geom, new_hole)
753
756
else # hole is partially within and outside of polygon's exterior
754
- new_polys = difference (curr_poly_ext, new_hole_poly, T; target= GI. PolygonTrait ())
757
+ new_polys = difference (alg, curr_poly_ext, new_hole_poly, T; target= GI. PolygonTrait ())
755
758
n_new_polys = length (new_polys) - 1
756
759
# replace original
757
760
curr_poly. geom[1 ] = GI. getexterior (new_polys[1 ])
@@ -763,7 +766,7 @@ function _add_holes_to_polys!(::Type{T}, return_polys, hole_iterator, remove_pol
763
766
end
764
767
end
765
768
# polygon is completely within hole
766
- elseif coveredby (curr_poly_ext, GI. Polygon (StaticArrays. SVector (curr_hole)))
769
+ elseif coveredby (#= TODO : alg.manifold =# curr_poly_ext, GI. Polygon (StaticArrays. SVector (curr_hole)))
767
770
remove_poly_idx[j] = true
768
771
end
769
772
end
@@ -788,16 +791,16 @@ are in the "main" polygon or in one of these new pieces and moved accordingly.
788
791
If the holes don't touch or curr_poly has no holes, then new_hole is returned without any
789
792
changes.
790
793
=#
791
- function _combine_holes! (:: Type{T} , new_hole, curr_poly, return_polys, remove_hole_idx) where T
794
+ function _combine_holes! (alg :: FosterHormannClipping{M, A} , :: Type{T} , new_hole, curr_poly, return_polys, remove_hole_idx) where {T, M, A}
792
795
n_new_polys = 0
793
796
empty! (remove_hole_idx)
794
797
new_hole_poly = GI. Polygon (StaticArrays. SVector (new_hole))
795
798
# Combine any existing holes in curr_poly with new hole
796
799
for (k, old_hole) in enumerate (GI. gethole (curr_poly))
797
800
old_hole_poly = GI. Polygon (StaticArrays. SVector (old_hole))
798
- if intersects (new_hole_poly, old_hole_poly)
801
+ if intersects (#= TODO : alg.manifold =# new_hole_poly, old_hole_poly)
799
802
# If the holes intersect, combine them into a bigger hole
800
- hole_union = union (new_hole_poly, old_hole_poly, T; target = GI. PolygonTrait ())[1 ]
803
+ hole_union = union (alg, new_hole_poly, old_hole_poly, T; target = GI. PolygonTrait ())[1 ]
801
804
push! (remove_hole_idx, k + 1 )
802
805
new_hole = GI. getexterior (hole_union)
803
806
new_hole_poly = GI. Polygon (StaticArrays. SVector (new_hole))
826
829
827
830
#= Remove collinear edge points, other than the first and last edge vertex, to simplify
828
831
polygon - including both the exterior ring and any holes=#
829
- function _remove_collinear_points! (polys, remove_idx, poly_a, poly_b)
832
+ function _remove_collinear_points! (alg :: FosterHormannClipping{M, A} , polys, remove_idx, poly_a, poly_b) where {M, A}
830
833
for (i, poly) in Iterators. reverse (enumerate (polys))
831
834
for (j, ring) in Iterators. reverse (enumerate (GI. getring (poly)))
832
835
n = length (ring. geom)
@@ -844,6 +847,7 @@ function _remove_collinear_points!(polys, remove_idx, poly_a, poly_b)
844
847
else
845
848
p3 = p
846
849
# check if p2 is approximately on the edge formed by p1 and p3 - remove if so
850
+ # TODO : make this manifold aware
847
851
if Predicates. orient (p1, p2, p3; exact = False ()) == 0
848
852
remove_idx[i - 1 ] = true
849
853
end
0 commit comments