Skip to content

Commit

Permalink
Cleanup (#123)
Browse files Browse the repository at this point in the history
* reorganise

* reorganise map

* renames

* revert doc changes

* fix deps
  • Loading branch information
rafaqz authored Dec 31, 2024
1 parent 7fa8e5b commit 507e43b
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 310 deletions.
43 changes: 23 additions & 20 deletions src/Tyler.jl
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
module Tyler

using ArchGDAL
using Downloads
using FileIO
using GeometryBasics
using ImageIO
using LinearAlgebra
using Makie
using PointClouds
using Proj
using Scratch
using Statistics

import GeoFormatTypes as GFT
import GeometryOps as GO

using Colors: Colors, RGB, N0f8, Colorant
using Extents: Extents, Extent
using GeoInterface: GeoInterface
using GeometryBasics: GeometryBasics, GLTriangleFace, Point2f, Vec2f, Rect2f, Rect2, Rect, decompose, decompose_uv, Vec3d, Point2d, Point3d, Point4d
using GeometryBasics: GeometryBasics, GLTriangleFace, Point2f, Vec2f, Rect2f, Rect2, Rect, Vec3d, Point2d, Point3d, Point4d
using GeometryBasics: decompose, decompose_uv
using HTTP: HTTP
using LRUCache: LRUCache, LRU
using Makie: AbstractAxis, Observable, Figure, Axis, LScene, RGBAf
using Makie: on, isopen, meta, mesh!, translate!, scale!, Plot
using MapTiles: MapTiles, Tile, TileGrid, web_mercator, wgs84, CoordinateReferenceSystemFormat
using Makie: Makie, Observable, Figure, Axis, LScene, RGBAf, on, isopen, mesh!, translate!, scale!, Plot
using OrderedCollections: OrderedCollections, OrderedSet
using ThreadSafeDicts: ThreadSafeDicts, ThreadSafeDict
using TileProviders: TileProviders, AbstractProvider, geturl, min_zoom, max_zoom
using Makie
using Makie: AbstractAxis
using LinearAlgebra, GeometryBasics
using GeometryBasics
using Proj
using Statistics
using PointClouds
using ArchGDAL
import GeoFormatTypes as GFT
using Downloads
using Scratch
using ImageIO, FileIO
import GeometryOps as GO


const CACHE_PATH = Ref("")

Expand All @@ -38,15 +41,15 @@ abstract type FetchingScheme end
abstract type AbstractMap end

include("downloader.jl")
include("tiles.jl")
include("tile-cache.jl")
include("map.jl")
include("3d-map.jl")
include("tyler-cam3d.jl")
include("map3d.jl")
include("cam3d.jl")
include("tile-plotting.jl")
include("tile-fetching.jl")
include("provider/shared.jl")
include("provider/interpolations.jl")
include("provider/elevation/elevation-provider.jl")
include("provider/pointclouds/geotiles-pointcloud-provider.jl")


end
2 changes: 1 addition & 1 deletion src/tyler-cam3d.jl → src/cam3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,4 @@ function add_tyler_mouse_controls!(scene, cam::Camera3D)
end
return Consume(false)
end
end
end
10 changes: 3 additions & 7 deletions src/downloader.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ struct ByteDownloader <: AbstractDownloader
io::IOBuffer
bytes::Vector{UInt8}
end

function ByteDownloader(timeout=3)
downloader = Downloads.Downloader()
downloader.easy_hook = (easy, info) -> Downloads.Curl.setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_TIME, timeout)
Expand All @@ -31,7 +30,6 @@ struct PathDownloader <: AbstractDownloader
cache_dir::String
lru::LRU{String, Int}
end

function PathDownloader(cache_dir; timeout=5, cache_size_gb=5)
isdir(cache_dir) || mkpath(cache_dir)
lru = LRU{String, Int}(maxsize=cache_size_gb * 10^9, by=identity)
Expand All @@ -40,15 +38,13 @@ function PathDownloader(cache_dir; timeout=5, cache_size_gb=5)
return PathDownloader(timeout, downloader, cache_dir, lru)
end

function unique_filename(url)
return string(hash(url))
end

function download_tile_data(dl::PathDownloader, provider::AbstractProvider, url)
unique_name = unique_filename(url)
unique_name = _unique_filename(url)
path = joinpath(dl.cache_dir, unique_name * file_ending(provider))
if !isfile(path)
Downloads.download(url, path; downloader=dl.downloader)
end
return path
end

_unique_filename(url) = string(hash(url))
231 changes: 105 additions & 126 deletions src/map.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@

function tile_key(provider::AbstractProvider, tile::Tile)
return TileProviders.geturl(provider, tile.x, tile.y, tile.z)
end


