1
1
"""
2
- Returns a list of pairs (interval, label)
3
- label is 1 if the interval is *excluded* from the setdiff
4
- label is 0 if the interval is included in the setdiff
5
- label is -1 if the intersection of the two intervals was empty
2
+ _setdiff(x::Interval{T}, y::Interval{T})
3
+
4
+ Computes the set difference x\\ y and always returns a tuple of two intervals.
5
+ If the set difference is only one interval or is empty, then the returned tuple contains 1
6
+ or 2 empty intervals.
6
7
"""
7
- function labelled_setdiff (x:: Interval{T} , y:: Interval{T} ) where T
8
+ function _setdiff (x:: Interval{T} , y:: Interval{T} ) where T
8
9
intersection = x ∩ y
9
10
10
- isempty (intersection) && return [ (x, - 1 )]
11
- intersection == x && return [(x, 1 )]
11
+ isempty (intersection) && return (x, emptyinterval (T))
12
+ intersection == x && return ( emptyinterval (T), emptyinterval (T)) # x is subset of y; setdiff is empty
12
13
13
- x. lo == intersection. lo && return [(intersection, 1 ), ( Interval (intersection. hi, x. hi), 0 )]
14
- x. hi == intersection. hi && return [(intersection, 1 ), ( Interval (x. lo, intersection. lo), 0 )]
14
+ x. lo == intersection. lo && return ( Interval (intersection. hi, x. hi), emptyinterval (T))
15
+ x. hi == intersection. hi && return ( Interval (x. lo, intersection. lo), emptyinterval (T))
15
16
16
- return [(y, 1 ),
17
- (Interval (x. lo, y. lo), 0 ),
18
- (Interval (y. hi, x. hi), 0 )]
17
+ return (Interval (x. lo, y. lo), Interval (y. hi, x. hi))
19
18
20
19
end
21
20
22
- # function setdiff{N,T}(A::IntervalBox{N,T}, B::IntervalBox{N,T})
23
- # X = [labelled_setdiff(a,b) for (a, b) in zip(A, B)]
24
- # lengths = map(length, X)
25
- # index = ones(N)
26
- #
27
- # # index[j] represents which set we are looking at in direction j
28
- # ``
29
- #
30
- # while index[1] <= N
31
- # current_direction = 1
32
- # current_piece = [ X[1][index[1]] ]
33
- #
34
- # end
35
- # end
36
21
37
22
"""
38
23
setdiff(A::IntervalBox{N,T}, B::IntervalBox{N,T})
@@ -44,65 +29,21 @@ Algorithm: Start from the total overlap (in all directions);
44
29
expand each direction in turn.
45
30
"""
46
31
function setdiff (A:: IntervalBox{N,T} , B:: IntervalBox{N,T} ) where {N,T}
47
- X = [labelled_setdiff (a, b) for (a, b) in zip (A. v, B. v)]
48
- # ordered such that the first in each is the excluded interval
49
-
50
- first = [ i[1 ] for i in X ]
51
- labels = [i[2 ] for i in first]
52
-
53
- any (labels .== - 1 ) && return [A] # no overlap
54
-
55
- # @assert all(labels .== 1)
56
-
57
- excluded = [i[1 ] for i in first]
58
32
59
- result_list = IntervalBox{N,T}[]
60
-
61
- for dimension in N: - 1 : 1
62
- for which in X[dimension][2 : end ]
63
- excluded[dimension] = which[1 ]
64
- push! (result_list,
65
- IntervalBox (excluded[1 : dimension]. .. , A[dimension+ 1 : N]. .. ))
33
+ intersection = A ∩ B
34
+ isempty (intersection) && return [A]
35
+
36
+ result_list = fill (IntervalBox (emptyinterval (T), N), 2 * N)
37
+ offset = 0
38
+ x = A. v
39
+ @inbounds for i = 1 : N
40
+ tmp = _setdiff (A[i], B[i])
41
+ @inbounds for j = 1 : 2
42
+ x = setindex (x, tmp[j], i)
43
+ result_list[offset+ j] = IntervalBox {N, T} (x)
66
44
end
45
+ offset += 2
46
+ x = setindex (x, intersection[i], i)
67
47
end
68
-
69
- result_list
70
-
48
+ filter! (! isempty, result_list)
71
49
end
72
-
73
-
74
- # """
75
- # setdiff(A::IntervalBox{2,T}, B::IntervalBox{2,T})
76
- #
77
- # Returns a vector of `IntervalBox`es that are in the set difference `A \ B`,
78
- # i.e. the set of `x` that are in `A` but not in `B`.
79
- # """
80
- # function setdiff{T}(A::IntervalBox{2,T}, B::IntervalBox{2,T})
81
- # X = labelled_setdiff(A[1], B[1])
82
- # Y = labelled_setdiff(A[2], B[2])
83
- #
84
- # results_list = typeof(A)[]
85
- #
86
- # for (x, label) in X
87
- # label == -1 && return [A] # intersection in one direction empty, so total intersection empty
88
- #
89
- # if label == 0
90
- # push!(results_list, IntervalBox(x, A[2]))
91
- # continue
92
- # end
93
- #
94
- # # label is 1 here, so there is some intersection in the x direction
95
- # for (y, label) in Y
96
- # label == -1 && return [A]
97
- #
98
- # if label == 0
99
- # push!(results_list, IntervalBox(x, y))
100
- # continue
101
- # end
102
- #
103
- # # label == 1: exclude this box since all labels are 1
104
- # end
105
- # end
106
- #
107
- # return results_list
108
- # end
0 commit comments