1
+
2
+
3
+ export Line
4
+
5
+
6
+
7
+
8
+ # # Standard interval
9
+
10
+
11
+
12
+ # angle is π*a where a is (false==0) and (true==1)
13
+ # or ranges from (-1,1]. We use 1 as 1==true.
14
+
15
+ """
16
+ Line{a}(c)
17
+
18
+ represents the line at angle `a` in the complex plane, centred at `c`.
19
+ """
20
+ struct Line{angle,T<: Number } <: SegmentDomain{T}
21
+ center:: T
22
+ α:: Float64
23
+ β:: Float64
24
+
25
+ # TODO get this inner constructor working again.
26
+ Line {angle,T} (c,α,β) where {angle,T} = new {angle,T} (c,α,β)
27
+ Line {angle,T} (c) where {angle,T} = new {angle,T} (c,- 1. ,- 1. )
28
+ Line {angle,T} () where {angle,T} = new {angle,T} (zero (T),- 1. ,- 1. )
29
+ end
30
+
31
+ const RealLine{T} = Union{Line{false ,T},Line{true ,T}}
32
+
33
+ Line {a} (c,α,β) where {a} = Line {a,typeof(c)} (c,α,β)
34
+ Line {a} (c:: Number ) where {a} = Line {a,typeof(c)} (c)
35
+ Line {a} () where {a} = Line {a,Float64} ()
36
+
37
+ angle (d:: Line{a} ) where {a} = a* π
38
+
39
+ reverseorientation (d:: Line{true} ) = Line {false} (d. center,d. β,d. α)
40
+ reverseorientation (d:: Line{false} ) = Line {true} (d. center,d. β,d. α)
41
+ reverseorientation (d:: Line{a} ) where {a} = Line {a-1} (d. center,d. β,d. α)
42
+
43
+ # ensure the angle is always in (-1,1]
44
+ Line (c,a,α,β) = Line {mod(a/π-1,-2)+1,typeof(c)} (c,α,β)
45
+ Line (c,a) = Line (c,a,- 1. ,- 1. )
46
+ # true is negative orientation, false is positive orientation
47
+ # this is because false==0 and we take angle=0
48
+ Line (b:: Bool ) = Line {b} ()
49
+ Line () = Line (false )
50
+
51
+
52
+ isambiguous (d:: Line )= isnan (d. center)
53
+ convert (:: Type{Domain{T}} ,d:: Line{a} ) where {a,T<: Number } = Line {a,T} (d. center, d. α, d. β)
54
+ convert (:: Type{Line{a,T}} ,:: AnyDomain ) where {a,T<: Number } = Line {a,T} (NaN )
55
+ convert (:: Type{IT} ,:: AnyDomain ) where {IT<: Line }= Line (NaN ,NaN )
56
+
57
+ # # Map interval
58
+
59
+
60
+ # #TODO non-1 alpha,beta
61
+
62
+ isempty (:: Line ) = false
63
+
64
+ function line_tocanonical (α,β,x)
65
+ @assert α== β== - 1. || α== β== - .5
66
+
67
+ if α== β== - 1.
68
+ 2 x/ (1 + sqrt (1 + 4 x^ 2 ))
69
+ elseif α== β== - .5
70
+ x/ sqrt (1 + x^ 2 )
71
+ end
72
+ end
73
+
74
+ function line_tocanonicalD (α,β,x)
75
+ @assert α== β== - 1. || α== β== - .5
76
+
77
+ if α== β== - 1.
78
+ 2 / (1 + 4 x^ 2 + sqrt (1 + 4 x^ 2 ))
79
+ elseif α== β== - 0.5
80
+ (1 + x^ 2 )^ (- 3 / 2 )
81
+ end
82
+ end
83
+ function line_fromcanonical (α,β,x)
84
+ # TODO : why is this consistent?
85
+ if α== β== - 1.
86
+ x/ (1 - x^ 2 )
87
+ else
88
+ x* (1 + x)^ α* (1 - x)^ β
89
+ end
90
+ end
91
+ function line_fromcanonicalD (α,β,x)
92
+ if α== β== - 1.
93
+ (1 + x^ 2 )/ (1 - x^ 2 )^ 2
94
+ else
95
+ (1 - (β- α)x - (β+ α+ 1 )x^ 2 )* (1 + x)^ (α- 1 )* (1 - x)^ (β- 1 )
96
+ end
97
+ end
98
+
99
+ function line_invfromcanonicalD (α,β,x)
100
+ if α== β== - 1.
101
+ (1 - x^ 2 )^ 2 / (1 + x^ 2 )
102
+ else
103
+ 1 / (1 - (β- α)x - (β+ α+ 1 )x^ 2 )* (1 + x)^ (1 - α)* (1 - x)^ (1 - β)
104
+ end
105
+ end
106
+
107
+
108
+ tocanonical (d:: Line ,x) = line_tocanonical (d. α,d. β,cis (- angle (d)).* (x- d. center))
109
+ tocanonical (d:: Line{false} ,x) = line_tocanonical (d. α,d. β,x- d. center)
110
+ tocanonical (d:: Line{true} ,x) = line_tocanonical (d. α,d. β,d. center- x)
111
+
112
+ tocanonicalD (d:: Line ,x) = cis (- angle (d)).* line_tocanonicalD (d. α,d. β,cis (- angle (d)).* (x- d. center))
113
+ tocanonicalD (d:: Line{false} ,x) = line_tocanonicalD (d. α,d. β,x- d. center)
114
+ tocanonicalD (d:: Line{true} ,x) = - line_tocanonicalD (d. α,d. β,d. center- x)
115
+
116
+ fromcanonical (d:: Line ,x) = cis (angle (d))* line_fromcanonical (d. α,d. β,x)+ d. center
117
+ fromcanonical (d:: Line{false} ,x) = line_fromcanonical (d. α,d. β,x)+ d. center
118
+ fromcanonical (d:: Line{true} ,x) = - line_fromcanonical (d. α,d. β,x)+ d. center
119
+
120
+ fromcanonicalD (d:: Line ,x) = cis (angle (d))* line_fromcanonicalD (d. α,d. β,x)
121
+ fromcanonicalD (d:: Line{false} ,x) = line_fromcanonicalD (d. α,d. β,x)
122
+ fromcanonicalD (d:: Line{true} ,x) = - line_fromcanonicalD (d. α,d. β,x)
123
+
124
+ invfromcanonicalD (d:: Line ,x) = cis (- angle (d))* line_invfromcanonicalD (d. α,d. β,x)
125
+ invfromcanonicalD (d:: Line{false} ,x) = line_invfromcanonicalD (d. α,d. β,x)
126
+ invfromcanonicalD (d:: Line{true} ,x) = - line_invfromcanonicalD (d. α,d. β,x)
127
+
128
+
129
+
130
+
131
+
132
+
133
+ == (d:: Line{a} ,m:: Line{a} ) where {a} = d. center == m. center && d. β == m. β && d. α == m. α
134
+
135
+
136
+
137
+ # algebra
138
+ * (c:: Real ,d:: Line{false} ) = Line {sign(c)>0 ? false : true} (isapprox (d. center,0 ) ? d. center : c* d. center,d. α,d. β)
139
+ * (c:: Real ,d:: Line{true} ) = Line {sign(c)>0 ? true : false} (isapprox (d. center,0 ) ? d. center : c* d. center,d. α,d. β)
140
+ * (c:: Number ,d:: Line ) = Line (isapprox (d. center,0 ) ? d. center : c* d. center,angle (d)+ angle (c),d. α,d. β)
141
+ * (d:: Line ,c:: Number ) = c* d
142
+ for OP in (:+ ,:- )
143
+ @eval begin
144
+ $ OP (c:: Number ,d:: Line{a} ) where {a} = Line {a} ($ OP (c,d. center),d. α,d. β)
145
+ $ OP (d:: Line{a} ,c:: Number ) where {a} = Line {a} ($ OP (d. center,c),d. α,d. β)
146
+ end
147
+ end
148
+
149
+
150
+
151
+
152
+
153
+
154
+ # algebra
155
+ arclength (d:: Line ) = Inf
156
+ leftendpoint (d:: Line ) = - Inf
157
+ rightendpoint (d:: Line ) = Inf
158
+ complexlength (d:: Line ) = Inf
159
+
160
+ # # vectorized
161
+
162
+
163
+ function convert (:: Type{Line} ,d:: ClosedInterval )
164
+ a,b= d. left,d. right
165
+ @assert abs (a) == abs (b) == Inf
166
+
167
+ if isa (a,Real) && isa (b,Real)
168
+ if a== Inf
169
+ @assert b== - Inf
170
+ Line (true )
171
+ else
172
+ @assert a== - Inf && b== Inf
173
+ Line (false )
174
+ end
175
+ elseif abs (real (a)) < Inf
176
+ @assert real (a)== real (b)
177
+ @assert sign (imag (a))== - sign (imag (b))
178
+
179
+ Line (real (b),angle (b))
180
+ elseif isnan (real (a)) && isnan (real (b)) # hack for -im*Inf
181
+ Line ([imag (a)* im,imag (b)* im])
182
+ elseif isnan (real (a)) # hack for -im*Inf
183
+ Line ([real (b)+ imag (a)* im,b])
184
+ elseif isnan (real (b)) # hack for -im*Inf
185
+ Line ([a,real (a)+ imag (b)* im])
186
+ elseif abs (imag (a)) < Inf
187
+ @assert imag (a)== imag (b)
188
+ @assert sign (real (a))== - sign (real (b))
189
+
190
+ Line (imag (b),angle (b))
191
+ else
192
+ @assert angle (b) == - angle (a)
193
+
194
+ Line (0. ,angle (b))
195
+ end
196
+ end
197
+
198
+
199
+
200
+ issubset (a:: IntervalOrSegment , b:: Line ) = leftendpoint (a)∈ b && rightendpoint (a)∈ b
201
+ issubset (a:: Ray{angle} , b:: Line{angle} ) where angle = leftendpoint (a) ∈ b
202
+ issubset (a:: Ray{true} , b:: Line{false} ) = true
203
+ issubset (a:: Ray{false} , b:: Line{true} ) = true
204
+
205
+ function intersect (a:: Union{Interval,Segment,Ray} ,b:: Line )
206
+ @assert a ⊆ b
207
+ a
208
+ end
209
+
210
+ function union (a:: Union{Interval,Segment,Ray} ,b:: Line )
211
+ @assert a ⊆ b
212
+ b
213
+ end
214
+
215
+ intersect (b:: Line ,a:: Union{Interval,Segment,Ray} ) = intersect (a,b)
216
+ union (b:: Line ,a:: Union{Interval,Segment,Ray} ) = union (a,b)
217
+
218
+
219
+ function setdiff (b:: Line ,a:: Segment )
220
+ @assert a ⊆ b
221
+ if leftendpoint (a)> rightendpoint (a)
222
+ b\ reverseorientation (a)
223
+ else
224
+ Ray ([leftendpoint (b),leftendpoint (a)]) ∪ Ray ([rightendpoint (a),rightendpoint (b)])
225
+ end
226
+ end
0 commit comments