"""
Map(extent, [extent_crs=wgs84]; kw...)
Map(map::Map; ...) # layering another provider on top of an existing map
Expand Down Expand Up @@ -57,81 +51,6 @@ struct Map{Ax<:Makie.AbstractAxis} <: AbstractMap
max_plots::Int
scale::Float64
end

function setup_figure_and_axis!(figure::Makie.Figure, axis, ext_target, crs)
setup_axis!(axis, ext_target, crs)
return figure, axis
end

function setup_figure_and_axis!(figure::Makie.Figure, axis_kws_nt::NamedTuple, ext_target, crs)
axis_kws = Dict(pairs(axis_kws_nt))
AxisType = pop!(axis_kws, :type, Axis)

axis = AxisType(figure[1, 1]; axis_kws...)

setup_axis!(axis, ext_target, crs)

return figure, axis
end

_get_parent_layout(gp::Makie.GridPosition) = _get_parent_layout(gp.layout)
_get_parent_layout(gp::Makie.GridSubposition) = _get_parent_layout(gp.layout)
_get_parent_layout(gl::Makie.GridLayout) = gl


_get_parent_figure(fig::Makie.Figure) = fig
_get_parent_figure(gl::Makie.GridLayout) = _get_parent_figure(gl.parent)
_get_parent_figure(gp::Makie.GridPosition) = _get_parent_figure(_get_parent_layout(gp.layout))
_get_parent_figure(gp::Makie.GridSubposition) = _get_parent_figure(_get_parent_layout(gp.layout))

function setup_figure_and_axis!(figure::GridPosition, axis, ext_target, crs)
error("""
You have tried to construct a `Map` at a given grid position,
but with a materialized axis of type $(typeof(axis)).
You can only do this if you let Tyler construct the axis,
by passing its parameters as a NamedTuple
(like `axis = (; type = Axis, ...)`).
""")
end

function setup_figure_and_axis!(gridposition::GridPosition, axis_kws_nt::NamedTuple, ext_target, crs)
figure = _get_parent_figure(gridposition)

axis_kws = Dict(pairs(axis_kws_nt))
AxisType = pop!(axis_kws, :type, Axis)

axis = AxisType(gridposition; axis_kws...)

setup_axis!(axis, ext_target, crs)

return figure, axis
end

setup_axis!(::Makie.AbstractAxis, ext_target, crs) = nothing

function setup_axis!(axis::Axis, ext_target, crs)
X = ext_target.X
Y = ext_target.Y
axis.autolimitaspect = 1
Makie.limits!(axis, (X[1], X[2]), (Y[1], Y[2]))
axis.elements[:background].depth_shift[] = 0.1f0
translate!(axis.elements[:background], 0, 0, -1000)
axis.elements[:background].color = :transparent
axis.xgridvisible = false
axis.ygridvisible = false
return
end

function Map3D(m::Map; kw...)
ax = m.axis
# Make a copy of the lscene, so we can easier separate the plots.
ax2 = LScene(ax.parent, ax.layoutobservables, ax.blockscene)
ax2.scene = Scene(ax.scene; camera=ax.scene.camera, camera_controls=ax.scene.camera_controls)
return Map3D(nothing, nothing; figure=m.figure, axis=ax2, kw...)
end


"""
Map(m::Map; kw...)
Layering constructor to show another provider on top of an existing map.
Expand All @@ -158,18 +77,6 @@ function Map(m::Map; kw...)
setfield!(ax2.scene, :float32convert, ax.scene.float32convert)
return Map(nothing, nothing; figure=m.figure, axis=ax2, kw...)
end

toggle_visibility!(m::Map) = m.axis.scene.visible[] = !m.axis.scene.visible[]

function Base.close(m::Map)
cleanup_queue!(m, OrderedSet{Tile}())
empty!(m.foreground_tiles)
empty!(m.unused_plots)
empty!(m.plots)
empty!(m.should_get_plotted)
close(m.tiles)
end

