Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lenunit option to load #110

Merged
merged 4 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/GeoIO.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ using CoordRefSystems
using Meshes: SubDomain
using Format: generate_formatter
using TransformsBase: Identity, →
using Unitful: m

# image formats
import FileIO
Expand Down Expand Up @@ -110,17 +111,18 @@ include("utils.jl")
include("conversion.jl")

# extra code for backends
include("extra/vtkread.jl")
include("extra/vtkwrite.jl")
include("extra/stl.jl")
include("extra/obj.jl")
include("extra/off.jl")
include("extra/msh.jl")
include("extra/ply.jl")
include("extra/csv.jl")
include("extra/img.jl")
include("extra/cdm.jl")
include("extra/gdal.jl")
include("extra/geotiff.jl")
include("extra/vtkread.jl")
include("extra/vtkwrite.jl")

# user functions
include("load.jl")
Expand Down
2 changes: 1 addition & 1 deletion src/extra/csv.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

function csvread(fname; coords, kwargs...)
function csvread(fname; lenunit, coords, kwargs...)
csv = CSV.File(fname; kwargs...)
rows = Tables.rows(csv)
cnames = Symbol.(coords)
Expand Down
13 changes: 13 additions & 0 deletions src/extra/img.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

function imgread(fname; lenunit)
data = FileIO.load(fname)
dims = size(data)
values = (; color=vec(data))
# translation followed by rotation is faster
transform = Translate(-dims[1], 0) → Rotate(-π / 2)
domain = CartesianGrid(dims) |> transform
georef(values, domain)
end
7 changes: 5 additions & 2 deletions src/extra/msh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

function mshread(fname)
function mshread(fname; lenunit)
nodetags = Int[]
vertices = NTuple{3,Float64}[]
nodedata = Dict{Int,Any}()
Expand Down Expand Up @@ -42,7 +42,10 @@ function mshread(fname)
connec = map(elemtypes, eleminds) do elemtype, inds
connect(Tuple(inds), ELEMTYPE2GEOM[elemtype])
end
mesh = SimpleMesh(vertices, connec)

u = lenunit
points = map(v -> Point(v[1]u, v[2]u, v[3]u), vertices)
mesh = SimpleMesh(points, connec)

vtable = _datatable(nodetags, nodedata)
etable = _datatable(elemtags, elemdata)
Expand Down
8 changes: 5 additions & 3 deletions src/extra/obj.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

function objread(fname)
function objread(fname; lenunit)
vertices = NTuple{3,Float64}[]
faceinds = Vector{Int}[]

Expand Down Expand Up @@ -37,10 +37,12 @@ function objread(fname)
end
end

u = lenunit
points = map(v -> Point(v[1]u, v[2]u, v[3]u), vertices)
connec = map(inds -> connect(Tuple(inds), Ngon), faceinds)
mesh = SimpleMesh(vertices, connec)
mesh = SimpleMesh(points, connec)

GeoTable(mesh)
georef(nothing, mesh)
end

function objwrite(fname, geotable)
Expand Down
9 changes: 6 additions & 3 deletions src/extra/off.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

function offread(fname; defaultcolor::Colorant=RGBA(0.666, 0.666, 0.666, 0.666))
function offread(fname; lenunit, defaultcolor=RGBA(0.666, 0.666, 0.666, 0.666))
vertices = NTuple{3,Float64}[]
faceinds = Vector{Int}[]
facecolors = RGBA{Float64}[]
Expand Down Expand Up @@ -47,10 +47,13 @@ function offread(fname; defaultcolor::Colorant=RGBA(0.666, 0.666, 0.666, 0.666))
end
end

connec = map(inds -> connect(Tuple(inds), Ngon), faceinds)
mesh = SimpleMesh(vertices, connec)
table = (; COLOR=facecolors)

u = lenunit
points = map(v -> Point(v[1]u, v[2]u, v[3]u), vertices)
connec = map(inds -> connect(Tuple(inds), Ngon), faceinds)
mesh = SimpleMesh(points, connec)

georef(table, mesh)
end

Expand Down
5 changes: 3 additions & 2 deletions src/extra/ply.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
# ------------------------------------------------------------------

