-
Notifications
You must be signed in to change notification settings - Fork 26
/
iterators.jl
92 lines (81 loc) · 2.52 KB
/
iterators.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
function Base.iterate(layer::AbstractFeatureLayer, state::Int=0)
layer.ptr == C_NULL && return nothing
state == 0 && resetreading!(layer)
ptr = GDAL.ogr_l_getnextfeature(layer.ptr)
if ptr == C_NULL
resetreading!(layer)
return nothing
else
return (Feature(ptr), state+1)
end
end
Base.eltype(layer::AbstractFeatureLayer) = Feature
Base.length(layer::AbstractFeatureLayer) = nfeature(layer, true)
struct BlockIterator
rows::Cint
cols::Cint
ni::Cint
nj::Cint
n::Cint
xbsize::Cint
ybsize::Cint
end
function blocks(raster::AbstractRasterBand)
(xbsize, ybsize) = blocksize(raster)
rows = height(raster)
cols = width(raster)
ni = ceil(Cint, rows / ybsize)
nj = ceil(Cint, cols / xbsize)
BlockIterator(rows, cols, ni, nj, ni * nj, xbsize, ybsize)
end
function Base.iterate(obj::BlockIterator, iter::Int=0)
iter == obj.n && return nothing
j = floor(Int, iter / obj.ni)
i = iter % obj.ni
nrows = if (i + 1) * obj.ybsize < obj.rows
obj.ybsize
else
obj.rows - i * obj.ybsize
end
ncols = if (j + 1) * obj.xbsize < obj.cols
obj.xbsize
else
obj.cols - j * obj.xbsize
end
(((i, j), (nrows, ncols)), iter+1)
end
struct WindowIterator
blockiter::BlockIterator
end
Base.size(i::WindowIterator) = (i.blockiter.ni, i.blockiter.nj)
Base.length(i::WindowIterator) = i.blockiter.n
Base.IteratorSize(::Type{WindowIterator}) = Base.HasShape{2}()
Base.IteratorEltype(::Type{WindowIterator}) = Base.HasEltype()
Base.eltype(::WindowIterator) = Tuple{UnitRange{Int}, UnitRange{Int}}
windows(raster::AbstractRasterBand) = WindowIterator(blocks(raster))
function Base.iterate(obj::WindowIterator, iter::Int=0)
handle = obj.blockiter
next = Base.iterate(handle, iter)
next == nothing && return nothing
(((i, j), (nrows, ncols)), iter) = next
(((1:ncols) .+ j * handle.xbsize, (1:nrows) .+ i * handle.ybsize), iter)
end
mutable struct BufferIterator{T <: Real}
raster::AbstractRasterBand
w::WindowIterator
buffer::Array{T, 2}
end
function bufferwindows(raster::AbstractRasterBand)
BufferIterator(
raster,
windows(raster),
Array{pixeltype(raster)}(undef, blocksize(raster)...)
)
end
function Base.iterate(obj::BufferIterator, iter::Int=0)
next = Base.iterate(obj.w, iter)
next == nothing && return nothing
((cols, rows), iter) = next
rasterio!(obj.raster, obj.buffer, rows, cols)
return (obj.buffer[1:length(cols), 1:length(rows)], iter)
end