function Map(extent, extent_crs=wgs84;
size=(1000, 1000),
figure=Makie.Figure(; size=size),
Expand Down Expand Up @@ -247,29 +154,68 @@ function Map(extent, extent_crs=wgs84;
return map
end

function Base.wait(m::AbstractMap; timeout=50)
# The download + plot loops need a screen to do their work!
if isnothing(Makie.getscreen(m.figure.scene))
screen = display(m.figure.scene)
end
screen = Makie.getscreen(m.figure.scene)
isnothing(screen) && error("No screen after display.")
wait(m.tiles; timeout=timeout)
start = time()
while true
tile_keys = Set(tile_key.((m.provider,), keys(m.foreground_tiles)))
if all(k -> haskey(m.plots, k), tile_keys)
break
end
if time() - start > timeout
@warn "Timeout waiting for all tiles to be plotted"
break
end
sleep(0.01)
end
return m
function setup_figure_and_axis!(figure::Makie.Figure, axis, ext_target, crs)
setup_axis!(axis, ext_target, crs)
return figure, axis
end
function setup_figure_and_axis!(figure::Makie.Figure, axis_kws_nt::NamedTuple, ext_target, crs)
axis_kws = Dict(pairs(axis_kws_nt))
AxisType = pop!(axis_kws, :type, Axis)

axis = AxisType(figure[1, 1]; axis_kws...)

setup_axis!(axis, ext_target, crs)

return figure, axis
end
function setup_figure_and_axis!(figure::GridPosition, axis, ext_target, crs)
error("""
You have tried to construct a `Map` at a given grid position,
but with a materialized axis of type $(typeof(axis)).
You can only do this if you let Tyler construct the axis,
by passing its parameters as a NamedTuple
(like `axis = (; type = Axis, ...)`).
""")
end
function setup_figure_and_axis!(gridposition::GridPosition, axis_kws_nt::NamedTuple, ext_target, crs)
figure = _get_parent_figure(gridposition)

axis_kws = Dict(pairs(axis_kws_nt))
AxisType = pop!(axis_kws, :type, Axis)

axis = AxisType(gridposition; axis_kws...)

setup_axis!(axis, ext_target, crs)

return figure, axis
end

_get_parent_layout(gp::Makie.GridPosition) = _get_parent_layout(gp.layout)
_get_parent_layout(gp::Makie.GridSubposition) = _get_parent_layout(gp.layout)
_get_parent_layout(gl::Makie.GridLayout) = gl

_get_parent_figure(fig::Makie.Figure) = fig
_get_parent_figure(gl::Makie.GridLayout) = _get_parent_figure(gl.parent)
_get_parent_figure(gp::Makie.GridPosition) = _get_parent_figure(_get_parent_layout(gp.layout))
_get_parent_figure(gp::Makie.GridSubposition) = _get_parent_figure(_get_parent_layout(gp.layout))

setup_axis!(::Makie.AbstractAxis, ext_target, crs) = nothing
function setup_axis!(axis::Axis, ext_target, crs)
X = ext_target.X
Y = ext_target.Y
axis.autolimitaspect = 1
Makie.limits!(axis, (X[1], X[2]), (Y[1], Y[2]))
axis.elements[:background].depth_shift[] = 0.1f0
translate!(axis.elements[:background], 0, 0, -1000)
axis.elements[:background].color = :transparent
axis.xgridvisible = false
axis.ygridvisible = false
return
end

toggle_visibility!(m::Map) = m.axis.scene.visible[] = !m.axis.scene.visible[]

function tile_reloader(map::Map{Axis})
axis = map.axis
throttled = Makie.Observables.throttle(0.2, axis.finallimits)
Expand All @@ -283,12 +229,29 @@ function plotted_tiles(m::Map)
return getindex.(values(m.plots), 2)
end

function remove_unused!(m::AbstractMap, tile::Tile)
return remove_unused!(m, tile_key(m.provider, tile))
end
function remove_unused!(m::AbstractMap, key::String)
plot_tile = get(m.plots, key, nothing)
if !isnothing(plot_tile)
plot, tile, bounds = plot_tile
move_to_back!(plot, abs(m.zoom[] - tile.z), bounds)
return plot, key
end
return nothing
end

# Package interface methods

GeoInterface.crs(map::Map) = map.crs
Extents.extent(map::Map) = Extents.extent(map.axis.finallimits[])

TileProviders.max_zoom(map::Map) = map.max_zoom
TileProviders.min_zoom(map::Map) = Int(min_zoom(map.provider))

# Base methods

Base.showable(::MIME"image/png", ::AbstractMap) = true

function Base.show(io::IO, m::MIME"image/png", map::AbstractMap)
Expand All @@ -301,17 +264,33 @@ function Base.display(map::AbstractMap)
Base.display(map.figure.scene)
end


function remove_unused!(m::AbstractMap, tile::Tile)
return remove_unused!(m, tile_key(m.provider, tile))
function Base.close(m::Map)
cleanup_queue!(m, OrderedSet{Tile}())
empty!(m.foreground_tiles)
empty!(m.unused_plots)
empty!(m.plots)
empty!(m.should_get_plotted)
close(m.tiles)
end

function remove_unused!(m::AbstractMap, key::String)
plot_tile = get(m.plots, key, nothing)
if !isnothing(plot_tile)
plot, tile, bounds = plot_tile
move_to_back!(plot, abs(m.zoom[] - tile.z), bounds)
return plot, key
function Base.wait(m::AbstractMap; timeout=50)
# The download + plot loops need a screen to do their work!
if isnothing(Makie.getscreen(m.figure.scene))
screen = display(m.figure.scene)
end
return nothing
end
screen = Makie.getscreen(m.figure.scene)
isnothing(screen) && error("No screen after display.")
wait(m.tiles; timeout=timeout)
start = time()
while true
tile_keys = Set(tile_key.((m.provider,), keys(m.foreground_tiles)))
if all(k -> haskey(m.plots, k), tile_keys)
break
end
if time() - start > timeout
@warn "Timeout waiting for all tiles to be plotted"
break
end
sleep(0.01)
end
return m
end
Loading

0 comments on commit 507e43b

Please sign in to comment.