# helper function to read PlyIO properties
function plyread(fname; kwargs...)
function plyread(fname; lenunit, kwargs...)
# load dictionary
ply = PlyIO.load_ply(fname; kwargs...)

# load domain
v = ply["vertex"]
e = ply["face"]
points = Point.(v["x"], v["y"], v["z"])
u = lenunit
points = Point.(v["x"]u, v["y"]u, v["z"]u)
connec = [connect(Tuple(c .+ 1)) for c in e["vertex_indices"]]
domain = SimpleMesh(points, connec)

Expand Down
19 changes: 12 additions & 7 deletions src/extra/stl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@
# STL READ
# ---------

function stlraed(fname)
function stlraed(fname; lenunit)
normals, vertices = if _isstlbin(fname)
stlbinread(fname)
else
stlasciiread(fname)
end

upoints = unique(Iterators.flatten(vertices))
ptindex = Dict(zip(upoints, eachindex(upoints)))
connec = map(vertices) do points
inds = ntuple(i -> ptindex[points[i]], 3)
uverts = unique(Iterators.flatten(vertices))
index = Dict(zip(uverts, eachindex(uverts)))
connec = map(vertices) do verts
inds = ntuple(i -> index[verts[i]], 3)
connect(inds, Triangle)
end

mesh = SimpleMesh(upoints, connec)
table = (; NORMAL=Vec.(normals))
u = lenunit

norms = map(n -> Vec(n .* u), normals)
table = (; NORMAL=norms)

points = map(v -> Point(v[1]u, v[2]u, v[3]u), uverts)
mesh = SimpleMesh(points, connec)

georef(table, mesh)
end
Expand Down
22 changes: 11 additions & 11 deletions src/extra/vtkread.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ const GEOMTYPE = Dict(
VTKCellTypes.VTK_PYRAMID => Pyramid
)

function vtkread(fname; mask=:MASK)
function vtkread(fname; lenunit, mask=:MASK)
gtb = if endswith(fname, ".vtu")
vturead(fname)
vturead(fname; lenunit)
elseif endswith(fname, ".vtp")
vtpread(fname)
vtpread(fname; lenunit)
elseif endswith(fname, ".vtr")
vtrread(fname)
vtrread(fname; lenunit)
elseif endswith(fname, ".vts")
vtsread(fname)
vtsread(fname; lenunit)
elseif endswith(fname, ".vti")
vtiread(fname)
vtiread(fname; lenunit)
else
error("unsupported VTK file format")
end
Expand All @@ -40,7 +40,7 @@ function vtkread(fname; mask=:MASK)
end
end

function vturead(fname)
function vturead(fname; lenunit)
vtk = ReadVTK.VTKFile(fname)

# construct mesh
Expand All @@ -55,7 +55,7 @@ function vturead(fname)
GeoTable(mesh; vtable, etable)
end

function vtpread(fname)
function vtpread(fname; lenunit)
vtk = ReadVTK.VTKFile(fname)

# construct mesh
Expand All @@ -70,7 +70,7 @@ function vtpread(fname)
GeoTable(mesh; vtable, etable)
end

function vtrread(fname)
function vtrread(fname; lenunit)
vtk = ReadVTK.VTKFile(fname)

# construct grid
Expand All @@ -85,7 +85,7 @@ function vtrread(fname)
GeoTable(grid; vtable, etable)
end

function vtsread(fname)
function vtsread(fname; lenunit)
vtk = ReadVTK.VTKFile(fname)

# construct grid
Expand All @@ -102,7 +102,7 @@ function vtsread(fname)
GeoTable(grid; vtable, etable)
end

function vtiread(fname)
function vtiread(fname; lenunit)
vtk = ReadVTK.VTKFile(fname)

# construct grid
Expand Down
60 changes: 28 additions & 32 deletions src/load.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ------------------------------------------------------------------

