Skip to content

Commit 1c3c42b

Browse files
committed
change Rect() to generate NaN origin, 0 widths
1 parent 1a1f341 commit 1c3c42b

File tree

2 files changed

+37
-24
lines changed

2 files changed

+37
-24
lines changed

src/primitives/rectangles.jl

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,9 @@ Rect() = Rect{2,Float32}()
5656
RectT{T}() where {T} = Rect{2,T}()
5757
Rect{N}() where {N} = Rect{N,Float32}()
5858

59-
function Rect{N,T}() where {T,N}
60-
# empty constructor such that update will always include the first point
61-
return Rect{N,T}(Vec{N,T}(typemax(T)), Vec{N,T}(typemin(T)))
62-
end
59+
Rect{N,T}() where {T <: AbstractFloat,N} = Rect{N,T}(Vec{N,T}(NaN), Vec{N,T}(0))
60+
Rect{N,T}() where {T, N} = throw(MethodError(Rect{N,T}, tuple()))
61+
# TODO: what about integers and other types? No reasonable default?
6362

6463
# Rect(numbers...)
6564
Rect(args::Vararg{Number, N}) where {N} = Rect{div(N, 2), promote_type(typeof.(args)...)}(args...)
@@ -302,16 +301,19 @@ end
302301
"""
303302
isempty(h::Rect)
304303
305-
Return `true` if any of the widths of `h` are negative.
304+
Return `true` if any of the widths of `h` are zero or negative.
306305
"""
307-
Base.isempty(h::Rect{N,T}) where {N,T} = any(<(zero(T)), h.widths)
306+
Base.isempty(h::Rect{N,T}) where {N,T} = any(<=(zero(T)), h.widths)
307+
Base.isnan(r::Rect) = isnan(origin(r)) || isnan(widths(r))
308308

309309
"""
310310
union(r1::Rect{N}, r2::Rect{N})
311311
312312
Returns a new `Rect{N}` which contains both r1 and r2.
313313
"""
314314
function Base.union(h1::Rect{N}, h2::Rect{N}) where {N}
315+
isnan(h1) && return h2
316+
isnan(h2) && return h1
315317
m = min.(minimum(h1), minimum(h2))
316318
mm = max.(maximum(h1), maximum(h2))
317319
return Rect{N}(m, mm - m)
@@ -332,6 +334,7 @@ end
332334
Perform a intersection between two Rects.
333335
"""
334336
function Base.intersect(h1::Rect{N}, h2::Rect{N}) where {N}
337+
isnan(h1) || isnan(h2) && return Rect{N}()
335338
m = max.(minimum(h1), minimum(h2))
336339
mm = min.(maximum(h1), maximum(h2))
337340
return Rect{N}(m, mm - m)
@@ -342,6 +345,8 @@ function update(b::Rect{N,T}, v::VecTypes{N,T2}) where {N,T,T2}
342345
end
343346

344347
function update(b::Rect{N,T}, v::VecTypes{N,T}) where {N,T}
348+
isnan(b) && return Rect{N, T}(v, Vec{N, T}(0))
349+
345350
m = min.(minimum(b), v)
346351
maxi = maximum(b)
347352
mm = if any(isnan, maxi)

test/geometrytypes.jl

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,36 @@ end
7878

7979
@testset "HyperRectangles" begin
8080
@testset "Constructors" begin
81-
# TODO: Do these actually make sense?
82-
# Should they not be Rect(NaN..., 0...)?
8381
@testset "Empty Constructors" begin
82+
function nan_equal(r1::Rect, r2::Rect)
83+
o1 = origin(r1); o2 = origin(r2)
84+
return ((isnan(o1) && isnan(o2)) || (o1 == o2)) && (widths(r1) == widths(r2))
85+
end
86+
8487
for constructor in [Rect, Rect{2}, Rect2, RectT, Rect2f]
85-
@test constructor() == Rect{2, Float32}(Inf, Inf, -Inf, -Inf)
88+
@test nan_equal(constructor(), Rect{2, Float32}(NaN, NaN, 0, 0))
8689
end
8790
for constructor in [Rect{3}, Rect3, Rect3f]
88-
@test constructor() == Rect{3, Float32}((Inf, Inf, Inf), (-Inf, -Inf, -Inf))
91+
@test nan_equal(constructor(), Rect{3, Float32}((NaN, NaN, NaN), (0, 0, 0)))
8992
end
9093

91-
for T in [UInt32, Int16, Float64]
94+
for T in [UInt32, Int16]
9295
a = typemax(T)
9396
b = typemin(T)
9497
for constructor in [Rect{2, T}, Rect2{T}, RectT{T, 2}]
95-
@test constructor() == Rect{2, T}(a, a, b, b)
98+
@test_throws MethodError constructor()
9699
end
97100
for constructor in [Rect{3, T}, Rect3{T}, RectT{T, 3}]
98-
@test constructor() == Rect{3, T}(Point(a, a, a), Vec(b, b, b))
101+
@test_throws MethodError constructor()
99102
end
100103
end
104+
105+
for constructor in [Rect{2, Float64}, Rect2{Float64}, RectT{Float64, 2}]
106+
@test nan_equal(constructor(), Rect{2, Float64}(NaN, NaN, 0, 0))
107+
end
108+
for constructor in [Rect{3, Float64}, Rect3{Float64}, RectT{Float64, 3}]
109+
@test nan_equal(constructor(), Rect{3, Float64}(Point3(NaN), Vec3(0)))
110+
end
101111
end
102112

103113
@testset "Constructor arg conversions" begin
@@ -182,19 +192,17 @@ end
182192
end
183193
end
184194

185-
# TODO: These don't really make sense...
186195
r = Rect2f()
187-
@test origin(r) == Vec(Inf, Inf)
188-
@test minimum(r) == Vec(Inf, Inf)
196+
@test isnan(origin(r))
197+
@test isnan(minimum(r))
189198
@test isnan(maximum(r))
190-
@test width(r) == -Inf
191-
@test height(r) == -Inf
192-
@test widths(r) == Vec(-Inf, -Inf)
193-
@test area(r) == Inf
194-
@test volume(r) == Inf
195-
# TODO: broken? returns NaN widths
196-
# @test union(r, Rect2f(1,1,2,2)) == Rect2f(1,1,2,2)
197-
# @test union(Rect2f(1,1,2,2), r) == Rect2f(1,1,2,2)
199+
@test width(r) == 0
200+
@test height(r) == 0
201+
@test widths(r) == Vec2(0)
202+
@test area(r) == 0
203+
@test volume(r) == 0
204+
@test union(r, Rect2f(1,1,2,2)) == Rect2f(1,1,2,2)
205+
@test union(Rect2f(1,1,2,2), r) == Rect2f(1,1,2,2)
198206
@test update(r, Vec2f(1,1)) == Rect2f(1,1,0,0)
199207

200208
a = Rect(Vec(0, 1), Vec(2, 3))

0 commit comments

Comments
 (0)