From 0adb42d614f339b1be965aef6bedce76c9df2a34 Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 12:18:01 -0500 Subject: [PATCH 01/10] write to shapefile --- src/GeoTables.jl | 22 +++++++++++++++------- src/conversion.jl | 16 ++++++++++------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/GeoTables.jl b/src/GeoTables.jl index b57df4f..c7490b0 100644 --- a/src/GeoTables.jl +++ b/src/GeoTables.jl @@ -31,14 +31,14 @@ specify the layer of geometries to read within the file. - `*.geojson` via GeoJSON.jl - Other formats via ArchGDAL.jl """ -function load(fname, layer=0) +function load(fname; layer=0, kwargs...) if endswith(fname, ".shp") - table = SHP.Table(fname) + table = SHP.Table(fname; kwargs...) elseif endswith(fname, ".geojson") data = Base.read(fname) - table = GJS.read(data) + table = GJS.read(data; kwargs...) else # fallback to GDAL - data = AG.read(fname) + data = AG.read(fname; kwargs...) table = AG.getlayer(data, layer) end GeoTable(table) @@ -54,9 +54,17 @@ appropriate format based on the file extension. - `*.geojson` via GeoJSON.jl """ -function save(fname, geotable) - if endswith(fname, ".geojson") - GJS.write(fname, geotable) +function save(fname, geotable; kwargs...) + if endswith(fname, ".shp") + geotable = MeshData(geotable) + geoms = domain(geotable) + if !isa(geoms[1], Multi) & !isa(geoms[1], Point) + geoms = GeometrySet(map(x -> Multi([x]), geoms)) + geotable = meshdata(geoms, etable = values(geotable)) + end + SHP.write(fname, geotable; kwargs...) + elseif endswith(fname, ".geojson") + GJS.write(fname, geotable; kwargs...) else throw(ErrorException("file format not supported")) end diff --git a/src/conversion.jl b/src/conversion.jl index 6fd79a1..888c988 100644 --- a/src/conversion.jl +++ b/src/conversion.jl @@ -20,15 +20,19 @@ GI.ncoord(::GI.PointTrait, p::Point) = embeddim(p) GI.getcoord(::GI.PointTrait, p::Point) = coordinates(p) GI.getcoord(::GI.PointTrait, p::Point, i) = coordinates(p)[i] -GI.ngeom(::Any, s::Segment) = nvertices(s) -GI.getgeom(::Any, s::Segment, i) = vertices(s)[i] +GI.ncoord(::GI.LineTrait, s::Segment) = embeddim(s) +GI.ngeom(::GI.LineTrait, s::Segment) = nvertices(s) +GI.getgeom(::GI.LineTrait, s::Segment, i) = vertices(s)[i] -GI.ngeom(::Any, c::Chain) = nvertices(c) -GI.getgeom(::Any, c::Chain, i) = vertices(c)[i] +GI.ncoord(::GI.LineStringTrait, c::Chain) = embeddim(c) +GI.ngeom(::GI.LineStringTrait, c::Chain) = nvertices(c) +GI.getgeom(::GI.LineStringTrait, c::Chain, i) = vertices(c)[i] -GI.ngeom(::Any, p::Polygon) = length(chains(p)) -GI.getgeom(::Any, p::Polygon, i) = chains(p)[i] +GI.ncoord(::GI.PolygonTrait, p::Polygon) = embeddim(p) +GI.ngeom(::GI.PolygonTrait, p::Polygon) = length(chains(p)) +GI.getgeom(::GI.PolygonTrait, p::Polygon, i) = chains(p)[i] +GI.ncoord(::Any, m::Multi) = embeddim(m) GI.ngeom(::Any, m::Multi) = length(collect(m)) GI.getgeom(::Any, m::Multi, i) = collect(m)[i] From f0844d25364fcc96013369e18a980009ef13d14f Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 13:02:30 -0500 Subject: [PATCH 02/10] remove initial conversion to MeshData --- src/GeoTables.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/GeoTables.jl b/src/GeoTables.jl index c7490b0..6183002 100644 --- a/src/GeoTables.jl +++ b/src/GeoTables.jl @@ -56,11 +56,10 @@ appropriate format based on the file extension. """ function save(fname, geotable; kwargs...) if endswith(fname, ".shp") - geotable = MeshData(geotable) geoms = domain(geotable) if !isa(geoms[1], Multi) & !isa(geoms[1], Point) - geoms = GeometrySet(map(x -> Multi([x]), geoms)) - geotable = meshdata(geoms, etable = values(geotable)) + newgeoms = GeometrySet([Multi([geom]) for geom in geoms]) + geotable = meshdata(newgeoms, etable = values(geotable)) end SHP.write(fname, geotable; kwargs...) elseif endswith(fname, ".geojson") From dd8e411816751ed76d780374905421b4e08dc539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlio=20Hoffimann?= Date: Wed, 3 May 2023 15:05:11 -0300 Subject: [PATCH 03/10] Update src/GeoTables.jl --- src/GeoTables.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GeoTables.jl b/src/GeoTables.jl index 6183002..4d15a7a 100644 --- a/src/GeoTables.jl +++ b/src/GeoTables.jl @@ -57,7 +57,7 @@ appropriate format based on the file extension. function save(fname, geotable; kwargs...) if endswith(fname, ".shp") geoms = domain(geotable) - if !isa(geoms[1], Multi) & !isa(geoms[1], Point) + if !(geoms[1] isa Multi) && !(geoms[1] isa Point) newgeoms = GeometrySet([Multi([geom]) for geom in geoms]) geotable = meshdata(newgeoms, etable = values(geotable)) end From 7e83d662778256ab4068b601137aa473dc8a29c5 Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 14:54:08 -0500 Subject: [PATCH 04/10] add information about keyword arguments --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index e81a28a..2ec46bc 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,18 @@ table = GeoTables.load("file.shp") GeoTables.save("file.geojson", table) ``` +Additional keyword arguments can be passed to `load` and `save` functions. Valid +arguments are those accepted by `GeoJSON.read`, `GeoJSON.write`, `Shapefile.Table`, +`Shapefile.write` and `ArchGDAL.read`. See below some examples. + +```julia +# Read GeoJSON geometries as Float64. +table = GeoTables.load("file.geojson", numbertype = Float64) + +# Force Shapefile to write on existing file. +GeoTables.save("file.shp", table, force = true) +``` + ### Loading data from GADM The `gadm` function (down)loads data from the GADM dataset: From e2935a7654e8c85f8281a27f876ad2c3e7956074 Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 15:01:58 -0500 Subject: [PATCH 05/10] better description of examples --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2ec46bc..0482c84 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,13 @@ GeoTables.save("file.geojson", table) Additional keyword arguments can be passed to `load` and `save` functions. Valid arguments are those accepted by `GeoJSON.read`, `GeoJSON.write`, `Shapefile.Table`, -`Shapefile.write` and `ArchGDAL.read`. See below some examples. +`Shapefile.write` and `ArchGDAL.read`. See below some examples: ```julia -# Read GeoJSON geometries as Float64. +# Read `.geojson` geometries with Float64 precision. table = GeoTables.load("file.geojson", numbertype = Float64) -# Force Shapefile to write on existing file. +# Force writing on existing `.shp` file. GeoTables.save("file.shp", table, force = true) ``` From 493b3f4cef241868478c474abb6032f7eace181c Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 15:14:37 -0500 Subject: [PATCH 06/10] docstring for keyargs --- src/GeoTables.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/GeoTables.jl b/src/GeoTables.jl index 4d15a7a..34296d4 100644 --- a/src/GeoTables.jl +++ b/src/GeoTables.jl @@ -19,11 +19,14 @@ include("conversion.jl") include("geotable.jl") """ - load(fname, layer=0) + load(fname, layer=0, kwargs...) Load geospatial table from file `fname` and convert the `geometry` column to Meshes.jl geometries. Optionally, -specify the layer of geometries to read within the file. +specify the layer of geometries to read within the file and +keyword arguments accepted by `Shapefile.Table`, `GeoJSON.read` +and `ArchGDAL.read`. For example, use `numbertype = Float64` to +read `.geojson` geometries with Float64 precision. ## Supported formats @@ -45,13 +48,17 @@ function load(fname; layer=0, kwargs...) end """ - save(fname, geotable) + save(fname, geotable; kwargs...) Save geospatial table to file `fname` using the appropriate format based on the file extension. +Optionally, specify keyword arguments accepted by +`Shapefile.write` and `GeoJSON.write`. For example, use +`force = true` to force writing on existing `.shp` file. ## Supported formats +- `*.shp` via Shapefile.jl - `*.geojson` via GeoJSON.jl """ function save(fname, geotable; kwargs...) From 9e62c6ead65bae83060e1d4a3501d1da12a77b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dr=2E=20Erick=20A=2E=20Chac=C3=B3n=20Montalv=C3=A1n?= Date: Wed, 3 May 2023 15:14:09 -0500 Subject: [PATCH 07/10] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: JĂșlio Hoffimann --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0482c84..adf83c2 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,10 @@ arguments are those accepted by `GeoJSON.read`, `GeoJSON.write`, `Shapefile.Tabl `Shapefile.write` and `ArchGDAL.read`. See below some examples: ```julia -# Read `.geojson` geometries with Float64 precision. +# read `.geojson` geometries with Float64 precision table = GeoTables.load("file.geojson", numbertype = Float64) -# Force writing on existing `.shp` file. +# force writing on existing `.shp` file GeoTables.save("file.shp", table, force = true) ``` From 2001430039ee292fff761f8217adb887fef5543d Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 18:47:17 -0500 Subject: [PATCH 08/10] remove temporal fix of Shapefile.jl --- src/GeoTables.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/GeoTables.jl b/src/GeoTables.jl index 34296d4..9d65827 100644 --- a/src/GeoTables.jl +++ b/src/GeoTables.jl @@ -63,11 +63,6 @@ Optionally, specify keyword arguments accepted by """ function save(fname, geotable; kwargs...) if endswith(fname, ".shp") - geoms = domain(geotable) - if !(geoms[1] isa Multi) && !(geoms[1] isa Point) - newgeoms = GeometrySet([Multi([geom]) for geom in geoms]) - geotable = meshdata(newgeoms, etable = values(geotable)) - end SHP.write(fname, geotable; kwargs...) elseif endswith(fname, ".geojson") GJS.write(fname, geotable; kwargs...) From 83abc8c4f0fb7d817cef5cc7b153115a51a266cc Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 20:26:51 -0500 Subject: [PATCH 09/10] tests for writing --- test/runtests.jl | 62 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 7a1d053..82a7b46 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -201,10 +201,64 @@ datadir = joinpath(@__DIR__,"data") end @testset "save" begin - table = GeoTables.load(joinpath(datadir,"path.shp")) - GeoTables.save(joinpath(datadir,"path.geojson"), table) - table = GeoTables.load(joinpath(datadir,"zone.shp")) - GeoTables.save(joinpath(datadir,"path.geojson"), table) + writedir = joinpath(tempdir(), "geotables") + mkdir(writedir) + + @testset "points" begin + table = GeoTables.load(joinpath(datadir, "points.geojson"), ) + GeoTables.save(joinpath(writedir, "tpoints.geojson"), table) + GeoTables.save(joinpath(writedir, "tpoints.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir, "points.gpkg")) + GeoTables.save(joinpath(writedir, "tpoints.geojson"), table) + GeoTables.save(joinpath(writedir, "tpoints.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir, "points.shp")) + GeoTables.save(joinpath(writedir, "tpoints.geojson"), table) + GeoTables.save(joinpath(writedir, "tpoints.shp"), table, force = true) + end + + @testset "lines" begin + table = GeoTables.load(joinpath(datadir, "lines.geojson")) + GeoTables.save(joinpath(writedir, "tlines.geojson"), table) + # GeoTables.save(joinpath(writedir, "tlines.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir, "lines.gpkg")) + GeoTables.save(joinpath(writedir, "tlines.geojson"), table) + # GeoTables.save(joinpath(writedir, "tlines.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir, "lines.shp")) + GeoTables.save(joinpath(writedir, "tlines.geojson"), table) + GeoTables.save(joinpath(writedir, "tlines.shp"), table, force = true) + end + + @testset "polygons" begin + table = GeoTables.load(joinpath(datadir, "polygons.geojson")) + GeoTables.save(joinpath(writedir, "tpolygons.geojson"), table) + # GeoTables.save(joinpath(writedir, "tpolygons.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir, "polygons.gpkg")) + GeoTables.save(joinpath(writedir, "tpolygons.geojson"), table) + # GeoTables.save(joinpath(writedir, "tpolygons.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir, "polygons.shp")) + GeoTables.save(joinpath(writedir, "tpolygons.geojson"), table) + GeoTables.save(joinpath(writedir, "tpolygons.shp"), table, force = true) + end + + @testset "multipolygons" begin + table = GeoTables.load(joinpath(datadir,"path.shp")) + GeoTables.save(joinpath(writedir, "tpath.geojson"), table) + GeoTables.save(joinpath(writedir, "tpath.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir,"zone.shp")) + GeoTables.save(joinpath(writedir, "tzone.geojson"), table) + GeoTables.save(joinpath(writedir, "tzone.shp"), table, force = true) + + table = GeoTables.load(joinpath(datadir,"ne_110m_land.shp")) + GeoTables.save(joinpath(writedir, "tne_110m_land.geojson"), table) + GeoTables.save(joinpath(writedir, "tne_110m_land.shp"), table, force = true) + end end @testset "gadm" begin From 37fa2907cba1548d01f4ac59ef3c0d02df7d0bd4 Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 3 May 2023 21:07:22 -0500 Subject: [PATCH 10/10] use datadir for writing --- test/runtests.jl | 50 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 82a7b46..61349b1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -201,63 +201,61 @@ datadir = joinpath(@__DIR__,"data") end @testset "save" begin - writedir = joinpath(tempdir(), "geotables") - mkdir(writedir) @testset "points" begin table = GeoTables.load(joinpath(datadir, "points.geojson"), ) - GeoTables.save(joinpath(writedir, "tpoints.geojson"), table) - GeoTables.save(joinpath(writedir, "tpoints.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpoints.geojson"), table) + GeoTables.save(joinpath(datadir, "tpoints.shp"), table, force = true) table = GeoTables.load(joinpath(datadir, "points.gpkg")) - GeoTables.save(joinpath(writedir, "tpoints.geojson"), table) - GeoTables.save(joinpath(writedir, "tpoints.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpoints.geojson"), table) + GeoTables.save(joinpath(datadir, "tpoints.shp"), table, force = true) table = GeoTables.load(joinpath(datadir, "points.shp")) - GeoTables.save(joinpath(writedir, "tpoints.geojson"), table) - GeoTables.save(joinpath(writedir, "tpoints.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpoints.geojson"), table) + GeoTables.save(joinpath(datadir, "tpoints.shp"), table, force = true) end @testset "lines" begin table = GeoTables.load(joinpath(datadir, "lines.geojson")) - GeoTables.save(joinpath(writedir, "tlines.geojson"), table) - # GeoTables.save(joinpath(writedir, "tlines.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tlines.geojson"), table) + # GeoTables.save(joinpath(datadir, "tlines.shp"), table, force = true) table = GeoTables.load(joinpath(datadir, "lines.gpkg")) - GeoTables.save(joinpath(writedir, "tlines.geojson"), table) - # GeoTables.save(joinpath(writedir, "tlines.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tlines.geojson"), table) + # GeoTables.save(joinpath(datadir, "tlines.shp"), table, force = true) table = GeoTables.load(joinpath(datadir, "lines.shp")) - GeoTables.save(joinpath(writedir, "tlines.geojson"), table) - GeoTables.save(joinpath(writedir, "tlines.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tlines.geojson"), table) + GeoTables.save(joinpath(datadir, "tlines.shp"), table, force = true) end @testset "polygons" begin table = GeoTables.load(joinpath(datadir, "polygons.geojson")) - GeoTables.save(joinpath(writedir, "tpolygons.geojson"), table) - # GeoTables.save(joinpath(writedir, "tpolygons.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpolygons.geojson"), table) + # GeoTables.save(joinpath(datadir, "tpolygons.shp"), table, force = true) table = GeoTables.load(joinpath(datadir, "polygons.gpkg")) - GeoTables.save(joinpath(writedir, "tpolygons.geojson"), table) - # GeoTables.save(joinpath(writedir, "tpolygons.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpolygons.geojson"), table) + # GeoTables.save(joinpath(datadir, "tpolygons.shp"), table, force = true) table = GeoTables.load(joinpath(datadir, "polygons.shp")) - GeoTables.save(joinpath(writedir, "tpolygons.geojson"), table) - GeoTables.save(joinpath(writedir, "tpolygons.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpolygons.geojson"), table) + GeoTables.save(joinpath(datadir, "tpolygons.shp"), table, force = true) end @testset "multipolygons" begin table = GeoTables.load(joinpath(datadir,"path.shp")) - GeoTables.save(joinpath(writedir, "tpath.geojson"), table) - GeoTables.save(joinpath(writedir, "tpath.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tpath.geojson"), table) + GeoTables.save(joinpath(datadir, "tpath.shp"), table, force = true) table = GeoTables.load(joinpath(datadir,"zone.shp")) - GeoTables.save(joinpath(writedir, "tzone.geojson"), table) - GeoTables.save(joinpath(writedir, "tzone.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tzone.geojson"), table) + GeoTables.save(joinpath(datadir, "tzone.shp"), table, force = true) table = GeoTables.load(joinpath(datadir,"ne_110m_land.shp")) - GeoTables.save(joinpath(writedir, "tne_110m_land.geojson"), table) - GeoTables.save(joinpath(writedir, "tne_110m_land.shp"), table, force = true) + GeoTables.save(joinpath(datadir, "tne_110m_land.geojson"), table) + GeoTables.save(joinpath(datadir, "tne_110m_land.shp"), table, force = true) end end