"""
load(fname, repair=true, layer=0, kwargs...)
load(fname, repair=true, layer=0, lenunit=m, kwargs...)

Load geospatial table from file `fname` stored in any format.

Expand All @@ -16,8 +16,10 @@ In that case, we recommend setting `repair=false`. Custom
repairs can be performed with the `Repair` transform from
Meshes.jl.

Optionally, specify the `layer` to read within the file and
forward `kwargs` to backend packages.
Optionally, specify the `layer` to read within the file, and
the length unit `lenunit` of the coordinates when the format
does not include units in its specification. Other `kwargs`
are forwarded to the backend packages.

Please use the [`formats`](@ref) function to list
all supported file formats.
Expand All @@ -29,68 +31,62 @@ all supported file formats.
GeoIO.load("file.geojson", numbertype = Float64)
```
"""
function load(fname; repair=true, layer=0, kwargs...)
# IMG formats
if any(ext -> endswith(fname, ext), IMGEXTS)
data = FileIO.load(fname)
dims = size(data)
values = (; color=vec(data))
# translation followed by rotation is faster
transform = Translate(-dims[1], 0) → Rotate(-π / 2)
domain = CartesianGrid(dims) |> transform
return georef(values, domain)
end

function load(fname; repair=true, layer=0, lenunit=m, kwargs...)
# VTK formats
if any(ext -> endswith(fname, ext), VTKEXTS)
return vtkread(fname; kwargs...)
end

# Common Data Model formats
if any(ext -> endswith(fname, ext), CDMEXTS)
return cdmread(fname; kwargs...)
end

# GeoTiff formats
if any(ext -> endswith(fname, ext), GEOTIFFEXTS)
return geotiffread(fname; kwargs...)
return vtkread(fname; lenunit, kwargs...)
end

# STL format
if endswith(fname, ".stl")
return stlraed(fname; kwargs...)
return stlraed(fname; lenunit, kwargs...)
end

# OBJ format
if endswith(fname, ".obj")
return objread(fname; kwargs...)
return objread(fname; lenunit, kwargs...)
end

# OFF format
if endswith(fname, ".off")
return offread(fname; kwargs...)
return offread(fname; lenunit, kwargs...)
end

# MSH format
if endswith(fname, ".msh")
return mshread(fname; kwargs...)
return mshread(fname; lenunit, kwargs...)
end

# PLY format
if endswith(fname, ".ply")
return plyread(fname; kwargs...)
return plyread(fname; lenunit, kwargs...)
end

# CSV format
if endswith(fname, ".csv")
return csvread(fname; kwargs...)
return csvread(fname; lenunit, kwargs...)
end

# IMG formats
if any(ext -> endswith(fname, ext), IMGEXTS)
return imgread(fname; lenunit, kwargs...)
end

# GSLIB format
if endswith(fname, ".gslib")
return GslibIO.load(fname; kwargs...)
end

# Common Data Model formats
if any(ext -> endswith(fname, ext), CDMEXTS)
return cdmread(fname; kwargs...)
end

# GeoTiff formats
if any(ext -> endswith(fname, ext), GEOTIFFEXTS)
return geotiffread(fname; kwargs...)
end

# GIS formats
table = if endswith(fname, ".shp")
SHP.Table(fname; kwargs...)
Expand Down
7 changes: 4 additions & 3 deletions src/save.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
"""
save(fname, geotable; kwargs...)

Save geospatial table to file `fname` using the
appropriate format based on the file extension.
Optionally, forward `kwargs` to backend packages.
Save `geotable` to file `fname` of given format
based on the file extension.

Other `kwargs` are forwarded to the backend packages.

Please use the [`formats`](@ref) function to list
all supported file formats.
Expand Down
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ ReferenceTests = "324d217c-45ce-50fc-942e-d289b448e8cf"
Shapefile = "8e980c4a-a4fe-5da2-b3a7-4b4b0353a2f4"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
6 changes: 6 additions & 0 deletions test/io/msh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
@test Meshes.lentype(gtb.geometry) <: Meshes.Met{Float64}
@test eltype(gtb.geometry) <: Triangle
@test length(gtb.geometry) == 4

# custom lenunit
gtb = GeoIO.load(joinpath(datadir, "tetrahedron1.msh"), lenunit=cm)
@test unit(Meshes.lentype(crs(gtb.geometry))) == cm
gtb = GeoIO.load(joinpath(datadir, "tetrahedron2.msh"), lenunit=cm)
@test unit(Meshes.lentype(crs(gtb.geometry))) == cm
end

@testset "save" begin
Expand Down
Loading