From 928e88b69579b93fc92a4eb904b03af3f74c72fa Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 12:32:21 -0700 Subject: [PATCH 001/169] ignore .DS_Store files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 120d0431..0d6ff5ce 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ test/gdalworkshop/ test/ospy/ test/pyrasterio/ test/spatialite/ +.DS_Store From fd95b3fa5cc2673260aeed7e708c119ae2509aee Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 12:33:03 -0700 Subject: [PATCH 002/169] Return errors for unknown datatypes when looking up gdaltypes --- src/dataset.jl | 8 ++++---- src/types.jl | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/dataset.jl b/src/dataset.jl index 25a9c3ea..4b0f8233 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -198,7 +198,7 @@ function unsafe_create( options = StringList(C_NULL) ) result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - _GDALTYPE[dtype], options) + gdaltype(dtype), options) return Dataset(result) end @@ -212,7 +212,7 @@ function unsafe_create( options = StringList(C_NULL) ) result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - _GDALTYPE[dtype], options) + gdaltype(dtype), options) return Dataset(result) end @@ -256,7 +256,7 @@ function create( options = StringList(C_NULL) ) result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - _GDALTYPE[dtype], options) + gdaltype(dtype), options) return IDataset(result) end @@ -270,7 +270,7 @@ function create( options = StringList(C_NULL) ) result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - _GDALTYPE[dtype], options) + gdaltype(dtype), options) return IDataset(result) end diff --git a/src/types.jl b/src/types.jl index 1f35f39c..04e89da9 100644 --- a/src/types.jl +++ b/src/types.jl @@ -265,6 +265,9 @@ const _JLTYPE = Dict{GDAL.GDALDataType, DataType}( GDAL.GDT_Float32 => Float32, GDAL.GDT_Float64 => Float64) +"return the corresponding `GDAL.GDALDataType`." +datatype(gt::DataType) = get(_GDALTYPE, gt, error("Unknown DataType: $gt")) + const _GDALTYPE = Dict{DataType,GDAL.GDALDataType}( Any => GDAL.GDT_Unknown, UInt8 => GDAL.GDT_Byte, @@ -275,6 +278,11 @@ const _GDALTYPE = Dict{DataType,GDAL.GDALDataType}( Float32 => GDAL.GDT_Float32, Float64 => GDAL.GDT_Float64) +"return the corresponding `GDAL.GDALDataType`." +gdaltype(gt::DataType) = get(_GDALTYPE, gt) do + error("Unknown DataType: $gt") +end + "return the corresponding `DataType` in julia" const _FIELDTYPE = Dict{OGRFieldType, DataType}( GDAL.OFTInteger => Int32, From 52a183a4ac0b212bb0f53f093ba71aeca7639979 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 12:37:45 -0700 Subject: [PATCH 003/169] bugfix for looking up julia datatypes when given a gdaldatatype --- src/types.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/types.jl b/src/types.jl index 04e89da9..f17795d0 100644 --- a/src/types.jl +++ b/src/types.jl @@ -166,7 +166,7 @@ mutable struct RasterBand{T} <: AbstractRasterBand{T} ptr::GDALRasterBand end function RasterBand(ptr::GDALRasterBand) - t = _JLTYPE[GDAL.gdalgetrasterdatatype(ptr)] + t = datatype(GDAL.gdalgetrasterdatatype(ptr)) RasterBand{t}(ptr) end @@ -185,7 +185,7 @@ mutable struct IRasterBand{T} <: AbstractRasterBand{T} end function IRasterBand(ptr::GDALRasterBand; ownedby = Dataset()) - t = _JLTYPE[GDAL.gdalgetrasterdatatype(ptr)] + t = datatype(GDAL.gdalgetrasterdatatype(ptr)) IRasterBand{t}(ptr, ownedby=ownedby) end @@ -265,8 +265,10 @@ const _JLTYPE = Dict{GDAL.GDALDataType, DataType}( GDAL.GDT_Float32 => Float32, GDAL.GDT_Float64 => Float64) -"return the corresponding `GDAL.GDALDataType`." -datatype(gt::DataType) = get(_GDALTYPE, gt, error("Unknown DataType: $gt")) +"return the corresponding `DataType` in julia" +datatype(gt::GDAL.GDALDataType) = get(_JLTYPE, gt) do + error("Unknown GDAL.GDALDataType: $gt") +end const _GDALTYPE = Dict{DataType,GDAL.GDALDataType}( Any => GDAL.GDT_Unknown, @@ -278,9 +280,9 @@ const _GDALTYPE = Dict{DataType,GDAL.GDALDataType}( Float32 => GDAL.GDT_Float32, Float64 => GDAL.GDT_Float64) -"return the corresponding `GDAL.GDALDataType`." -gdaltype(gt::DataType) = get(_GDALTYPE, gt) do - error("Unknown DataType: $gt") +"return the corresponding `GDAL.GDALDataType`" +gdaltype(dt::DataType) = get(_GDALTYPE, dt) do + error("Unknown DataType: $dt") end "return the corresponding `DataType` in julia" From 95fb4db73caba6a37edbef92d222cb3b292528d6 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 12:48:49 -0700 Subject: [PATCH 004/169] throw informative error message for unknown field types --- src/tables.jl | 2 +- src/types.jl | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/tables.jl b/src/tables.jl index 0d6d6d13..2dfed7eb 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -14,7 +14,7 @@ function Tables.schema(layer::AbstractFeatureLayer) field_names, geom_names, featuredefn, fielddefns = schema_names(layer) ngeom = ArchGDAL.ngeom(featuredefn) geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) - field_types = (_FIELDTYPE[gettype(fielddefn)] for fielddefn in fielddefns) + field_types = (datatype(gettype(fielddefn)) for fielddefn in fielddefns) geom_types = (IGeometry for i in 1:ngeom) Tables.Schema((field_names..., geom_names...), (field_types..., geom_types...)) end diff --git a/src/types.jl b/src/types.jl index f17795d0..2024510e 100644 --- a/src/types.jl +++ b/src/types.jl @@ -255,7 +255,7 @@ GWKAverageOrModeAlg = GDAL.GWKAverageOrModeAlg OGRAxisOrientation = GDAL.OGRAxisOrientation "return the corresponding `DataType` in julia" -const _JLTYPE = Dict{GDAL.GDALDataType, DataType}( +const _JLTYPE = Dict{GDALDataType, DataType}( GDAL.GDT_Unknown => Any, GDAL.GDT_Byte => UInt8, GDAL.GDT_UInt16 => UInt16, @@ -266,11 +266,11 @@ const _JLTYPE = Dict{GDAL.GDALDataType, DataType}( GDAL.GDT_Float64 => Float64) "return the corresponding `DataType` in julia" -datatype(gt::GDAL.GDALDataType) = get(_JLTYPE, gt) do - error("Unknown GDAL.GDALDataType: $gt") +datatype(gt::GDALDataType) = get(_JLTYPE, gt) do + error("Unknown GDALDataType: $gt") end -const _GDALTYPE = Dict{DataType,GDAL.GDALDataType}( +const _GDALTYPE = Dict{DataType,GDALDataType}( Any => GDAL.GDT_Unknown, UInt8 => GDAL.GDT_Byte, UInt16 => GDAL.GDT_UInt16, @@ -302,6 +302,11 @@ const _FIELDTYPE = Dict{OGRFieldType, DataType}( GDAL.OFTInteger64 => Int64, GDAL.OFTInteger64List => Nothing) +"return the corresponding `DataType` in julia" +datatype(ft::OGRFieldType) = get(_FIELDTYPE, ft) do + error("Unknown OGRFieldType: $ft") +end + @enum(GDALOpenFlag, OF_ReadOnly = GDAL.GDAL_OF_READONLY, # 0x00 OF_Update = GDAL.GDAL_OF_UPDATE, # 0x01 From d09334d747d8c400b93f33bd3cac32cddb7e66d2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 14:30:55 -0700 Subject: [PATCH 005/169] Add instructions for managing dependencies --- Manifest.toml | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++ Project.toml | 1 + README.md | 41 ++++++++ 3 files changed, 303 insertions(+) create mode 100644 Manifest.toml diff --git a/Manifest.toml b/Manifest.toml new file mode 100644 index 00000000..9d538430 --- /dev/null +++ b/Manifest.toml @@ -0,0 +1,261 @@ +# This file is machine-generated - editing it directly is not advised + +[[ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + +[[Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[CEnum]] +git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.4.1" + +[[DataAPI]] +git-tree-sha1 = "dfb3b7e89e395be1e25c2ad6d7690dc29cc53b1d" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.6.0" + +[[DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[DiskArrays]] +git-tree-sha1 = "731967c22b99f606540c45a3773e92d336fd6963" +uuid = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" +version = "0.2.7" + +[[Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" + +[[Expat_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "1402e52fcda25064f51c77a9655ce8680b76acf0" +uuid = "2e619515-83b5-522b-bb60-26c02a35a201" +version = "2.2.7+6" + +[[GDAL]] +deps = ["CEnum", "GDAL_jll", "MozillaCACerts_jll", "PROJ_jll"] +git-tree-sha1 = "14dcb10bf90a1c912a24417c2aa55a69bcd93e49" +uuid = "add2ef01-049f-52c4-9ee2-e494f65e021a" +version = "1.2.1" + +[[GDAL_jll]] +deps = ["Artifacts", "Expat_jll", "GEOS_jll", "JLLWrappers", "LibCURL_jll", "LibSSH2_jll", "Libdl", "Libtiff_jll", "MbedTLS_jll", "OpenJpeg_jll", "PROJ_jll", "Pkg", "SQLite_jll", "Zlib_jll", "Zstd_jll", "libgeotiff_jll", "nghttp2_jll"] +git-tree-sha1 = "439c33eb4dfa74a43a1e96b1d758aeb3cbc33dc3" +uuid = "a7073274-a066-55f0-b90d-d619367d196c" +version = "300.202.100+0" + +[[GEOS_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "45d0ddfd29620ac9b2d1072801e90fb016c5f94c" +uuid = "d604d12d-fa86-5845-992e-78dc15976526" +version = "3.9.0+0" + +[[GeoFormatTypes]] +git-tree-sha1 = "bb75ce99c9d6fb2edd8ef8ee474991cdacf12221" +uuid = "68eda718-8dee-11e9-39e7-89f7f65f511f" +version = "0.3.0" + +[[GeoInterface]] +deps = ["RecipesBase"] +git-tree-sha1 = "38a649e6a52d1bea9844b382343630ac754c931c" +uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +version = "0.5.5" + +[[InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[JLLWrappers]] +deps = ["Preferences"] +git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.3.0" + +[[JpegTurbo_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "9aff0587d9603ea0de2c6f6300d9f9492bbefbd3" +uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" +version = "2.0.1+3" + +[[LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" + +[[LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" + +[[LibGit2]] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + +[[Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[Libtiff_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "291dd857901f94d683973cdf679984cdf73b56d0" +uuid = "89763e89-9b03-5906-acba-b20f662cd828" +version = "4.1.0+2" + +[[LinearAlgebra]] +deps = ["Libdl"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[LittleCMS_jll]] +deps = ["JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg"] +git-tree-sha1 = "e6ea89d915cdad8d264f7f9158c6664f879edcde" +uuid = "d3a379c0-f9a3-5b72-a4c0-6bf4d2e8af0f" +version = "2.9.0+0" + +[[Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" + +[[MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + +[[NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" + +[[OpenJpeg_jll]] +deps = ["Libdl", "Libtiff_jll", "LittleCMS_jll", "Pkg", "libpng_jll"] +git-tree-sha1 = "e330ffff1c6a593fa44cc40c29900bee82026406" +uuid = "643b3616-a352-519d-856d-80112ee9badc" +version = "2.3.1+0" + +[[PROJ_jll]] +deps = ["Artifacts", "JLLWrappers", "LibCURL_jll", "LibSSH2_jll", "Libdl", "Libtiff_jll", "MbedTLS_jll", "Pkg", "SQLite_jll", "Zlib_jll", "nghttp2_jll"] +git-tree-sha1 = "2435e91710d7f97f53ef7a4872bf1f948dc8e5f8" +uuid = "58948b4f-47e0-5654-a9ad-f609743f8632" +version = "700.202.100+0" + +[[Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" + +[[Preferences]] +deps = ["TOML"] +git-tree-sha1 = "ea79e4c9077208cd3bc5d29631a26bc0cff78902" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.2.1" + +[[Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[Random]] +deps = ["Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[RecipesBase]] +git-tree-sha1 = "b3fb709f3c97bfc6e948be68beeecb55a0b340ae" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.1.1" + +[[SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" + +[[SQLite_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] +git-tree-sha1 = "30c4dc94e2a00f4f02ea039df36067b32e187f3c" +uuid = "76ed43ae-9a5d-5a62-8c75-30186b810ce8" +version = "3.34.0+0" + +[[Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" + +[[TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"] +git-tree-sha1 = "c9d2d262e9a327be1f35844df25fe4561d258dc9" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.4.2" + +[[Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" + +[[Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" + +[[Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "2c1332c54931e83f8f94d310fa447fd743e8d600" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.4.8+0" + +[[libgeotiff_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libtiff_jll", "PROJ_jll", "Pkg"] +git-tree-sha1 = "a5cc2e3dd7b1c1e783a61b8ab7de03eebddfed60" +uuid = "06c338fa-64ff-565b-ac2f-249532af990e" +version = "1.6.0+1" + +[[libpng_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] +git-tree-sha1 = "6abbc424248097d69c0c87ba50fcb0753f93e0ee" +uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" +version = "1.6.37+6" + +[[nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" diff --git a/Project.toml b/Project.toml index 3faa6b2b..72c64e3e 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ desc = "A high level API for GDAL - Geospatial Data Abstraction Library" version = "0.6.0" [deps] +CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a" diff --git a/README.md b/README.md index 6d77bf95..bb45b832 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,44 @@ To test if it is installed correctly, ```julia pkg> test ArchGDAL ``` + +## Dependencies +To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1.6/environments/): + +1. Navigate to the directory corresponding to the package: + +```julia +shell> cd /Users/yeesian/.julia/dev/ArchGDAL +/Users/yeesian/.julia/dev/ArchGDAL +``` + +2. Activate the environment corresponding to `Project.toml`): + +```julia +(@v1.6) pkg> activate + Activating environment at `~/.julia/environments/v1.6/Project.toml` +``` + +3. Manage the dependencies using Pkg in https://pkgdocs.julialang.org/v1.6/managing-packages/, e.g. + +```julia +(ArchGDAL) pkg> st + Project ArchGDAL v0.6.0 + Status `~/.julia/dev/ArchGDAL/Project.toml` + [3c3547ce] DiskArrays + [add2ef01] GDAL + [68eda718] GeoFormatTypes + [cf35fbd7] GeoInterface + [bd369af6] Tables + [ade2ca70] Dates + +(ArchGDAL) pkg> add CEnum + Resolving package versions... + Updating `~/.julia/dev/ArchGDAL/Project.toml` + [fa961155] + CEnum v0.4.1 + [3c3547ce] + DiskArrays v0.2.7 + [add2ef01] + GDAL v1.2.1 + [68eda718] + GeoFormatTypes v0.3.0 + [cf35fbd7] + GeoInterface v0.5.5 + [bd369af6] + Tables v1.4.2 +``` \ No newline at end of file From d31702961810b8be0b40cf5ced2a530d673427d1 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 15:35:15 -0700 Subject: [PATCH 006/169] remove cenum dependency --- Manifest.toml | 261 -------------------------------------------------- Project.toml | 1 - 2 files changed, 262 deletions(-) delete mode 100644 Manifest.toml diff --git a/Manifest.toml b/Manifest.toml deleted file mode 100644 index 9d538430..00000000 --- a/Manifest.toml +++ /dev/null @@ -1,261 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -[[ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" - -[[Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" - -[[Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[CEnum]] -git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9" -uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" -version = "0.4.1" - -[[DataAPI]] -git-tree-sha1 = "dfb3b7e89e395be1e25c2ad6d7690dc29cc53b1d" -uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.6.0" - -[[DataValueInterfaces]] -git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" -uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" -version = "1.0.0" - -[[Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[DiskArrays]] -git-tree-sha1 = "731967c22b99f606540c45a3773e92d336fd6963" -uuid = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" -version = "0.2.7" - -[[Downloads]] -deps = ["ArgTools", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" - -[[Expat_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "1402e52fcda25064f51c77a9655ce8680b76acf0" -uuid = "2e619515-83b5-522b-bb60-26c02a35a201" -version = "2.2.7+6" - -[[GDAL]] -deps = ["CEnum", "GDAL_jll", "MozillaCACerts_jll", "PROJ_jll"] -git-tree-sha1 = "14dcb10bf90a1c912a24417c2aa55a69bcd93e49" -uuid = "add2ef01-049f-52c4-9ee2-e494f65e021a" -version = "1.2.1" - -[[GDAL_jll]] -deps = ["Artifacts", "Expat_jll", "GEOS_jll", "JLLWrappers", "LibCURL_jll", "LibSSH2_jll", "Libdl", "Libtiff_jll", "MbedTLS_jll", "OpenJpeg_jll", "PROJ_jll", "Pkg", "SQLite_jll", "Zlib_jll", "Zstd_jll", "libgeotiff_jll", "nghttp2_jll"] -git-tree-sha1 = "439c33eb4dfa74a43a1e96b1d758aeb3cbc33dc3" -uuid = "a7073274-a066-55f0-b90d-d619367d196c" -version = "300.202.100+0" - -[[GEOS_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "45d0ddfd29620ac9b2d1072801e90fb016c5f94c" -uuid = "d604d12d-fa86-5845-992e-78dc15976526" -version = "3.9.0+0" - -[[GeoFormatTypes]] -git-tree-sha1 = "bb75ce99c9d6fb2edd8ef8ee474991cdacf12221" -uuid = "68eda718-8dee-11e9-39e7-89f7f65f511f" -version = "0.3.0" - -[[GeoInterface]] -deps = ["RecipesBase"] -git-tree-sha1 = "38a649e6a52d1bea9844b382343630ac754c931c" -uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" -version = "0.5.5" - -[[InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[IteratorInterfaceExtensions]] -git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" -uuid = "82899510-4779-5014-852e-03e436cf321d" -version = "1.0.0" - -[[JLLWrappers]] -deps = ["Preferences"] -git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e" -uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.3.0" - -[[JpegTurbo_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "9aff0587d9603ea0de2c6f6300d9f9492bbefbd3" -uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" -version = "2.0.1+3" - -[[LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" - -[[LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" - -[[LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "MbedTLS_jll"] -uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" - -[[Libdl]] -uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" - -[[Libtiff_jll]] -deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"] -git-tree-sha1 = "291dd857901f94d683973cdf679984cdf73b56d0" -uuid = "89763e89-9b03-5906-acba-b20f662cd828" -version = "4.1.0+2" - -[[LinearAlgebra]] -deps = ["Libdl"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - -[[LittleCMS_jll]] -deps = ["JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg"] -git-tree-sha1 = "e6ea89d915cdad8d264f7f9158c6664f879edcde" -uuid = "d3a379c0-f9a3-5b72-a4c0-6bf4d2e8af0f" -version = "2.9.0+0" - -[[Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" - -[[MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" - -[[NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" - -[[OpenJpeg_jll]] -deps = ["Libdl", "Libtiff_jll", "LittleCMS_jll", "Pkg", "libpng_jll"] -git-tree-sha1 = "e330ffff1c6a593fa44cc40c29900bee82026406" -uuid = "643b3616-a352-519d-856d-80112ee9badc" -version = "2.3.1+0" - -[[PROJ_jll]] -deps = ["Artifacts", "JLLWrappers", "LibCURL_jll", "LibSSH2_jll", "Libdl", "Libtiff_jll", "MbedTLS_jll", "Pkg", "SQLite_jll", "Zlib_jll", "nghttp2_jll"] -git-tree-sha1 = "2435e91710d7f97f53ef7a4872bf1f948dc8e5f8" -uuid = "58948b4f-47e0-5654-a9ad-f609743f8632" -version = "700.202.100+0" - -[[Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" - -[[Preferences]] -deps = ["TOML"] -git-tree-sha1 = "ea79e4c9077208cd3bc5d29631a26bc0cff78902" -uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.2.1" - -[[Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[Random]] -deps = ["Serialization"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[RecipesBase]] -git-tree-sha1 = "b3fb709f3c97bfc6e948be68beeecb55a0b340ae" -uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" -version = "1.1.1" - -[[SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" - -[[SQLite_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] -git-tree-sha1 = "30c4dc94e2a00f4f02ea039df36067b32e187f3c" -uuid = "76ed43ae-9a5d-5a62-8c75-30186b810ce8" -version = "3.34.0+0" - -[[Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" - -[[TableTraits]] -deps = ["IteratorInterfaceExtensions"] -git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" -uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" -version = "1.0.1" - -[[Tables]] -deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"] -git-tree-sha1 = "c9d2d262e9a327be1f35844df25fe4561d258dc9" -uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.4.2" - -[[Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" - -[[Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" - -[[Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" - -[[Zstd_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "2c1332c54931e83f8f94d310fa447fd743e8d600" -uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" -version = "1.4.8+0" - -[[libgeotiff_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Libtiff_jll", "PROJ_jll", "Pkg"] -git-tree-sha1 = "a5cc2e3dd7b1c1e783a61b8ab7de03eebddfed60" -uuid = "06c338fa-64ff-565b-ac2f-249532af990e" -version = "1.6.0+1" - -[[libpng_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] -git-tree-sha1 = "6abbc424248097d69c0c87ba50fcb0753f93e0ee" -uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" -version = "1.6.37+6" - -[[nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" - -[[p7zip_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" diff --git a/Project.toml b/Project.toml index 72c64e3e..3faa6b2b 100644 --- a/Project.toml +++ b/Project.toml @@ -6,7 +6,6 @@ desc = "A high level API for GDAL - Geospatial Data Abstraction Library" version = "0.6.0" [deps] -CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a" From de98ada2a6a82d46a1d4e57cdb625ee1f2f61834 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 15:43:21 -0700 Subject: [PATCH 007/169] [Breaking change] Maintain our own OGRFieldType This will be part of a broader move away from GDAL's enums so that the interface for ArchGDAL is "closed" (i.e. takes and return ArchGDAL types) and not require users to import GDAL. * We need to be careful to maintain interoperability with GDAL's enums, so I've defined corresponding convert() methods, and methods to map between the different types. * I also took the opportunity to update the _FIELDTYPE dictionary now that I see how it's used (in `src/tables.jl`), and will commit the code for supporting the corresponding types as part of the same PR. --- src/ogr/feature.jl | 22 ++++----- src/ogr/fielddefn.jl | 2 +- src/types.jl | 95 +++++++++++++++++++++++++++++++------ test/test_feature.jl | 16 +++---- test/test_fielddefn.jl | 18 +++---- test/test_gdal_tutorials.jl | 6 +-- test/test_ospy_examples.jl | 2 +- test/test_types.jl | 20 +++++--- 8 files changed, 127 insertions(+), 54 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 6d0f0a7b..81034c00 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -353,21 +353,21 @@ end getdefault(feature::Feature, i::Integer) = getdefault(getfielddefn(feature, i)) -const _FETCHFIELD = Dict{GDAL.OGRFieldType, Function}( - GDAL.OFTInteger => asint, #0 - GDAL.OFTIntegerList => asintlist, #1 - GDAL.OFTReal => asdouble, #2 - GDAL.OFTRealList => asdoublelist, #3 - GDAL.OFTString => asstring, #4 - GDAL.OFTStringList => asstringlist, #5 +const _FETCHFIELD = Dict{OGRFieldType, Function}( + OFTInteger => asint, #0 + OFTIntegerList => asintlist, #1 + OFTReal => asdouble, #2 + OFTRealList => asdoublelist, #3 + OFTString => asstring, #4 + OFTStringList => asstringlist, #5 # const OFTWideString = (UInt32)(6) # const OFTWideStringList = (UInt32)(7) - GDAL.OFTBinary => asbinary, #8 + OFTBinary => asbinary, #8 # const OFTDate = (UInt32)(9) # const OFTTime = (UInt32)(10) - GDAL.OFTDateTime => asdatetime, #11 - GDAL.OFTInteger64 => asint64, #12 - GDAL.OFTInteger64List => asint64list #13 + OFTDateTime => asdatetime, #11 + OFTInteger64 => asint64, #12 + OFTInteger64List => asint64list #13 # const OFTMaxType = (UInt32)(13) ) diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index 959d38b3..99c13760 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -30,7 +30,7 @@ end getname(fielddefn::AbstractFieldDefn) = GDAL.ogr_fld_getnameref(fielddefn.ptr) "Fetch the type of this field." -gettype(fielddefn::AbstractFieldDefn) = GDAL.ogr_fld_gettype(fielddefn.ptr) +gettype(fielddefn::AbstractFieldDefn) = gdaltype(GDAL.ogr_fld_gettype(fielddefn.ptr)) "Set the type of this field." function settype!(fielddefn::FieldDefn, etype::OGRFieldType) diff --git a/src/types.jl b/src/types.jl index 2024510e..14f65dc1 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,4 +1,5 @@ import DiskArrays: AbstractDiskArray +import Base.convert const GDALColorTable = GDAL.GDALColorTableH const GDALCoordTransform = GDAL.OGRCoordinateTransformationH const GDALDataset = GDAL.GDALDatasetH @@ -241,7 +242,6 @@ GDALGridAlgorithm = GDAL.GDALGridAlgorithm OGRwkbGeometryType = GDAL.OGRwkbGeometryType OGRwkbVariant = GDAL.OGRwkbVariant OGRwkbByteOrder = GDAL.OGRwkbByteOrder -OGRFieldType = GDAL.OGRFieldType OGRFieldSubType = GDAL.OGRFieldSubType OGRJustification = GDAL.OGRJustification OGRSTClassId = GDAL.OGRSTClassId @@ -285,22 +285,87 @@ gdaltype(dt::DataType) = get(_GDALTYPE, dt) do error("Unknown DataType: $dt") end +@enum(OGRFieldType, + OFTInteger = Int32(GDAL.OFTInteger), + OFTIntegerList = Int32(GDAL.OFTIntegerList), + OFTReal = Int32(GDAL.OFTReal), + OFTRealList = Int32(GDAL.OFTRealList), + OFTString = Int32(GDAL.OFTString), + OFTStringList = Int32(GDAL.OFTStringList), + OFTWideString = Int32(GDAL.OFTWideString), + OFTWideStringList = Int32(GDAL.OFTWideStringList), + OFTBinary = Int32(GDAL.OFTBinary), + OFTDate = Int32(GDAL.OFTDate), + OFTTime = Int32(GDAL.OFTTime), + OFTDateTime = Int32(GDAL.OFTDateTime), + OFTInteger64 = Int32(GDAL.OFTInteger64), + OFTInteger64List = Int32(GDAL.OFTInteger64List), + # OFTMaxType = Int32(GDAL.OFTMaxType), # unsupported +) + "return the corresponding `DataType` in julia" const _FIELDTYPE = Dict{OGRFieldType, DataType}( - GDAL.OFTInteger => Int32, - GDAL.OFTIntegerList => Nothing, - GDAL.OFTReal => Float64, - GDAL.OFTRealList => Nothing, - GDAL.OFTString => String, - GDAL.OFTStringList => Nothing, - GDAL.OFTWideString => Nothing, # deprecated - GDAL.OFTWideStringList => Nothing, # deprecated - GDAL.OFTBinary => Nothing, - GDAL.OFTDate => Date, - GDAL.OFTTime => Nothing, - GDAL.OFTDateTime => DateTime, - GDAL.OFTInteger64 => Int64, - GDAL.OFTInteger64List => Nothing) + OFTInteger => Int32, + OFTIntegerList => Vector{Int32}, + OFTReal => Float64, + OFTRealList => Vector{Float64}, + OFTString => String, + OFTStringList => Vector{String}, + OFTWideString => Nothing, # deprecated + OFTWideStringList => Nothing, # deprecated + OFTBinary => Bool, + OFTDate => Dates.Date, + OFTTime => Dates.Time, + OFTDateTime => Dates.DateTime, + OFTInteger64 => Int64, + OFTInteger64List => Vector{Int64}, + # OFTMaxType => Nothing # unsupported +) + +const _GDALFIELDTYPE = Dict{GDAL.OGRFieldType, OGRFieldType}( + GDAL.OFTInteger => OFTInteger, + GDAL.OFTIntegerList => OFTIntegerList, + GDAL.OFTReal => OFTReal, + GDAL.OFTRealList => OFTRealList, + GDAL.OFTString => OFTString, + GDAL.OFTStringList => OFTStringList, + GDAL.OFTWideString => OFTWideString, + GDAL.OFTWideStringList => OFTWideStringList, + GDAL.OFTBinary => OFTBinary, + GDAL.OFTDate => OFTDate, + GDAL.OFTTime => OFTTime, + GDAL.OFTDateTime => OFTDateTime, + GDAL.OFTInteger64 => OFTInteger64, + GDAL.OFTInteger64List => OFTInteger64List, + # GDAL.OFTMaxType => OFTMaxType, # unsupported +) + +const _GDALFIELDTYPES = Dict{OGRFieldType, GDAL.OGRFieldType}( + OFTInteger => GDAL.OFTInteger, + OFTIntegerList => GDAL.OFTIntegerList, + OFTReal => GDAL.OFTReal, + OFTRealList => GDAL.OFTRealList, + OFTString => GDAL.OFTString, + OFTStringList => GDAL.OFTStringList, + OFTWideString => GDAL.OFTWideString, + OFTWideStringList => GDAL.OFTWideStringList, + OFTBinary => GDAL.OFTBinary, + OFTDate => GDAL.OFTDate, + OFTTime => GDAL.OFTTime, + OFTDateTime => GDAL.OFTDateTime, + OFTInteger64 => GDAL.OFTInteger64, + OFTInteger64List => GDAL.OFTInteger64List, + # OFTMaxType => GDAL.OFTMaxType, # unsupported +) + +convert(::Type{GDAL.OGRFieldType}, ft::OGRFieldType) = get(_GDALFIELDTYPES, ft) do + error("Unknown GDAL.OGRFieldType: $ft") +end + +"returns the `OGRFieldType` in julia" +gdaltype(ft::GDAL.OGRFieldType) = get(_GDALFIELDTYPE, ft) do + error("Unknown GDAL.OGRFieldType: $ft") +end "return the corresponding `DataType` in julia" datatype(ft::OGRFieldType) = get(_FIELDTYPE, ft) do diff --git a/test/test_feature.jl b/test/test_feature.jl index c0d31133..fca37d4d 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -91,28 +91,28 @@ end @testset "In-Memory Driver" begin AG.create(AG.getdriver("MEMORY")) do output layer = AG.createlayer(dataset = output, geom=GDAL.wkbPolygon) - AG.createfielddefn("int64field", GDAL.OFTInteger64) do fielddefn + AG.createfielddefn("int64field", AG.OFTInteger64) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("doublefield", GDAL.OFTReal) do fielddefn + AG.createfielddefn("doublefield", AG.OFTReal) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("intlistfield", GDAL.OFTIntegerList) do fielddefn + AG.createfielddefn("intlistfield", AG.OFTIntegerList) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("int64listfield", GDAL.OFTInteger64List) do fielddefn + AG.createfielddefn("int64listfield", AG.OFTInteger64List) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("doublelistfield", GDAL.OFTRealList) do fielddefn + AG.createfielddefn("doublelistfield", AG.OFTRealList) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("stringlistfield", GDAL.OFTStringList) do fielddefn + AG.createfielddefn("stringlistfield", AG.OFTStringList) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("binaryfield", GDAL.OFTBinary) do fielddefn + AG.createfielddefn("binaryfield", AG.OFTBinary) do fielddefn AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("datetimefield", GDAL.OFTDateTime) do fielddefn + AG.createfielddefn("datetimefield", AG.OFTDateTime) do fielddefn AG.addfielddefn!(layer, fielddefn) end AG.createfeature(layer) do feature diff --git a/test/test_fielddefn.jl b/test/test_fielddefn.jl index 75c6f1a5..c026f349 100644 --- a/test/test_fielddefn.jl +++ b/test/test_fielddefn.jl @@ -3,15 +3,15 @@ import GDAL import ArchGDAL; const AG = ArchGDAL @testset "Tests for field defn" begin - AG.createfielddefn("fieldname",GDAL.OFTInteger) do fd + AG.createfielddefn("fieldname", AG.OFTInteger) do fd @test sprint(print, fd) == "fieldname (OFTInteger)" @test AG.getname(fd) == "fieldname" AG.setname!(fd, "newname") @test AG.getname(fd) == "newname" - @test AG.gettype(fd) == GDAL.OFTInteger - AG.settype!(fd, GDAL.OFTDate) - @test AG.gettype(fd) == GDAL.OFTDate - AG.settype!(fd, GDAL.OFTInteger) + @test AG.gettype(fd) == AG.OFTInteger + AG.settype!(fd, AG.OFTDate) + @test AG.gettype(fd) == AG.OFTDate + AG.settype!(fd, AG.OFTInteger) @test AG.getsubtype(fd) == GDAL.OFSTNone AG.setsubtype!(fd, GDAL.OFSTInt16) @test AG.getsubtype(fd) == GDAL.OFSTInt16 @@ -27,9 +27,9 @@ import ArchGDAL; const AG = ArchGDAL @test AG.getprecision(fd) == 0 AG.setprecision!(fd, 20) @test AG.getprecision(fd) == 20 - AG.setparams!(fd, "finalname", GDAL.OFTDate, nwidth=5, nprecision=2, + AG.setparams!(fd, "finalname", AG.OFTDate, nwidth=5, nprecision=2, justify=GDAL.OJRight) - @test AG.gettype(fd) == GDAL.OFTDate + @test AG.gettype(fd) == AG.OFTDate @test AG.getname(fd) == "finalname" @test AG.getsubtype(fd) == GDAL.OFSTNone @test AG.getjustify(fd) == GDAL.OJRight @@ -99,7 +99,7 @@ end @test AG.nreference(fd) == 1 AG.dereference(fd) @test AG.nreference(fd) == 0 - AG.createfielddefn("fieldname",GDAL.OFTInteger) do fielddef + AG.createfielddefn("fieldname", AG.OFTInteger) do fielddef @test AG.nfield(fd) == 0 AG.addfielddefn!(fd, fielddef) @test AG.nfield(fd) == 1 @@ -107,7 +107,7 @@ end @test AG.nfield(fd) == 2 AG.addfielddefn!(fd, fielddef) @test AG.nfield(fd) == 3 - AG.createfielddefn("newfield",GDAL.OFTInteger) do fielddef2 + AG.createfielddefn("newfield", AG.OFTInteger) do fielddef2 AG.addfielddefn!(fd, fielddef2) @test AG.nfield(fd) == 4 AG.getname(AG.getfielddefn(fd,0)) == "fieldname" diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index da6bf939..ab9d9454 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -80,9 +80,9 @@ end featuredefn = AG.layerdefn(layer) @test AG.nfield(featuredefn) == 2 fielddefn = AG.getfielddefn(featuredefn, 0) - @test AG.gettype(fielddefn) == GDAL.OFTReal + @test AG.gettype(fielddefn) == AG.OFTReal fielddefn = AG.getfielddefn(featuredefn, 1) - @test AG.gettype(fielddefn) == GDAL.OFTString + @test AG.gettype(fielddefn) == AG.OFTString AG.nextfeature(layer) do feature @test AG.asdouble(feature, 0) ≈ 2.0 @@ -108,7 +108,7 @@ end dataset = dataset, geom = GDAL.wkbPoint ) - AG.addfielddefn!(layer, "Name", GDAL.OFTString, nwidth = 32) + AG.addfielddefn!(layer, "Name", AG.OFTString, nwidth = 32) featuredefn = AG.layerdefn(layer) @test AG.getname(featuredefn) == "point_out" @test AG.nfeature(layer) == 0 diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index 5c827b12..59589482 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -154,7 +154,7 @@ end Layer: hw2a Geometry 0 (): [wkbPolygon] """ - AG.createfielddefn("name", GDAL.OFTString) do fielddefn + AG.createfielddefn("name", AG.OFTString) do fielddefn AG.setwidth!(fielddefn, 30) AG.addfielddefn!(layer, fielddefn) end diff --git a/test/test_types.jl b/test/test_types.jl index 71d1c1e8..ffc5164e 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -16,6 +16,11 @@ import ArchGDAL; const AG = ArchGDAL @test AG.typeunion(GDAL.GDT_UInt16, GDAL.GDT_Byte) == GDAL.GDT_UInt16 @test AG.iscomplex(GDAL.GDT_Float32) == false + + @test AG.datatype(GDAL.GDT_Int16) == Int16 + @test_throws ErrorException("Unknown GDALDataType: GDT_TypeCount") AG.datatype(GDAL.GDT_TypeCount) + @test AG.gdaltype(Int16) == GDAL.GDT_Int16 + @test_throws ErrorException("Unknown DataType: String") AG.gdaltype(String) end @testset "GDAL Colors and Palettes" begin @@ -36,14 +41,17 @@ import ArchGDAL; const AG = ArchGDAL end @testset "GDAL Field Types" begin - @test AG.getname(GDAL.OFTString) == "String" - @test AG.getname(GDAL.OFTIntegerList) == "IntegerList" + @test AG.getname(AG.OFTString) == "String" + @test AG.getname(AG.OFTIntegerList) == "IntegerList" @test AG.getname(GDAL.OFSTBoolean) == "Boolean" @test AG.getname(GDAL.OFSTFloat32) == "Float32" - @test AG.arecompatible(GDAL.OFTReal, GDAL.OFSTNone) == true - @test AG.arecompatible(GDAL.OFTReal, GDAL.OFSTBoolean) == false - @test AG.arecompatible(GDAL.OFTReal, GDAL.OFSTInt16) == false - @test AG.arecompatible(GDAL.OFTReal, GDAL.OFSTFloat32) == true + @test AG.arecompatible(AG.OFTReal, GDAL.OFSTNone) == true + @test AG.arecompatible(AG.OFTReal, GDAL.OFSTBoolean) == false + @test AG.arecompatible(AG.OFTReal, GDAL.OFSTInt16) == false + @test AG.arecompatible(AG.OFTReal, GDAL.OFSTFloat32) == true + + @test AG.datatype(AG.OFTString) == String + @test AG.gdaltype(GDAL.OFTMaxType) == AG.OFTInteger64List end end From 36085e9442dd6e0f72212aee5cd9b91893614db9 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 17:08:13 -0700 Subject: [PATCH 008/169] [stylistic] Require explicit return statements and enforce maxcolumnwidth=80 1. When writing the return statements, return should be at the top-level, rather than being nested inside e.g. an if-statement. * The convention of explicit returns is something that's been on my mind for a long time, and I think it's net healthier (when developing code) to be explicit about what's being returned to reduce on the number of gotchas when using it (e.g. in https://github.com/yeesian/ArchGDAL.jl/issues/171). 2. Return `nothing` upon destroying a GDAL object (rather than allowing users to encounter and depend on potentially dangerous behavior per https://www.hyrumslaw.com/) 3. The max columnwidth of 80char is somewhat arbitrary but most of the codebase is already in alignment, so I just want to bring it to 100% to reduce on the number of stylistic rules that we're still ambiguous about. --- src/ArchGDAL.jl | 1 + src/base/display.jl | 17 ++- src/base/iterators.jl | 17 +-- src/context.jl | 36 +++--- src/convert.jl | 25 ++-- src/dataset.jl | 39 +++--- src/driver.jl | 6 +- src/gcp.jl | 12 +- src/geointerface.jl | 35 +++--- src/ogr/feature.jl | 56 +++++---- src/ogr/featuredefn.jl | 11 +- src/ogr/featurelayer.jl | 90 +++++++------- src/ogr/fielddefn.jl | 21 ++-- src/ogr/geometry.jl | 10 +- src/ogr/styletable.jl | 6 +- src/raster/array.jl | 118 +++++++++++------- src/raster/colortable.jl | 6 +- src/raster/rasterattributetable.jl | 10 +- src/raster/rasterband.jl | 24 ++-- src/raster/rasterio.jl | 26 ++-- src/spatialref.jl | 187 +++++++++++++++++++---------- test/test_array.jl | 2 +- 22 files changed, 466 insertions(+), 289 deletions(-) diff --git a/src/ArchGDAL.jl b/src/ArchGDAL.jl index 1bb05c96..69acd1b8 100644 --- a/src/ArchGDAL.jl +++ b/src/ArchGDAL.jl @@ -46,6 +46,7 @@ module ArchGDAL function __init__() DRIVER_MANAGER[] = DriverManager() + return nothing end end # module diff --git a/src/base/display.jl b/src/base/display.jl index 43b0225f..0fc761f7 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -1,6 +1,7 @@ function Base.show(io::IO, drv::Driver) drv.ptr == C_NULL && (return print(io, "NULL Driver")) print(io, "Driver: $(shortname(drv))/$(longname(drv))") + return io end function Base.show(io::IO, dataset::AbstractDataset) @@ -44,12 +45,14 @@ function Base.show(io::IO, dataset::AbstractDataset) end end end + return io end #Add method to avoid show from DiskArrays Base.show(io::IO, raster::RasterDataset) = show(io, raster.ds) -Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset) = show(io, raster.ds) +Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset) = + show(io, raster.ds) function summarize(io::IO, rasterband::AbstractRasterBand) rasterband.ptr == C_NULL && (return print(io, "NULL RasterBand")) @@ -60,9 +63,11 @@ function summarize(io::IO, rasterband::AbstractRasterBand) i = indexof(rasterband) pxtype = pixeltype(rasterband) println(io, "[$access] Band $i ($color): $xsize x $ysize ($pxtype)") + return io end -Base.show(io::IO, rasterband::AbstractRasterBand) = show(io, "text/plain", rasterband) +Base.show(io::IO, rasterband::AbstractRasterBand) = + show(io, "text/plain", rasterband) function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand) rasterband.ptr == C_NULL && (return print(io, "NULL RasterBand")) @@ -81,6 +86,7 @@ function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand) print(io, "($(i-1)) $(width(ovr_band))x$(height(ovr_band)) ") i % 3 == 0 && print(io, "\n ") end + return io end # assumes that the layer is reset, and will reset it after display @@ -143,6 +149,7 @@ function Base.show(io::IO, layer::AbstractFeatureLayer) resetreading!(layer) end n > 5 && print(io, "...\n Number of Fields: $n") + return io end function Base.show(io::IO, featuredefn::AbstractFeatureDefn) @@ -162,16 +169,19 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn) println(io, " Field (index $(i-1)): $fd") end n > 5 && print(io, "...\n Number of Fields: $n") + return io end function Base.show(io::IO, fd::AbstractFieldDefn) fd.ptr == C_NULL && (return print(io, "NULL FieldDefn")) print(io, "$(getname(fd)) ($(gettype(fd)))") + return io end function Base.show(io::IO, gfd::AbstractGeomFieldDefn) gfd.ptr == C_NULL && (return print(io, "NULL GeomFieldDefn")) print(io, "$(getname(gfd)) ($(gettype(gfd)))") + return io end function Base.show(io::IO, feature::Feature) @@ -190,6 +200,7 @@ function Base.show(io::IO, feature::Feature) println(io, "$(getfield(feature, i-1))") end n > 10 && print(io, "...\n Number of Fields: $n") + return io end function Base.show(io::IO, spref::AbstractSpatialRef) @@ -202,6 +213,7 @@ function Base.show(io::IO, spref::AbstractSpatialRef) else print(io, "Spatial Reference System: $projstr") end + return io end function Base.show(io::IO, geom::AbstractGeometry) @@ -219,4 +231,5 @@ function Base.show(io::IO, geom::AbstractGeometry) else print(io, "Geometry: $(getgeomtype(geom))") end + return io end diff --git a/src/base/iterators.jl b/src/base/iterators.jl index fe563610..653725ce 100644 --- a/src/base/iterators.jl +++ b/src/base/iterators.jl @@ -2,11 +2,11 @@ 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 + return if ptr == C_NULL resetreading!(layer) - return nothing + nothing else - return (Feature(ptr), state+1) + (Feature(ptr), state+1) end end @@ -30,7 +30,7 @@ function blocks(raster::AbstractRasterBand) cols = width(raster) ni = ceil(Cint, rows / ybsize) nj = ceil(Cint, cols / xbsize) - BlockIterator(rows, cols, ni, nj, ni * nj, xbsize, ybsize) + return BlockIterator(rows, cols, ni, nj, ni * nj, xbsize, ybsize) end function Base.iterate(obj::BlockIterator, iter::Int=0) @@ -47,7 +47,7 @@ function Base.iterate(obj::BlockIterator, iter::Int=0) else obj.cols - j * obj.xbsize end - (((i, j), (nrows, ncols)), iter+1) + return (((i, j), (nrows, ncols)), iter+1) end struct WindowIterator @@ -66,7 +66,10 @@ function Base.iterate(obj::WindowIterator, iter::Int=0) 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) + return ( + ((1:ncols) .+ j * handle.xbsize, (1:nrows) .+ i * handle.ybsize), + iter + ) end mutable struct BufferIterator{T <: Real} @@ -76,7 +79,7 @@ mutable struct BufferIterator{T <: Real} end function bufferwindows(raster::AbstractRasterBand) - BufferIterator( + return BufferIterator( raster, windows(raster), Array{pixeltype(raster)}(undef, blocksize(raster)...) diff --git a/src/context.jl b/src/context.jl index 2fbb150b..1bb2ac6a 100644 --- a/src/context.jl +++ b/src/context.jl @@ -14,11 +14,13 @@ function environment( # # (ref https://github.com/mapbox/rasterio/pull/997#issuecomment-287117289) globalsettings = Dict(k => getconfigoption(k) for (k,v) in globalconfig) - localsettings = Dict(k => getthreadconfigoption(k) for (k,v) in threadconfig) + localsettings = Dict( + k => getthreadconfigoption(k) for (k,v) in threadconfig + ) for (k,v) in threadconfig; setthreadconfigoption(k, v) end for (k,v) in globalconfig; setconfigoption(k, v) end - try + return try f() finally # Restore previous settings @@ -41,7 +43,7 @@ end function executesql(f::Function, dataset::Dataset, args...) result = unsafe_executesql(dataset, args...) - try + return try f(result) finally releaseresultset(dataset, result) @@ -57,7 +59,7 @@ function createfeature(f::Function, featuredefn::FeatureDefn) # if we do not artificially increase the reference, then destroy(feature) # will release the featuredefn, when we're going to handle it ourselves # later. Therefore we dereference (rather than release) the featuredefn. - try + return try f(feature) finally destroy(feature) @@ -66,7 +68,8 @@ function createfeature(f::Function, featuredefn::FeatureDefn) end """ - addfielddefn!(layer::AbstractFeatureLayer, name, etype::OGRFieldType; ) + addfielddefn!(layer::AbstractFeatureLayer, name, etype::OGRFieldType; + ) Create a new field on a layer. @@ -110,7 +113,7 @@ function addfielddefn!( justify = justify) addfielddefn!(layer, fielddefn) destroy(fielddefn) - layer + return layer end function addfielddefn( @@ -126,7 +129,7 @@ function addfielddefn( fielddefn = unsafe_createfielddefn(name, etype) setparams!(fielddefn, name, etype, nwidth = nwidth, nprecision = nprecision, justify = justify) - try + return try f(fielddefn) addfielddefn!(layer, fielddefn) finally @@ -135,7 +138,8 @@ function addfielddefn( end """ - writegeomdefn!(layer::AbstractFeatureLayer, name, etype::OGRwkbGeometryType, approx=false) + writegeomdefn!(layer::AbstractFeatureLayer, name, etype::OGRwkbGeometryType, + approx=false) Write a new geometry field on a layer. @@ -181,7 +185,7 @@ function writegeomdefn( approx::Bool = false ) geomdefn = unsafe_creategeomdefn(name, etype) - try + return try f(geomdefn) addgeomdefn!(layer, geomdefn) finally @@ -202,17 +206,17 @@ for gdalfunc in ( :gdalbuildvrt, :gdaldem, :gdalgrid, :gdalnearblack, :gdalrasterize, :gdaltranslate, :gdalvectortranslate, :gdalwarp, :getband, :getcolortable, :getfeature, :getgeom, :getlayer, :getmaskband, - :getoverview, :getpart, :getspatialref, :importCRS, :intersection, :importEPSG, - :importEPSGA, :importESRI, :importPROJ4, :importWKT, :importXML, - :importURL, :lineargeom, :newspatialref, :nextfeature, :pointalongline, - :pointonsurface, :polygonfromedges, :polygonize, :read, :sampleoverview, - :simplify, :simplifypreservetopology, :symdifference, :union, :update, - :readraster, + :getoverview, :getpart, :getspatialref, :importCRS, :intersection, + :importEPSG, :importEPSGA, :importESRI, :importPROJ4, :importWKT, + :importXML, :importURL, :lineargeom, :newspatialref, :nextfeature, + :pointalongline, :pointonsurface, :polygonfromedges, :polygonize, :read, + :sampleoverview, :simplify, :simplifypreservetopology, :symdifference, + :union, :update, :readraster, ) eval(quote function $(gdalfunc)(f::Function, args...; kwargs...) obj = $(Symbol("unsafe_$gdalfunc"))(args...; kwargs...) - try + return try f(obj) finally destroy(obj) diff --git a/src/convert.jl b/src/convert.jl index 260f3d6d..6e4dfa1b 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -7,20 +7,25 @@ source::GeoFormatTypes.GeoFormat ) -Convert a `GeoFormatTypes.GeoFormat` object to Geometry, then to the target format. -The Geom trait is needed to separate out convert for CRS for WellKnownText -and GML, which may contain both. +Convert a `GeoFormatTypes.GeoFormat` object to Geometry, then to the target +format. The Geom trait is needed to separate out convert for CRS for +WellKnownText and GML, which may contain both. Both `Geom` and `Mixed` formats are converted to Geometries by default. To convert a `Mixed` format to crs, `CRS` must be explicitly passed for `mode`. """ -Base.convert(target::Type{<:GFT.GeoFormat}, mode::Union{GFT.FormatMode,Type{GFT.FormatMode}}, - source::GFT.GeoFormat) = - convert(target, convert(AbstractGeometry, source)) +function Base.convert( + target::Type{<:GFT.GeoFormat}, + mode::Union{GFT.FormatMode,Type{GFT.FormatMode}}, + source::GFT.GeoFormat + ) + return convert(target, convert(AbstractGeometry, source)) +end """ - convert(::Type{<:AbstractGeometry}, source::GeoFormatTypes.AbstractWellKnownText) + convert(::Type{<:AbstractGeometry}, + source::GeoFormatTypes.AbstractWellKnownText) convert(::Type{<:AbstractGeometry}, source::GeoFormatTypes.WellKnownBinary) convert(::Type{<:AbstractGeometry}, source::GeoFormatTypes.GeoJSON) convert(::Type{<:AbstractGeometry}, source::GeoFormatTypes.GML) @@ -38,7 +43,8 @@ Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) = fromGML(GFT.val(source)) """ - convert(::Type{<:GeoFormatTypes.AbstractWellKnownText}, source::AbstractGeometry) + convert(::Type{<:GeoFormatTypes.AbstractWellKnownText}, + source::AbstractGeometry) convert(::Type{<:GeoFormatTypes.WellKnownBinary}, source::AbstractGeometry) convert(::Type{<:GeoFormatTypes.GeoJSON}, source::AbstractGeometry) convert(::Type{<:GeoFormatTypes.GML}, source::AbstractGeometry) @@ -59,7 +65,8 @@ Base.convert(::Type{<:GFT.KML}, source::AbstractGeometry) = GFT.KML(toKML(source)) """ - convert(target::Type{<:GeoFormatTypes.GeoFormat}, mode::CRS, source::GeoFormat) + convert(target::Type{<:GeoFormatTypes.GeoFormat}, mode::CRS, + source::GeoFormat) Convert `GeoFormat` CRS data to another `GeoFormat` CRS type. """ diff --git a/src/dataset.jl b/src/dataset.jl index 4b0f8233..bb32240c 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -1,5 +1,6 @@ """ - copywholeraster(source::AbstractDataset, dest::AbstractDataset; ) + copywholeraster(source::AbstractDataset, dest::AbstractDataset; + ) Copy all dataset raster data. @@ -8,8 +9,8 @@ similarly configured dataset. The source and destination dataset must have the same number of bands, and the same width and height. The bands do not have to have the same data type. -Currently the only `options` supported are : `\"INTERLEAVE=PIXEL\"` to -force pixel interleaved operation and `\"COMPRESSED=YES\"` to force alignment on +Currently the only `options` supported are : `\"INTERLEAVE=PIXEL\"` to force +pixel interleaved operation and `\"COMPRESSED=YES\"` to force alignment on target dataset block sizes to achieve best compression. More options may be supported in the future. @@ -29,10 +30,12 @@ function copywholeraster( result = GDAL.gdaldatasetcopywholeraster(source.ptr, dest.ptr, options, @cplprogress(progressfunc), progressdata) @cplerr result "Failed to copy whole raster" + return result end """ - unsafe_copy(dataset::AbstractDataset; [filename, [driver, []]]) + unsafe_copy(dataset::AbstractDataset; [filename, [driver, + []]]) Create a copy of a dataset. @@ -166,7 +169,8 @@ function write(dataset::AbstractDataset, filename::AbstractString; kwargs...) end """ - unsafe_create(filename::AbstractString; driver, width, height, nbands, dtype, options) + unsafe_create(filename::AbstractString; driver, width, height, nbands, + dtype, options) Create a new dataset. @@ -217,7 +221,8 @@ function unsafe_create( end """ - create(filename::AbstractString; driver, width, height, nbands, dtype, options) + create(filename::AbstractString; driver, width, height, nbands, dtype, + options) Create a new dataset. @@ -275,7 +280,8 @@ function create( end """ - unsafe_read(filename; flags=OF_ReadOnly, alloweddrivers, options, siblingfiles) + unsafe_read(filename; flags=OF_ReadOnly, alloweddrivers, options, + siblingfiles) Open a raster file as a GDALDataset. @@ -462,8 +468,8 @@ unsafe_getlayer(dataset::AbstractDataset, i::Integer) = getlayer(dataset::AbstractDataset, name::AbstractString) getlayer(table::Table) -Fetch the feature layer corresponding to the given name. If it is called on a Table, which -supports only one layer, a name is not needed. +Fetch the feature layer corresponding to the given name. If it is called on a +Table, which supports only one layer, a name is not needed. The returned layer remains owned by the GDALDataset and should not be deleted by the application. @@ -496,7 +502,8 @@ end """ testcapability(dataset::AbstractDataset, capability::AbstractString) -Test if capability is available. `true` if capability available otherwise `false`. +Test if capability is available. `true` if capability available otherwise +`false`. One of the following dataset capability names can be passed into this function, and a `true` or `false` value will be returned indicating whether or not the @@ -536,7 +543,8 @@ function listcapability( end """ - unsafe_executesql(dataset::AbstractDataset, query::AbstractString; dialect, spatialfilter) + unsafe_executesql(dataset::AbstractDataset, query::AbstractString; dialect, + spatialfilter) Execute an SQL statement against the data store. @@ -595,6 +603,7 @@ before destroying the GDALDataset may cause errors. function releaseresultset(dataset::AbstractDataset, layer::FeatureLayer) GDAL.gdaldatasetreleaseresultset(dataset.ptr, layer.ptr) destroy(layer) + return nothing end """ @@ -688,9 +697,10 @@ function setproj!(dataset::AbstractDataset, projstring::AbstractString) end """ - buildoverviews!(dataset::AbstractDataset, overviewlist::Vector{Cint}; bandlist, resampling="NEAREST", - progressfunc, progressdata) - Build raster overview(s). + buildoverviews!(dataset::AbstractDataset, overviewlist::Vector{Cint}; + bandlist, resampling="NEAREST", progressfunc, progressdata) + +Build raster overview(s). If the operation is unsupported for the indicated dataset, then CE_Failure is returned, and CPLGetLastErrorNo() will return CPLE_NotSupported. @@ -731,4 +741,5 @@ end function destroy(dataset::AbstractDataset) GDAL.gdalclose(dataset.ptr) dataset.ptr = C_NULL + return nothing end diff --git a/src/driver.jl b/src/driver.jl index 97f7ca3e..1f39071e 100644 --- a/src/driver.jl +++ b/src/driver.jl @@ -24,6 +24,7 @@ driver that is registered with the `GDALDriverManager`. function destroy(drv::Driver) GDAL.gdaldestroydriver(drv.ptr) drv.ptr = C_NULL + return nothing end """ @@ -134,6 +135,7 @@ function copyfiles end function copyfiles(drv::Driver, new::AbstractString, old::AbstractString) result = GDAL.gdalcopydatasetfiles(drv.ptr, new, old) @cplerr result "Failed to copy dataset files" + return result end copyfiles(drvname::AbstractString, new::AbstractString, old::AbstractString) = @@ -142,8 +144,8 @@ copyfiles(drvname::AbstractString, new::AbstractString, old::AbstractString) = """ extensions() -Returns a `Dict{String,String}` of all of the file extensions that can be read by GDAL, -with their respective drivers shortname. +Returns a `Dict{String,String}` of all of the file extensions that can be read +by GDAL, with their respective drivers' `shortname`s. """ function extensions() extdict = Dict{String,String}() diff --git a/src/gcp.jl b/src/gcp.jl index cf1fed23..6fbe11b4 100644 --- a/src/gcp.jl +++ b/src/gcp.jl @@ -16,14 +16,15 @@ converts the equation from being pixel to geo to being geo to pixel. function invgeotransform!(gt_in::Vector{Cdouble}, gt_out::Vector{Cdouble}) result = Bool(GDAL.gdalinvgeotransform(pointer(gt_in), pointer(gt_out))) result || error("Geotransform coefficients is uninvertable") - gt_out + return gt_out end invgeotransform(gt_in::Vector{Cdouble}) = invgeotransform!(gt_in, Array{Cdouble}(undef, 6)) """ - applygeotransform(geotransform::Vector{Cdouble}, pixel::Cdouble, line::Cdouble) + applygeotransform(geotransform::Vector{Cdouble}, pixel::Cdouble, + line::Cdouble) Apply GeoTransform to x/y coordinate. @@ -47,11 +48,12 @@ function applygeotransform( geo_x = pointer(geo_xy) geo_y = geo_x + sizeof(Cdouble) GDAL.gdalapplygeotransform(pointer(geotransform), pixel, line, geo_x, geo_y) - geo_xy + return geo_xy end """ - composegeotransform!(gt1::Vector{Float64}, gt2::Vector{Float64}, gtout::Vector{Float64}) + composegeotransform!(gt1::Vector{Float64}, gt2::Vector{Float64}, + gtout::Vector{Float64}) Compose two geotransforms. @@ -70,7 +72,7 @@ function composegeotransform!( gtout::Vector{Cdouble} ) GDAL.gdalcomposegeotransform(pointer(gt1), pointer(gt2), pointer(gtout)) - gtout + return gtout end composegeotransform(gt1::Vector{Cdouble}, gt2::Vector{Cdouble}) = diff --git a/src/geointerface.jl b/src/geointerface.jl index e39dd7b5..4c6ea100 100644 --- a/src/geointerface.jl +++ b/src/geointerface.jl @@ -16,54 +16,55 @@ let pointtypes = (GDAL.wkbPoint, GDAL.wkbPoint25D, GDAL.wkbPointM, function GeoInterface.geotype(g::AbstractGeometry) gtype = getgeomtype(g) - if gtype in pointtypes - return :Point + return if gtype in pointtypes + :Point elseif gtype in multipointtypes - return :MultiPoint + :MultiPoint elseif gtype in linetypes - return :LineString + :LineString elseif gtype == GDAL.wkbLinearRing - return :LinearRing + :LinearRing elseif gtype in multilinetypes - return :MultiLineString + :MultiLineString elseif gtype in polygontypes - return :Polygon + :Polygon elseif gtype in multipolygontypes - return :MultiPolygon + :MultiPolygon elseif gtype in collectiontypes - return :GeometryCollection + :GeometryCollection else @warn "unknown geometry type" gtype - return :Unknown + :Unknown end end function GeoInterface.coordinates(g::AbstractGeometry) gtype = getgeomtype(g) ndim = getcoorddim(g) - if gtype in pointtypes + return if gtype in pointtypes if ndim == 2 - return Float64[getx(g,0), gety(g,0)] + Float64[getx(g,0), gety(g,0)] elseif ndim == 3 - return Float64[getx(g,0), gety(g,0), getz(g,0)] + Float64[getx(g,0), gety(g,0), getz(g,0)] else @assert ndim == 0 @warn("Empty Point") + nothing end elseif gtype in multipointtypes - return Vector{Float64}[ + Vector{Float64}[ GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) ] elseif gtype in linetypes || gtype == GDAL.wkbLinearRing - return Vector{Float64}[ + Vector{Float64}[ collect(getpoint(g,i-1)[1:ndim]) for i in 1:ngeom(g) ] elseif gtype in multilinetypes || gtype in polygontypes - return Vector{Vector{Float64}}[ + Vector{Vector{Float64}}[ GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) ] elseif gtype in multipolygontypes - return Vector{Vector{Vector{Float64}}}[ + Vector{Vector{Vector{Float64}}}[ GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) ] end diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 81034c00..17a9cf46 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -22,6 +22,7 @@ inappropriate. function destroy(feature::Feature) GDAL.ogr_f_destroy(feature.ptr) feature.ptr = C_NULL + return nothing end """ @@ -44,6 +45,7 @@ type is illegal for the `OGRFeatureDefn` (checking not yet implemented). function setgeom!(feature::Feature, geom::AbstractGeometry) result = GDAL.ogr_f_setgeometry(feature.ptr, geom.ptr) @ogrerr result "OGRErr $result: Failed to set feature geometry." + return result end """ @@ -53,19 +55,19 @@ Returns a clone of the geometry corresponding to the feature. """ function getgeom(feature::Feature) result = GDAL.ogr_f_getgeometryref(feature.ptr) - if result == C_NULL - return IGeometry() + return if result == C_NULL + IGeometry() else - return IGeometry(GDAL.ogr_g_clone(result)) + IGeometry(GDAL.ogr_g_clone(result)) end end function unsafe_getgeom(feature::Feature) result = GDAL.ogr_f_getgeometryref(feature.ptr) - if result == C_NULL - return Geometry() + return if result == C_NULL + Geometry() else - return Geometry(GDAL.ogr_g_clone(result)) + Geometry(GDAL.ogr_g_clone(result)) end end @@ -301,7 +303,8 @@ end """ asdatetime(feature::Feature, i::Integer) -Fetch field value as date and time. +Fetch field value as date and time. Currently this method only works for +OFTDate, OFTTime and OFTDateTime fields. ### Parameters * `hFeat`: handle to the feature that owned the field. @@ -363,21 +366,20 @@ const _FETCHFIELD = Dict{OGRFieldType, Function}( # const OFTWideString = (UInt32)(6) # const OFTWideStringList = (UInt32)(7) OFTBinary => asbinary, #8 - # const OFTDate = (UInt32)(9) - # const OFTTime = (UInt32)(10) + OFTDate => asdatetime, #9 + OFTTime => asdatetime, #10 OFTDateTime => asdatetime, #11 OFTInteger64 => asint64, #12 OFTInteger64List => asint64list #13 - # const OFTMaxType = (UInt32)(13) ) function getfield(feature::Feature, i::Integer) - if isfieldset(feature, i) + return if isfieldset(feature, i) _fieldtype = gettype(getfielddefn(feature, i)) _fetchfield = get(_FETCHFIELD, _fieldtype, getdefault) - return _fetchfield(feature, i) + _fetchfield(feature, i) else - return getdefault(feature, i) + getdefault(feature, i) end end @@ -390,10 +392,10 @@ getfield(feature::Feature, name::Union{AbstractString, Symbol}) = Set a feature's `i`-th field to `value`. -The following types for `value` are accepted: `Int32`, `Int64`, `Float64`, `AbstractString`, -or a `Vector` with those in it, as well as `Vector{UInt8}`. For `DateTime` values, an -additional keyword argument `tzflag` is accepted (0=unknown, 1=localtime, 100=GMT, see data -model for details). +The following types for `value` are accepted: `Int32`, `Int64`, `Float64`, +`AbstractString`, or a `Vector` with those in it, as well as `Vector{UInt8}`. +For `DateTime` values, an additional keyword argument `tzflag` is accepted +(0=unknown, 1=localtime, 100=GMT, see data model for details). OFTInteger, OFTInteger64 and OFTReal fields will be set directly. OFTString fields will be assigned a string representation of the value, but not @@ -540,19 +542,19 @@ Returns a clone of the feature geometry at index `i`. """ function getgeom(feature::Feature, i::Integer) result = GDAL.ogr_f_getgeomfieldref(feature.ptr, i) - if result == C_NULL - return IGeometry() + return if result == C_NULL + IGeometry() else - return IGeometry(GDAL.ogr_g_clone(result)) + IGeometry(GDAL.ogr_g_clone(result)) end end function unsafe_getgeom(feature::Feature, i::Integer) result = GDAL.ogr_f_getgeomfieldref(feature.ptr, i) - if result == C_NULL - return Geometry() + return if result == C_NULL + Geometry() else - return Geometry(GDAL.ogr_g_clone(result)) + Geometry(GDAL.ogr_g_clone(result)) end end @@ -610,7 +612,8 @@ end """ setfrom!(feature1::Feature, feature2::Feature, forgiving::Bool = false) - setfrom!(feature1::Feature, feature2::Feature, indices::Vector{Cint}, forgiving::Bool = false) + setfrom!(feature1::Feature, feature2::Feature, indices::Vector{Cint}, + forgiving::Bool = false) Set one feature from another. @@ -750,7 +753,8 @@ function setmediatype!(feature::Feature, mediatype::AbstractString) end """ - fillunsetwithdefault!(feature::Feature; notnull = true, options = StringList(C_NULL)) + fillunsetwithdefault!(feature::Feature; notnull = true, + options = StringList(C_NULL)) Fill unset fields with default values that might be defined. @@ -764,7 +768,7 @@ function fillunsetwithdefault!( notnull::Bool = true, options = StringList(C_NULL) ) - GDAL.ogr_f_fillunsetwithdefault(feature.ptr, notnull, options) + return GDAL.ogr_f_fillunsetwithdefault(feature.ptr, notnull, options) end """ diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index 3d3a792a..67195a73 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -91,7 +91,8 @@ getfielddefn(featuredefn::IFeatureDefnView, i::Integer) = IFieldDefnView(GDAL.ogr_fd_getfielddefn(featuredefn.ptr, i)) """ - findfieldindex(featuredefn::AbstractFeatureDefn, name::Union{AbstractString, Symbol}) + findfieldindex(featuredefn::AbstractFeatureDefn, + name::Union{AbstractString, Symbol}) Find field by name. @@ -101,8 +102,12 @@ the field index, or -1 if no match found. ### Remarks This uses the OGRFeatureDefn::GetFieldIndex() method. """ -findfieldindex(featuredefn::AbstractFeatureDefn, name::Union{AbstractString, Symbol}) = - GDAL.ogr_fd_getfieldindex(featuredefn.ptr, name) +function findfieldindex( + featuredefn::AbstractFeatureDefn, + name::Union{AbstractString, Symbol} + ) + return GDAL.ogr_fd_getfieldindex(featuredefn.ptr, name) +end """ addfielddefn!(featuredefn::FeatureDefn, fielddefn::FieldDefn) diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index aa48dc8d..c15f349b 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -86,7 +86,7 @@ function unsafe_copy( name::AbstractString = "copy($(getname(layer)))", options = StringList(C_NULL) ) - FeatureLayer(GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, + return FeatureLayer(GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options)) end @@ -111,12 +111,12 @@ Returns the current spatial filter for this layer. """ function getspatialfilter(layer::AbstractFeatureLayer) result = GDALGeometry(GDAL.ogr_l_getspatialfilter(Ptr{Cvoid}(layer.ptr))) - if result == C_NULL - return IGeometry(result) + return if result == C_NULL + IGeometry(result) else # NOTE(yeesian): we make a clone here so that the geometry does not # depend on the FeatureLayer. - return IGeometry(GDALGeometry(GDAL.ogr_g_clone(result))) + IGeometry(GDALGeometry(GDAL.ogr_g_clone(result))) end end @@ -127,23 +127,23 @@ Returns a clone of the spatial reference system for this layer. """ function getspatialref(layer::AbstractFeatureLayer) result = GDAL.ogr_l_getspatialref(layer.ptr) - if result == C_NULL - return ISpatialRef() + return if result == C_NULL + ISpatialRef() else # NOTE(yeesian): we make a clone here so that the spatialref does not # depend on the FeatureLayer/Dataset. - return ISpatialRef(GDAL.osrclone(result)) + ISpatialRef(GDAL.osrclone(result)) end end function unsafe_getspatialref(layer::AbstractFeatureLayer) result = GDAL.ogr_l_getspatialref(layer.ptr) - if result == C_NULL - return SpatialRef() + return if result == C_NULL + SpatialRef() else # NOTE(yeesian): we make a clone here so that the spatialref does not # depend on the FeatureLayer/Dataset. - return SpatialRef(GDAL.osrclone(result)) + SpatialRef(GDAL.osrclone(result)) end end @@ -217,7 +217,8 @@ function setspatialfilter!( end """ - setspatialfilter!(layer::AbstractFeatureLayer, i::Integer, geom::AbstractGeometry) + setspatialfilter!(layer::AbstractFeatureLayer, i::Integer, + geom::AbstractGeometry) Set a new spatial filter. @@ -259,7 +260,8 @@ function clearspatialfilter!(layer::AbstractFeatureLayer, i::Integer) end """ - setspatialfilter!(layer::AbstractFeatureLayer, i::Integer, xmin, ymin, xmax, ymax) + setspatialfilter!(layer::AbstractFeatureLayer, i::Integer, xmin, ymin, xmax, + ymax) Set a new rectangular spatial filter. @@ -419,7 +421,8 @@ the features in the layer looking for the desired feature. Sequential reads (with OGR_L_GetNextFeature()) are generally considered interrupted by a OGR_L_GetFeature() call. -The returned feature is now owned by the caller, and should be freed with `destroy()`. +The returned feature is now owned by the caller, and should be freed with +`destroy()`. """ unsafe_getfeature(layer::AbstractFeatureLayer, i::Integer) = Feature(GDALFeature(GDAL.ogr_l_getfeature(layer.ptr, i))) @@ -464,7 +467,7 @@ end function addfeature(f::Function, layer::AbstractFeatureLayer) feature = unsafe_createfeature(layer) - try + return try f(feature) addfeature!(layer, feature) finally @@ -485,7 +488,7 @@ unsafe_createfeature(layer::AbstractFeatureLayer) = function createfeature(f::Function, layer::AbstractFeatureLayer) feature = unsafe_createfeature(layer) - try + return try f(feature) setfeature!(layer, feature) finally @@ -524,7 +527,8 @@ layerdefn(layer::AbstractFeatureLayer) = IFeatureDefnView(GDAL.ogr_l_getlayerdefn(layer.ptr)) """ - findfieldindex(layer::AbstractFeatureLayer, field::Union{AbstractString, Symbol}, exactmatch::Bool) + findfieldindex(layer::AbstractFeatureLayer, + field::Union{AbstractString, Symbol}, exactmatch::Bool) Find the index of the field in a layer, or -1 if the field doesn't exist. @@ -633,8 +637,8 @@ the caller. implementation using `resetreading!()` and `nextfeature()` to find the requested feature id. -* `OLCSequentialWrite` / \"SequentialWrite\": `true` if the CreateFeature() method - works for this layer. Note this means that this particular layer is +* `OLCSequentialWrite` / \"SequentialWrite\": `true` if the CreateFeature() + method works for this layer. Note this means that this particular layer is writable. The same OGRLayer class may returned `false` for other layer instances that are effectively read-only. @@ -643,19 +647,19 @@ the caller. writable. The same OGRLayer class may returned `false` for other layer instances that are effectively read-only. -* `OLCFastSpatialFilter` / \"FastSpatialFilter\": `true` if this layer implements - spatial filtering efficiently. Layers that effectively read all features, - and test them with the OGRFeature intersection methods should return `false`. - This can be used as a clue by the application whether it should build and - maintain its own spatial index for features in this layer. +* `OLCFastSpatialFilter` / \"FastSpatialFilter\": `true` if this layer + implements spatial filtering efficiently. Layers that effectively read all + features, and test them with the OGRFeature intersection methods should + return `false`. This can be used as a clue by the application whether it + should build and maintain its own spatial index for features in this layer. -* `OLCFastFeatureCount` / \"FastFeatureCount\": `true` if this layer can return a - feature count (via GetFeatureCount()) efficiently. i.e. without counting the - features. In some cases this will return `true` until a spatial filter is - installed after which it will return `false`. +* `OLCFastFeatureCount` / \"FastFeatureCount\": `true` if this layer can return + a feature count (via GetFeatureCount()) efficiently. i.e. without counting + the features. In some cases this will return `true` until a spatial filter + is installed after which it will return `false`. -* `OLCFastGetExtent` / \"FastGetExtent\": `true` if this layer can return its data - extent (via GetExtent()) efficiently, i.e. without scanning all the +* `OLCFastGetExtent` / \"FastGetExtent\": `true` if this layer can return its + data extent (via GetExtent()) efficiently, i.e. without scanning all the features. In some cases this will return `true` until a spatial filter is installed after which it will return `false`. @@ -665,9 +669,9 @@ the caller. * `OLCCreateField` / \"CreateField\": `true` if this layer can create new fields on the current layer using CreateField(), otherwise `false`. -* `OLCCreateGeomField` / \"CreateGeomField\": (GDAL >= 1.11) `true` if this layer - can create new geometry fields on the current layer using CreateGeomField(), - otherwise `false`. +* `OLCCreateGeomField` / \"CreateGeomField\": (GDAL >= 1.11) `true` if this + layer can create new geometry fields on the current layer using + CreateGeomField(), otherwise `false`. * `OLCDeleteField` / \"DeleteField\": `true` if this layer can delete existing fields on the current layer using DeleteField(), otherwise `false`. @@ -680,19 +684,19 @@ the caller. definition of an existing field on the current layer using AlterFieldDefn(), otherwise `false`. -* `OLCDeleteFeature` / \"DeleteFeature\": `true` if the DeleteFeature() method is - supported on this layer, otherwise `false`. +* `OLCDeleteFeature` / \"DeleteFeature\": `true` if the DeleteFeature() method + is supported on this layer, otherwise `false`. -* `OLCStringsAsUTF8` / \"StringsAsUTF8\": `true` if values of OFTString fields are - assured to be in UTF-8 format. If `false` the encoding of fields is uncertain, - though it might still be UTF-8. +* `OLCStringsAsUTF8` / \"StringsAsUTF8\": `true` if values of OFTString fields + are assured to be in UTF-8 format. If `false` the encoding of fields is + uncertain, though it might still be UTF-8. * `OLCTransactions` / \"Transactions\": `true` if the StartTransaction(), CommitTransaction() and RollbackTransaction() methods work in a meaningful way, otherwise `false`. -* `OLCIgnoreFields` / \"IgnoreFields\": `true` if fields, geometry and style will - be omitted when fetching features as set by SetIgnoredFields() method. +* `OLCIgnoreFields` / \"IgnoreFields\": `true` if fields, geometry and style + will be omitted when fetching features as set by SetIgnoredFields() method. * `OLCCurveGeometries` / \"CurveGeometries\": `true` if this layer supports writing curve geometries or may return such geometries. (GDAL 2.0). @@ -721,7 +725,7 @@ function listcapability( GDAL.OLCCurveGeometries, GDAL.OLCMeasuredGeometries) ) - Dict{String, Bool}([ + return Dict{String, Bool}([ c => testcapability(layer,c) for c in capabilities ]) end @@ -739,7 +743,8 @@ end # ) """ - addfielddefn!(layer::AbstractFeatureLayer, field::AbstractFieldDefn, approx = false) + addfielddefn!(layer::AbstractFeatureLayer, field::AbstractFieldDefn, + approx = false) Create a new field on a layer. @@ -778,7 +783,8 @@ function addfielddefn!( end """ - addgeomdefn!(layer::AbstractFeatureLayer, field::AbstractGeomFieldDefn, approx = false) + addgeomdefn!(layer::AbstractFeatureLayer, field::AbstractGeomFieldDefn, + approx = false) Create a new geometry field on a layer. diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index 99c13760..da364507 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -30,7 +30,8 @@ end getname(fielddefn::AbstractFieldDefn) = GDAL.ogr_fld_getnameref(fielddefn.ptr) "Fetch the type of this field." -gettype(fielddefn::AbstractFieldDefn) = gdaltype(GDAL.ogr_fld_gettype(fielddefn.ptr)) +gettype(fielddefn::AbstractFieldDefn) = + gdaltype(GDAL.ogr_fld_gettype(fielddefn.ptr)) "Set the type of this field." function settype!(fielddefn::FieldDefn, etype::OGRFieldType) @@ -186,9 +187,9 @@ Return whether this field can receive null values. By default, fields are nullable. -Even if this method returns `false` (i.e not-nullable field), it doesn't mean that -OGRFeature::IsFieldSet() will necessary return `true`, as fields can be temporary -unset and null/not-null validation is usually done when +Even if this method returns `false` (i.e not-nullable field), it doesn't mean +that OGRFeature::IsFieldSet() will necessarily return `true`, as fields can be +temporarily unset and null/not-null validation is usually done when OGRLayer::CreateFeature()/SetFeature() is called. """ isnullable(fielddefn::AbstractFieldDefn) = @@ -217,10 +218,10 @@ Get default field value """ function getdefault(fielddefn::AbstractFieldDefn) result = @gdal(OGR_Fld_GetDefault::Cstring, fielddefn.ptr::GDALFieldDefn) - if result == C_NULL - return "" + return if result == C_NULL + "" else - return unsafe_string(result) + unsafe_string(result) end end @@ -356,9 +357,9 @@ Return whether this geometry field can receive null values. By default, fields are nullable. -Even if this method returns `false` (i.e not-nullable field), it doesn't mean that -OGRFeature::IsFieldSet() will necessary return `true`, as fields can be temporary -unset and null/not-null validation is usually done when +Even if this method returns `false` (i.e not-nullable field), it doesn't mean +that OGRFeature::IsFieldSet() will necessary return `true`, as fields can be +temporarily unset and null/not-null validation is usually done when OGRLayer::CreateFeature()/SetFeature() is called. Note that not-nullable geometry fields might also contain 'empty' geometries. diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 0ea2f943..e9b05903 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -221,9 +221,12 @@ Returns a bounding box polygon (CW) built from envelope coordinates """ function boundingbox(geom::AbstractGeometry) coordinates = envelope(geom) - MinX, MaxX, MinY, MaxY = coordinates.MinX, coordinates.MaxX, coordinates.MinY, coordinates.MaxY + MinX, MaxX = coordinates.MinX, coordinates.MaxX + MinY, MaxY = coordinates.MinY, coordinates.MaxY # creates a CW closed ring polygon - return createpolygon([[MaxY, MinX], [MaxY, MaxX], [MinY, MaxX], [MinY, MinX], [MaxY, MinX]]) + return createpolygon([ + [MaxY, MinX], [MaxY, MaxX], [MinY, MaxX], [MinY, MinX], [MaxY, MinX] + ]) end """ @@ -1269,7 +1272,8 @@ unsafe_curvegeom(geom::AbstractGeometry) = Geometry(GDAL.ogr_g_getcurvegeometry(geom.ptr, C_NULL)) """ - polygonfromedges(lines::AbstractGeometry, tol::Real; besteffort = false, autoclose = false) + polygonfromedges(lines::AbstractGeometry, tol::Real; besteffort = false, + autoclose = false) Build a ring from a bunch of arcs. diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index 664259af..4af83caf 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -21,6 +21,7 @@ Destroy Style Manager. function destroy(sm::StyleManager) GDAL.ogr_sm_destroy(sm.ptr) sm.ptr = C_NULL + return nothing end @@ -76,7 +77,8 @@ npart(stylemanager::StyleManager, stylestring::AbstractString) = GDAL.ogr_sm_getpartcount(stylemanager.ptr, stylestring) """ - unsafe_getpart(stylemanager::StyleManager, id::Integer, stylestring = C_NULL) + unsafe_getpart(stylemanager::StyleManager, id::Integer, + stylestring = C_NULL) Fetch a part (style tool) from the current style. @@ -156,6 +158,7 @@ Destroy Style Tool. function destroy(styletool::StyleTool) GDAL.ogr_st_destroy(styletool.ptr) styletool.ptr = C_NULL + return nothing end """ @@ -342,6 +345,7 @@ Destroy Style Table. function destroy(st::StyleTable) GDAL.ogr_stbl_destroy(st.ptr) st.ptr = C_NULL + return nothing end """ diff --git a/src/raster/array.jl b/src/raster/array.jl index 9d220287..d675f67e 100644 --- a/src/raster/array.jl +++ b/src/raster/array.jl @@ -6,23 +6,21 @@ const AllowedBand = Union{Integer,Colon,AbstractArray} """ RasterDataset(dataset::AbstractDataset) -This data structure is returned by the [`ArchGDAL.readraster`](@ref) function and -is a wrapper for a GDAL dataset. This wrapper is to signal the -user that the dataset should be treated as a 3D AbstractArray -where the first two dimensions correspond to longitude and latitude -and the third dimension corresponds to different raster bands. - -As it is a wrapper around a GDAL Dataset, it supports the usual -raster methods for a GDAL Dataset such as `getgeotransform`, -`nraster`, `getband`, `getproj`, `width`, and `height`. As it -is also a subtype of `AbstractDiskArray{T,3}`, it supports the -following additional methods: `readblock!`, `writeblock!`, -`eachchunk`, `haschunks`, etc. -This satisfies the DiskArray interface, allowing us to -be able to index into it like we would an array. - -Constructing a RasterDataset will error if the raster bands do not -have all the same size and a common element data type. +This data structure is returned by the [`ArchGDAL.readraster`](@ref) function +and is a wrapper for a GDAL dataset. This wrapper is to signal the user that the +dataset should be treated as a 3D AbstractArray where the first two dimensions +correspond to longitude and latitude and the third dimension corresponds to +different raster bands. + +As it is a wrapper around a GDAL Dataset, it supports the usual raster methods +for a GDAL Dataset such as `getgeotransform`, `nraster`, `getband`, `getproj`, +`width`, and `height`. As it is also a subtype of `AbstractDiskArray{T,3}`, it +supports the following additional methods: `readblock!`, `writeblock!`, +`eachchunk`, `haschunks`, etc. This satisfies the DiskArray interface, allowing +us to be able to index into it like we would an array. + +Constructing a RasterDataset will error if the raster bands do not have all the +same size and a common element data type. """ struct RasterDataset{T,DS} <: AbstractDiskArray{T,3} ds::DS @@ -30,9 +28,11 @@ struct RasterDataset{T,DS} <: AbstractDiskArray{T,3} end function RasterDataset(ds::AbstractDataset) - iszero(nraster(ds)) && throw(ArgumentError("The Dataset does not contain any raster bands")) + if iszero(nraster(ds)) + throw(ArgumentError("The Dataset does not contain any raster bands")) + end s = _common_size(ds) - RasterDataset{_dataset_type(ds), typeof(ds)}(ds, s) + return RasterDataset{_dataset_type(ds), typeof(ds)}(ds, s) end # Forward a few functions @@ -45,9 +45,12 @@ for f in (:getgeotransform, :nraster, :getband, :getproj, end # Here we need to special-case, because source and dest might be rasters -copywholeraster(x::RasterDataset,y::AbstractDataset;kwargs...) = copywholeraster(x.ds,y;kwargs...) -copywholeraster(x::RasterDataset,y::RasterDataset;kwargs...) = copywholeraster(x.ds,y.ds;kwargs...) -copywholeraster(x::AbstractDataset,y::RasterDataset;kwargs...) = copywholeraster(x.ds,y.ds;kwargs...) +copywholeraster(x::RasterDataset,y::AbstractDataset;kwargs...) = + copywholeraster(x.ds, y; kwargs...) +copywholeraster(x::RasterDataset,y::RasterDataset;kwargs...) = + copywholeraster(x.ds, y.ds; kwargs...) +copywholeraster(x::AbstractDataset,y::RasterDataset;kwargs...) = + copywholeraster(x.ds, y.ds; kwargs...) """ _dataset_type(ds::AbstractDataset) @@ -60,7 +63,7 @@ function _dataset_type(ds::AbstractDataset) b = getband(ds, i) pixeltype(b) end - reduce(promote_type, alldatatypes) + return reduce(promote_type, alldatatypes) end """ @@ -76,25 +79,31 @@ function _common_size(ds::AbstractDataset) size(b) end s = unique(allsizes) - length(s) == 1 || throw(DimensionMismatch("Can not coerce bands to single dataset, different sizes found")) - Int.((s[1]..., nr)) + if length(s) != 1 + throw(DimensionMismatch( + "Can not coerce bands to single dataset, different sizes found" + )) + end + return Int.((s[1]..., nr)) end getband(ds::RasterDataset, i::Integer) = getband(ds.ds, i) -unsafe_readraster(args...; kwargs...) = RasterDataset(unsafe_read(args...; kwargs...)) +unsafe_readraster(args...; kwargs...) = + RasterDataset(unsafe_read(args...; kwargs...)) """ readraster(s::String; kwargs...) -Opens a GDAL raster dataset. The difference to `ArchGDAL.read` is that -this function returns a `RasterDataset`, which is a subtype of `AbstractDiskArray{T,3}`, -so that users can operate on the array using direct indexing. +Opens a GDAL raster dataset. The difference to `ArchGDAL.read` is that this +function returns a `RasterDataset`, which is a subtype of +`AbstractDiskArray{T,3}`, so that users can operate on the array using direct +indexing. """ readraster(s::String; kwargs...) = RasterDataset(read(s; kwargs...)) function DiskArrays.eachchunk(ds::RasterDataset) subchunks = DiskArrays.eachchunk(getband(ds, 1)) - DiskArrays.GridChunks(ds,(subchunks.chunksize..., 1)) + return DiskArrays.GridChunks(ds,(subchunks.chunksize..., 1)) end DiskArrays.haschunks(::RasterDataset) = DiskArrays.Chunked() @@ -105,19 +114,28 @@ Base.size(band::AbstractRasterBand) = (width(band), height(band)) function DiskArrays.eachchunk(band::AbstractRasterBand) wI = windows(band) cs = (wI.blockiter.xbsize, wI.blockiter.ybsize) - DiskArrays.GridChunks(band, cs) + return DiskArrays.GridChunks(band, cs) end -function DiskArrays.readblock!(band::AbstractRasterBand, buffer, x::AbstractUnitRange, y::AbstractUnitRange) +function DiskArrays.readblock!( + band::AbstractRasterBand, + buffer, x::AbstractUnitRange, + y::AbstractUnitRange + ) xoffset, yoffset = first(x)-1, first(y)-1 xsize, ysize = length(x), length(y) - read!(band, buffer, xoffset, yoffset, xsize, ysize) + return read!(band, buffer, xoffset, yoffset, xsize, ysize) end -function DiskArrays.writeblock!(band::AbstractRasterBand, value, x::AbstractUnitRange, y::AbstractUnitRange) +function DiskArrays.writeblock!( + band::AbstractRasterBand, + value, + x::AbstractUnitRange, + y::AbstractUnitRange + ) xoffset, yoffset = first(x)-1, first(y)-1 xsize, ysize = length(x), length(y) - write!(band, value, xoffset, yoffset, xsize, ysize) + return write!(band, value, xoffset, yoffset, xsize, ysize) end @@ -125,24 +143,42 @@ end Base.size(dataset::RasterDataset) = dataset.size -function DiskArrays.readblock!(dataset::RasterDataset, buffer, x::AbstractUnitRange, y::AbstractUnitRange, z::AbstractUnitRange) +function DiskArrays.readblock!( + dataset::RasterDataset, + buffer, + x::AbstractUnitRange, + y::AbstractUnitRange, + z::AbstractUnitRange + ) buffer2 = Array(buffer) DiskArrays.readblock!(dataset::RasterDataset, buffer2, x, y, z) - buffer .= buffer2 + return buffer .= buffer2 end -function DiskArrays.readblock!(dataset::RasterDataset, buffer::Array, x::AbstractUnitRange, y::AbstractUnitRange, z::AbstractUnitRange) +function DiskArrays.readblock!( + dataset::RasterDataset, + buffer::Array, + x::AbstractUnitRange, + y::AbstractUnitRange, + z::AbstractUnitRange + ) xoffset, yoffset = first.((x, y)) .- 1 xsize, ysize= length.((x, y)) indices = [Cint(i) for i in z] - read!(dataset.ds, buffer, indices, xoffset, yoffset, xsize, ysize) + return read!(dataset.ds, buffer, indices, xoffset, yoffset, xsize, ysize) end -function DiskArrays.writeblock!(dataset::RasterDataset, value, x::AbstractUnitRange, y::AbstractUnitRange, bands::AbstractUnitRange) +function DiskArrays.writeblock!( + dataset::RasterDataset, + value, + x::AbstractUnitRange, + y::AbstractUnitRange, + bands::AbstractUnitRange + ) xoffset, yoffset = first.((x, y)) .- 1 xsize, ysize= length.((x, y)) indices = [Cint(i) for i in bands] - write!(dataset.ds, value, indices, xoffset, yoffset, xsize, ysize) + return write!(dataset.ds, value, indices, xoffset, yoffset, xsize, ysize) end Base.Array(dataset::RasterDataset) = dataset[:,:,:] diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index cd7f9af5..eb87eeba 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -10,6 +10,7 @@ unsafe_createcolortable(palette::GDALPaletteInterp) = function destroy(ct::ColorTable) GDAL.gdaldestroycolortable(ct.ptr) ct.ptr = C_NULL + return nothing end """ @@ -87,8 +88,9 @@ function setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry) end """ - createcolorramp!(ct::ColorTable, startindex, startcolor::GDAL.GDALColorEntry, - endindex, endcolor::GDAL.GDALColorEntry) + createcolorramp!(ct::ColorTable, startindex, + startcolor::GDAL.GDALColorEntry, endindex, + endcolor::GDAL.GDALColorEntry) Create color ramp. diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 1469df42..33ed497e 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -17,6 +17,7 @@ unsafe_createRAT(ct::ColorTable) = function destroy(rat::RasterAttrTable) GDAL.gdaldestroyrasterattributetable(rat.ptr) rat.ptr = C_NULL + return nothing end """ @@ -186,7 +187,8 @@ changesarewrittentofile(rat::RasterAttrTable) = Bool(GDAL.gdalratchangesarewrittentofile(rat.ptr)) """ - attributeio!(rat::RasterAttrTable, access::GDALRWFlag, col, startrow, nrows, data::Vector) + attributeio!(rat::RasterAttrTable, access::GDALRWFlag, col, startrow, nrows, + data::Vector) Read or Write a block of data to/from the Attribute Table. @@ -195,7 +197,8 @@ Read or Write a block of data to/from the Attribute Table. * `col` Column of the Attribute Table * `startrow` Row to start reading/writing (zero based) * `nrows` Number of rows to read or write -* `data` Vector of Float64, Int32 or AbstractString to read/write. Should be at least `nrows` long. +* `data` Vector of Float64, Int32 or AbstractString to read/write. Should + be at least `nrows` long. """ function attributeio! end @@ -256,7 +259,8 @@ function setrowcount!(rat::RasterAttrTable, n::Integer) end """ - createcolumn!(rat::RasterAttrTable, name, fieldtype::GDALRATFieldType, fieldusage::GDALRATFieldUsage) + createcolumn!(rat::RasterAttrTable, name, fieldtype::GDALRATFieldType, + fieldusage::GDALRATFieldUsage) Create new column. diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 5e3888b4..66465f4e 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -165,8 +165,8 @@ end Fetch the no data value for this band. If there is no out of data value, `nothing` will be -returned instead. The no data value for a band is generally a special marker value -used to mark pixels that are not valid data. Such pixels should generally +returned instead. The no data value for a band is generally a special marker +value used to mark pixels that are not valid data. Such pixels should generally not be displayed, nor contribute to analysis operations. ### Returns @@ -178,10 +178,10 @@ function getnodatavalue(band::AbstractRasterBand) # actually associated with this layer. May be `NULL` (default). hasnodatavalue = Ref(Cint(0)) nodatavalue = GDAL.gdalgetrasternodatavalue(band.ptr, hasnodatavalue) - if Bool(hasnodatavalue[]) - return nodatavalue + return if Bool(hasnodatavalue[]) + nodatavalue else - return nothing + nothing end end @@ -355,10 +355,10 @@ depended on for long, nor should it ever be modified by the caller.) """ function unsafe_getcolortable(band::AbstractRasterBand) result = ColorTable(GDALColorTable(GDAL.gdalgetrastercolortable(band.ptr))) - if result.ptr == C_NULL - return result + return if result.ptr == C_NULL + result else - return unsafe_clone(result) + unsafe_clone(result) end end @@ -386,8 +386,8 @@ function clearcolortable!(band::AbstractRasterBand) end """ - regenerateoverviews!(band::AbstractRasterBand, overviewbands::Vector{<:AbstractRasterBand}, - resampling = "NEAREST") + regenerateoverviews!(band::AbstractRasterBand, + overviewbands::Vector{<:AbstractRasterBand}, resampling = "NEAREST") Generate downsampled overviews. @@ -592,8 +592,8 @@ maskflags(band::AbstractRasterBand) = GDAL.gdalgetmaskflags(band.ptr) """ maskflaginfo(band::AbstractRasterBand) -Returns the flags as in `maskflags`(@ref) but unpacks the bit values into a named -tuple with the following fields: +Returns the flags as in `maskflags`(@ref) but unpacks the bit values into a +named tuple with the following fields: * `all_valid` * `per_dataset` diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 06af5131..0be8ce7c 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -1,9 +1,13 @@ """ - rasterio!(dataset::AbstractDataset, buffer::Array{<:Real, 3}, bands; ) - rasterio!(dataset::AbstractDataset, buffer::Array{<:Real, 3}, bands, rows, cols; ) - rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Real}; ) - rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Real}, rows, cols; ) + rasterio!(dataset::AbstractDataset, buffer::Array{<:Real, 3}, + bands; ) + rasterio!(dataset::AbstractDataset, buffer::Array{<:Real, 3}, bands, rows, + cols; ) + rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Real}; + ) + rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Real}, rows, + cols; ) Read/write a region of image data from multiple bands. @@ -24,10 +28,10 @@ boundaries\" as returned by `blocksize()`, or use the `readblock!()` and `writeblock!()` methods. ### Parameters -* `rows` A continuous range of rows expressed as a `UnitRange{<:Integer}`, - such as 2:9. -* `cols` A continuous range of columns expressed as a `UnitRange{<:Integer}`, - such as 2:9. +* `rows` A continuous range of rows expressed as a + `UnitRange{<:Integer}`, such as 2:9. +* `cols` A continuous range of columns expressed as a + `UnitRange{<:Integer}`, such as 2:9. * `access` Either `GDAL.GF_Read` to read a region of data, or `GDAL.GF_Write` to write a region of data. * `xoffset` The pixel offset to the top left corner of the region to be @@ -496,7 +500,8 @@ for (T,GT) in _GDALTYPE end """ - readblock!(rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, buffer) + readblock!(rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, + buffer) Read a block of image data efficiently. @@ -525,7 +530,8 @@ function readblock!( end """ - writeblock!(rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, buffer) + writeblock!(rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, + buffer) Write a block of image data efficiently. diff --git a/src/spatialref.jl b/src/spatialref.jl index f000e117..5889505e 100644 --- a/src/spatialref.jl +++ b/src/spatialref.jl @@ -5,9 +5,9 @@ Import a coordinate reference system from a `GeoFormat` into GDAL, returning an `ArchGDAL.AbstractSpatialRef`. ## Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, the default will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant` (the default) + will use axis ordering compliant with the relevant CRS authority. """ importCRS(x::GFT.GeoFormat; kwargs...) = importCRS!(newspatialref(; kwargs...), x) @@ -36,61 +36,113 @@ importCRS!(spref::AbstractSpatialRef, x::GFT.KML) = importCRS!(spref, GFT.EPSG(4326)) """ - reproject(points, sourceproj::GeoFormat, destproj::GeoFormat; [order=:compliant]) + reproject(points, sourceproj::GeoFormat, destproj::GeoFormat; + [order=:compliant]) Reproject points to a different coordinate reference system and/or format. ## Arguments - `coord`: Vector of Geometry points - `sourcecrs`: The current coordinate reference system, as a `GeoFormat` -- `targetcrs`: The coordinate reference system to transform to, using any CRS capable `GeoFormat` +- `targetcrs`: The coordinate reference system to transform to, using any CRS + capable `GeoFormat` ## Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, the default will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant` (the default) + will use axis ordering compliant with the relevant CRS authority. ## Example ```julia-repl julia> using ArchGDAL, GeoFormatTypes -julia> ArchGDAL.reproject([[118, 34], [119, 35]], ProjString("+proj=longlat +datum=WGS84 +no_defs"), EPSG(2025)) +julia> ArchGDAL.reproject( + [[118, 34], [119, 35]], + ProjString("+proj=longlat +datum=WGS84 +no_defs"), + EPSG(2025) +) 2-element Array{Array{Float64,1},1}: [-2.60813482878655e6, 1.5770429674905164e7] [-2.663928675953517e6, 1.56208905951487e7] ``` """ -reproject(coord, sourcecrs::GFT.GeoFormat, targetcrs::Nothing; kwargs...) = coord +reproject(coord, sourcecrs::GFT.GeoFormat, targetcrs::Nothing; kwargs...) = + coord -# These should be better integrated with geometry packages or follow some standard -const ReprojectCoord = Union{<:NTuple{2,<:Number},<:NTuple{3,<:Number},AbstractVector{<:Number}} +# These should be better integrated with geometry packages or follow a standard +const ReprojectCoord = Union{ + <:NTuple{2,<:Number}, + <:NTuple{3,<:Number}, + AbstractVector{<:Number} +} # Vector/Tuple coordinate(s) -reproject(coord::ReprojectCoord, sourcecrs::GFT.GeoFormat, targetcrs::GFT.GeoFormat; kwargs...) = - GeoInterface.coordinates(reproject(createpoint(coord...), sourcecrs, targetcrs; kwargs...)) -reproject(coords::AbstractArray{<:ReprojectCoord}, sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; kwargs...) = - GeoInterface.coordinates.(reproject([createpoint(c...) for c in coords], sourcecrs, targetcrs; kwargs...)) +function reproject( + coord::ReprojectCoord, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs... + ) + return GeoInterface.coordinates( + reproject(createpoint(coord...), sourcecrs, targetcrs; kwargs...) + ) +end + +function reproject( + coords::AbstractArray{<:ReprojectCoord}, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs... + ) + return GeoInterface.coordinates.( + reproject( + [createpoint(c...) for c in coords], + sourcecrs, + targetcrs; + kwargs... + ) + ) +end # GeoFormat -reproject(geom::GFT.GeoFormat, sourcecrs::GFT.GeoFormat, targetcrs::GFT.GeoFormat; kwargs...) = - convert(typeof(geom), reproject(convert(Geometry, geom), sourcecrs, targetcrs; kwargs...)) +function reproject( + geom::GFT.GeoFormat, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs... + ) + return convert( + typeof(geom), + reproject(convert(Geometry, geom), sourcecrs, targetcrs; kwargs...) + ) +end # Geometries -function reproject(geom::AbstractGeometry, sourcecrs::GFT.GeoFormat, targetcrs::GFT.GeoFormat; kwargs...) - crs2transform(sourcecrs, targetcrs; kwargs...) do transform +function reproject( + geom::AbstractGeometry, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs... + ) + return crs2transform(sourcecrs, targetcrs; kwargs...) do transform transform!(geom, transform) end end -function reproject(geoms::AbstractArray{<:AbstractGeometry}, sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; kwargs...) - crs2transform(sourcecrs, targetcrs; kwargs...) do transform + +function reproject( + geoms::AbstractArray{<:AbstractGeometry}, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs... + ) + return crs2transform(sourcecrs, targetcrs; kwargs...) do transform transform!.(geoms, Ref(transform)) end end """ - crs2transform(f::Function, sourcecrs::GeoFormat, targetcrs::GeoFormat; kwargs...) + crs2transform(f::Function, sourcecrs::GeoFormat, targetcrs::GeoFormat; + kwargs...) Run the function `f` on a coord transform generated from the source and target crs definitions. These can be any `GeoFormat` (from GeoFormatTypes) that holds @@ -98,8 +150,13 @@ a coordinate reference system. `kwargs` are passed through to `importCRS`. """ -function crs2transform(f::Function, sourcecrs::GFT.GeoFormat, targetcrs::GFT.GeoFormat; kwargs...) - importCRS(sourcecrs; kwargs...) do sourcecrs_ref +function crs2transform( + f::Function, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs... + ) + return importCRS(sourcecrs; kwargs...) do sourcecrs_ref importCRS(targetcrs; kwargs...) do targetcrs_ref createcoordtrans(sourcecrs_ref, targetcrs_ref) do transform f(transform) @@ -114,9 +171,9 @@ end Construct a Spatial Reference System from its WKT. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ newspatialref(wkt::AbstractString = ""; order=:compliant) = maybesetaxisorder!(ISpatialRef(GDAL.osrnewspatialreference(wkt)), order) @@ -128,9 +185,11 @@ function maybesetaxisorder!(sr::AbstractSpatialRef, order) if order == :trad GDAL.osrsetaxismappingstrategy(sr.ptr, GDAL.OAMS_TRADITIONAL_GIS_ORDER) elseif order != :compliant - throw(ArgumentError("order $order is not supported. Use :trad or :compliant")) + throw(ArgumentError( + "order $order is not supported. Use :trad or :compliant" + )) end - sr + return sr end function destroy(spref::AbstractSpatialRef) @@ -144,18 +203,18 @@ end Makes a clone of the Spatial Reference System. May return NULL. """ function clone(spref::AbstractSpatialRef) - if spref.ptr == C_NULL - return ISpatialRef() + return if spref.ptr == C_NULL + ISpatialRef() else - return ISpatialRef(GDAL.osrclone(spref.ptr)) + ISpatialRef(GDAL.osrclone(spref.ptr)) end end function unsafe_clone(spref::AbstractSpatialRef) - if spref.ptr == C_NULL - return SpatialRef() + return if spref.ptr == C_NULL + SpatialRef() else - return SpatialRef(GDAL.osrclone(spref.ptr)) + SpatialRef(GDAL.osrclone(spref.ptr)) end end @@ -196,9 +255,9 @@ end Construct a Spatial Reference System from its EPSG GCS or PCS code. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ importEPSG(code::Integer; kwargs...) = importEPSG!(newspatialref(; kwargs...), code) @@ -237,9 +296,9 @@ contrary to typical GIS use). See `importFromEPSG()` for more details on operation of this method. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ importEPSGA(code::Integer; kwargs...) = importEPSGA!(newspatialref(; kwargs...), code) @@ -269,9 +328,9 @@ end Create SRS from its WKT string. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ importWKT(wktstr::AbstractString; kwargs...) = newspatialref(wktstr; kwargs...) @@ -313,9 +372,9 @@ end Create SRS from its PROJ.4 string. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ importPROJ4(projstr::AbstractString; kwargs...) = importPROJ4!(newspatialref(; kwargs...), projstr) @@ -385,9 +444,9 @@ Passing the keyword argument `order=:compliant` or `order=:trad` will set the mapping strategy to return compliant axis order or traditional lon/lat order. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ importXML(xmlstr::AbstractString; kwargs...) = importXML!(newspatialref(; kwargs...), xmlstr) @@ -418,9 +477,9 @@ This method will download the spatial reference at a given URL and feed it into SetFromUserInput for you. # Keyword Arguments -- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat axis - ordering in any actions done with the crs. `:compliant`, will use axis - ordering compliant with the relevant CRS authority. +- `order`: Sets the axis mapping strategy. `:trad` will use traditional lon/lat + axis ordering in any actions done with the crs. `:compliant`, will use axis + ordering compliant with the relevant CRS authority. """ importURL(url::AbstractString; kwargs...) = importURL!(newspatialref(; kwargs...), url) @@ -447,8 +506,8 @@ Convert this SRS into a nicely formatted WKT string for display to a person. ### Parameters * `spref`: the SRS to be converted -* `simplify`: `true` if the `AXIS`, `AUTHORITY` and `EXTENSION` nodes should be - stripped off. +* `simplify`: `true` if the `AXIS`, `AUTHORITY` and `EXTENSION` nodes should + be stripped off. """ function toWKT(spref::AbstractSpatialRef, simplify::Bool) wktptr = Ref{Cstring}() @@ -548,7 +607,8 @@ function morphfromESRI!(spref::AbstractSpatialRef) end """ - setattrvalue!(spref::AbstractSpatialRef, path::AbstractString, value::AbstractString) + setattrvalue!(spref::AbstractSpatialRef, path::AbstractString, + value::AbstractString) Set attribute value in spatial reference. @@ -598,7 +658,8 @@ getattrvalue(spref::AbstractSpatialRef, name::AbstractString, i::Integer) = GDAL.osrgetattrvalue(spref.ptr, name, i) """ - unsafe_createcoordtrans(source::AbstractSpatialRef, target::AbstractSpatialRef) + unsafe_createcoordtrans(source::AbstractSpatialRef, + target::AbstractSpatialRef) Create transformation object. @@ -620,7 +681,7 @@ end "OGRCoordinateTransformation destructor." function destroy(obj::CoordTransform) GDAL.octdestroycoordinatetransformation(obj.ptr) - obj.ptr = C_NULL + return obj.ptr = C_NULL end """ @@ -642,8 +703,8 @@ function transform!( zvertices::Vector{Cdouble}, obj::CoordTransform ) - # The method TransformEx() allows extended success information to be captured - # indicating which points failed to transform. + # The method TransformEx() allows extended success information to be + # captured indicating which points failed to transform. n = length(xvertices) @assert length(yvertices) == n @assert length(zvertices) == n diff --git a/test/test_array.jl b/test/test_array.jl index 384216b8..17c63bac 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -18,7 +18,7 @@ import ArchGDAL; const AG = ArchGDAL @test splitpath(AG.filelist(ds)[2]) == ["ospy", "data4", "aster.rrd"] @test AG.listcapability(ds) isa Dict @test AG.ngcp(ds)==0 - @test AG.write(ds,tempname()) == C_NULL + @test AG.write(ds,tempname()) == nothing @test AG.testcapability(ds,"ODsCCreateLayer") == false end @testset "DiskArray chunk interface" begin From 9bb0304b785d3dadade2f948d3ca58fec70580bc Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 17:28:53 -0700 Subject: [PATCH 009/169] Update the types in the API to be based on julia types (rather than C-types or GDAL-types) --- src/ogr/feature.jl | 12 ++++++------ src/types.jl | 2 +- test/test_feature.jl | 28 ++++++++++++++-------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 17a9cf46..0dcdcf37 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -409,7 +409,7 @@ field types may be unaffected. """ function setfield! end -function setfield!(feature::Feature, i::Integer, value::Cint) +function setfield!(feature::Feature, i::Integer, value::Int32) GDAL.ogr_f_setfieldinteger(feature.ptr, i, value) return feature end @@ -419,7 +419,7 @@ function setfield!(feature::Feature, i::Integer, value::Int64) return feature end -function setfield!(feature::Feature, i::Integer, value::Cdouble) +function setfield!(feature::Feature, i::Integer, value::Float64) GDAL.ogr_f_setfielddouble(feature.ptr, i, value) return feature end @@ -429,17 +429,17 @@ function setfield!(feature::Feature, i::Integer, value::AbstractString) return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{Cint}) +function setfield!(feature::Feature, i::Integer, value::Vector{Int32}) GDAL.ogr_f_setfieldintegerlist(feature.ptr, i, length(value), value) return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{GDAL.GIntBig}) +function setfield!(feature::Feature, i::Integer, value::Vector{Int64}) GDAL.ogr_f_setfieldinteger64list(feature.ptr, i, length(value), value) return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{Cdouble}) +function setfield!(feature::Feature, i::Integer, value::Vector{Float64}) GDAL.ogr_f_setfielddoublelist(feature.ptr, i, length(value), value) return feature end @@ -468,7 +468,7 @@ end # Ptr{OGRField}),arg1,arg2,arg3) # end -function setfield!(feature::Feature, i::Integer, value::Vector{GDAL.GByte}) +function setfield!(feature::Feature, i::Integer, value::Vector{UInt8}) GDAL.ogr_f_setfieldbinary(feature.ptr, i, sizeof(value), value) return feature end diff --git a/src/types.jl b/src/types.jl index 14f65dc1..183721ed 100644 --- a/src/types.jl +++ b/src/types.jl @@ -313,7 +313,7 @@ const _FIELDTYPE = Dict{OGRFieldType, DataType}( OFTStringList => Vector{String}, OFTWideString => Nothing, # deprecated OFTWideStringList => Nothing, # deprecated - OFTBinary => Bool, + OFTBinary => Vector{UInt8}, OFTDate => Dates.Date, OFTTime => Dates.Time, OFTDateTime => Dates.DateTime, diff --git a/test/test_feature.jl b/test/test_feature.jl index fca37d4d..35af5118 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -118,22 +118,22 @@ end AG.createfeature(layer) do feature AG.setfield!(feature, 0, 1) AG.setfield!(feature, 1, 1.0) - AG.setfield!(feature, 2, Cint[1, 2]) + AG.setfield!(feature, 2, Int32[1, 2]) AG.setfield!(feature, 3, Int64[1, 2]) AG.setfield!(feature, 4, Float64[1.0, 2.0]) AG.setfield!(feature, 5, ["1", "2.0"]) - AG.setfield!(feature, 6, GDAL.GByte[1,2,3,4]) + AG.setfield!(feature, 6, UInt8[1,2,3,4]) AG.setfield!(feature, 7, Dates.DateTime(2016,9,25,21,17,0)) AG.addfeature(layer) do newfeature AG.setfrom!(newfeature, feature) @test AG.getfield(newfeature, 0) == 1 - @test AG.getfield(newfeature, 1) ≈ 1.0 + @test AG.getfield(newfeature, 1) ≈ 1.0 @test AG.getfield(newfeature, 2) == Int32[1, 2] @test AG.getfield(newfeature, 3) == Int64[1, 2] - @test AG.getfield(newfeature, 4) ≈ [1.0, 2.0] - @test AG.getfield(newfeature, 5) == ["1", "2.0"] - @test AG.getfield(newfeature, 6) == GDAL.GByte[1,2,3,4] + @test AG.getfield(newfeature, 4) ≈ Float64[1.0, 2.0] + @test AG.getfield(newfeature, 5) == String["1", "2.0"] + @test AG.getfield(newfeature, 6) == UInt8[1,2,3,4] @test AG.getfield(newfeature, 7) == Dates.DateTime(2016,9,25,21,17,0) AG.createfeature(layer) do lastfeature @@ -142,21 +142,21 @@ end AG.setfield!(lastfeature, 1, 18.2) AG.setfield!(lastfeature, 5, ["foo", "bar"]) @test AG.getfield(lastfeature, 0) == 45 - @test AG.getfield(lastfeature, 1) ≈ 18.2 + @test AG.getfield(lastfeature, 1) ≈ 18.2 @test AG.getfield(lastfeature, 2) == Int32[1, 2] @test AG.getfield(lastfeature, 3) == Int64[1, 2] - @test AG.getfield(lastfeature, 4) ≈ [1.0, 2.0] - @test AG.getfield(lastfeature, 5) == ["foo", "bar"] - @test AG.getfield(lastfeature, 6) == GDAL.GByte[1,2,3,4] + @test AG.getfield(lastfeature, 4) ≈ Float64[1.0, 2.0] + @test AG.getfield(lastfeature, 5) == String["foo", "bar"] + @test AG.getfield(lastfeature, 6) == UInt8[1,2,3,4] @test AG.getfield(lastfeature, 7) == Dates.DateTime(2016,9,25,21,17,0) @test AG.getfield(newfeature, 0) == 1 - @test AG.getfield(newfeature, 1) ≈ 1.0 - @test AG.getfield(newfeature, 5) == ["1", "2.0"] + @test AG.getfield(newfeature, 1) ≈ 1.0 + @test AG.getfield(newfeature, 5) == String["1", "2.0"] AG.setfrom!(newfeature, lastfeature, collect(Cint, 0:7)) @test AG.getfield(newfeature, 0) == 45 - @test AG.getfield(newfeature, 1) ≈ 18.2 - @test AG.getfield(newfeature, 5) == ["foo", "bar"] + @test AG.getfield(newfeature, 1) ≈ 18.2 + @test AG.getfield(newfeature, 5) == String["foo", "bar"] end @test AG.nfeature(layer) == 1 end From aa380f3a0bc4ab45a3c42c1b172678dae52fbc5a Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 18:57:22 -0700 Subject: [PATCH 010/169] [Breaking change] Introduce types for wkbGeometryType --- src/context.jl | 6 +- src/geointerface.jl | 31 ++--- src/ogr/featuredefn.jl | 8 +- src/ogr/featurelayer.jl | 9 +- src/ogr/fielddefn.jl | 9 +- src/ogr/geometry.jl | 33 ++--- src/types.jl | 237 ++++++++++++++++++++++++++++++++- test/test_cookbook_geometry.jl | 96 ++++++------- test/test_dataset.jl | 8 +- test/test_feature.jl | 10 +- test/test_featurelayer.jl | 12 +- test/test_fielddefn.jl | 18 ++- test/test_gdal_tutorials.jl | 8 +- test/test_geometry.jl | 34 ++--- test/test_ospy_examples.jl | 10 +- 15 files changed, 398 insertions(+), 131 deletions(-) diff --git a/src/context.jl b/src/context.jl index 1bb2ac6a..8e39923b 100644 --- a/src/context.jl +++ b/src/context.jl @@ -138,7 +138,7 @@ function addfielddefn( end """ - writegeomdefn!(layer::AbstractFeatureLayer, name, etype::OGRwkbGeometryType, + writegeomdefn!(layer::AbstractFeatureLayer, name, etype::WKBGeometryType, approx=false) Write a new geometry field on a layer. @@ -168,7 +168,7 @@ to the layer. function writegeomdefn!( layer::AbstractFeatureLayer, name::AbstractString, - etype::OGRwkbGeometryType; + etype::WKBGeometryType; approx::Bool = false ) geomdefn = unsafe_creategeomdefn(name, etype) @@ -181,7 +181,7 @@ function writegeomdefn( f::Function, layer::AbstractFeatureLayer, name::AbstractString, - etype::OGRwkbGeometryType; + etype::WKBGeometryType; approx::Bool = false ) geomdefn = unsafe_creategeomdefn(name, etype) diff --git a/src/geointerface.jl b/src/geointerface.jl index 4c6ea100..da4845b4 100644 --- a/src/geointerface.jl +++ b/src/geointerface.jl @@ -1,18 +1,15 @@ -let pointtypes = (GDAL.wkbPoint, GDAL.wkbPoint25D, GDAL.wkbPointM, - GDAL.wkbPointZM), - multipointtypes = (GDAL.wkbMultiPoint, GDAL.wkbMultiPoint25D, - GDAL.wkbMultiPointM, GDAL.wkbMultiPointZM), - linetypes = (GDAL.wkbLineString, GDAL.wkbLineString25D, GDAL.wkbLineStringM, - GDAL.wkbLineStringZM), - multilinetypes = (GDAL.wkbMultiLineString, GDAL.wkbMultiLineString25D, - GDAL.wkbMultiLineStringM, GDAL.wkbMultiLineStringZM), - polygontypes = (GDAL.wkbPolygon, GDAL.wkbPolygon25D, GDAL.wkbPolygonM, - GDAL.wkbPolygonZM), - multipolygontypes = (GDAL.wkbMultiPolygon, GDAL.wkbMultiPolygon25D, - GDAL.wkbMultiPolygonM, GDAL.wkbMultiPolygonZM), - collectiontypes = (GDAL.wkbGeometryCollection, - GDAL.wkbGeometryCollection25D, GDAL.wkbGeometryCollectionM, - GDAL.wkbGeometryCollectionZM) +let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), + multipointtypes = (wkbMultiPoint, wkbMultiPoint25D, wkbMultiPointM, + wkbMultiPointZM), + linetypes = (wkbLineString, wkbLineString25D, wkbLineStringM, + wkbLineStringZM), + multilinetypes = (wkbMultiLineString, wkbMultiLineString25D, + wkbMultiLineStringM, wkbMultiLineStringZM), + polygontypes = (wkbPolygon, wkbPolygon25D, wkbPolygonM, wkbPolygonZM), + multipolygontypes = (wkbMultiPolygon, wkbMultiPolygon25D, wkbMultiPolygonM, + wkbMultiPolygonZM), + collectiontypes = (wkbGeometryCollection, wkbGeometryCollection25D, + wkbGeometryCollectionM, wkbGeometryCollectionZM) function GeoInterface.geotype(g::AbstractGeometry) gtype = getgeomtype(g) @@ -22,7 +19,7 @@ let pointtypes = (GDAL.wkbPoint, GDAL.wkbPoint25D, GDAL.wkbPointM, :MultiPoint elseif gtype in linetypes :LineString - elseif gtype == GDAL.wkbLinearRing + elseif gtype == wkbLinearRing :LinearRing elseif gtype in multilinetypes :MultiLineString @@ -55,7 +52,7 @@ let pointtypes = (GDAL.wkbPoint, GDAL.wkbPoint25D, GDAL.wkbPointM, Vector{Float64}[ GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) ] - elseif gtype in linetypes || gtype == GDAL.wkbLinearRing + elseif gtype in linetypes || gtype == wkbLinearRing Vector{Float64}[ collect(getpoint(g,i-1)[1:ndim]) for i in 1:ngeom(g) ] diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index 67195a73..6221939c 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -183,11 +183,11 @@ For layers with multiple geometry fields, this method only returns the geometry type of the first geometry column. For other columns, use `OGR_GFld_GetType(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer), i))`. """ -getgeomtype(featuredefn::AbstractFeatureDefn) = - GDAL.ogr_fd_getgeomtype(featuredefn.ptr) +getgeomtype(featuredefn::AbstractFeatureDefn)::WKBGeometryType = + gdaltype(GDAL.ogr_fd_getgeomtype(featuredefn.ptr)) """ - setgeomtype!(featuredefn::FeatureDefn, etype::OGRwkbGeometryType) + setgeomtype!(featuredefn::FeatureDefn, etype::WKBGeometryType) Assign the base geometry type for the passed layer (same as the fd). @@ -196,7 +196,7 @@ type. The default upon creation is `wkbUnknown` which allows for any geometry type. The geometry type should generally not be changed after any OGRFeatures have been created against this definition. """ -function setgeomtype!(featuredefn::FeatureDefn, etype::OGRwkbGeometryType) +function setgeomtype!(featuredefn::FeatureDefn, etype::WKBGeometryType) GDAL.ogr_fd_setgeomtype(featuredefn.ptr, etype) return featuredefn end diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index c15f349b..650e8d57 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -21,7 +21,7 @@ This function attempts to create a new layer on the dataset with the indicated * `name`: the name for the new layer. This should ideally not match any existing layer on the datasource. Defaults to an empty string. * `dataset`: the dataset. Defaults to creating a new in memory dataset. -* `geom`: the geometry type for the layer. Use wkbUnknown (default) if +* `geom`: the geometry type for the layer. Use `wkbUnknown` (default) if there are no constraints on the types geometry to be written. * `spatialref`: the coordinate system to use for the new layer. * `options`: a StringList of name=value (driver-specific) options. @@ -29,7 +29,7 @@ This function attempts to create a new layer on the dataset with the indicated function createlayer(; name::AbstractString = "", dataset::AbstractDataset = create(getdriver("Memory")), - geom::OGRwkbGeometryType = GDAL.wkbUnknown, + geom::WKBGeometryType = wkbUnknown, spatialref::AbstractSpatialRef = SpatialRef(), options = StringList(C_NULL) ) @@ -44,7 +44,7 @@ end function unsafe_createlayer(; name::AbstractString = "", dataset::AbstractDataset = create(getdriver("Memory")), - geom::OGRwkbGeometryType = GDAL.wkbUnknown, + geom::WKBGeometryType = wkbUnknown, spatialref::AbstractSpatialRef = SpatialRef(), options = StringList(C_NULL) ) @@ -102,7 +102,8 @@ getname(layer::AbstractFeatureLayer) = GDAL.ogr_l_getname(layer.ptr) Return the layer geometry type. """ -getgeomtype(layer::AbstractFeatureLayer) = GDAL.ogr_l_getgeomtype(layer.ptr) +getgeomtype(layer::AbstractFeatureLayer) = + gdaltype(GDAL.ogr_l_getgeomtype(layer.ptr)) """ getspatialfilter(layer::AbstractFeatureLayer) diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index da364507..d8574ff5 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -265,11 +265,11 @@ isdefaultdriverspecific(fielddefn::AbstractFieldDefn) = Bool(GDAL.ogr_fld_isdefaultdriverspecific(fielddefn.ptr)) """ - unsafe_creategeomdefn(name::AbstractString, etype::OGRwkbGeometryType) + unsafe_creategeomdefn(name::AbstractString, etype::WKBGeometryType) Create a new field geometry definition. """ -unsafe_creategeomdefn(name::AbstractString, etype::OGRwkbGeometryType) = +unsafe_creategeomdefn(name::AbstractString, etype::WKBGeometryType) = GeomFieldDefn(GDAL.ogr_gfld_create(name, etype)) "Destroy a geometry field definition." @@ -297,10 +297,11 @@ getname(geomdefn::AbstractGeomFieldDefn) = GDAL.ogr_gfld_getnameref(geomdefn.ptr) "Fetch geometry type of this field." -gettype(geomdefn::AbstractGeomFieldDefn) = GDAL.ogr_gfld_gettype(geomdefn.ptr) +gettype(geomdefn::AbstractGeomFieldDefn) = + gdaltype(GDAL.ogr_gfld_gettype(geomdefn.ptr)) "Set the geometry type of this field." -function settype!(geomdefn::GeomFieldDefn, etype::OGRwkbGeometryType) +function settype!(geomdefn::GeomFieldDefn, etype::WKBGeometryType) GDAL.ogr_gfld_settype(geomdefn.ptr, etype) return geomdefn end diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index e9b05903..8436e923 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -102,21 +102,21 @@ function unsafe_clone(geom::AbstractGeometry) end """ - creategeom(geomtype::OGRwkbGeometryType) + creategeom(geomtype::WKBGeometryType) Create an empty geometry of desired type. This is equivalent to allocating the desired geometry with new, but the allocation is guaranteed to take place in the context of the GDAL/OGR heap. """ -creategeom(geomtype::OGRwkbGeometryType) = +creategeom(geomtype::WKBGeometryType) = IGeometry(GDAL.ogr_g_creategeometry(geomtype)) -unsafe_creategeom(geomtype::OGRwkbGeometryType) = +unsafe_creategeom(geomtype::WKBGeometryType) = Geometry(GDAL.ogr_g_creategeometry(geomtype)) """ - forceto(geom::AbstractGeometry, targettype::OGRwkbGeometryType, [options]) + forceto(geom::AbstractGeometry, targettype::WKBGeometryType, [options]) Tries to force the provided geometry to the specified geometry type. @@ -137,7 +137,7 @@ The passed in geometry is cloned and a new one returned. """ function forceto( geom::AbstractGeometry, - targettype::OGRwkbGeometryType, + targettype::WKBGeometryType, options = StringList(C_NULL) ) return IGeometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, @@ -146,7 +146,7 @@ end function unsafe_forceto( geom::AbstractGeometry, - targettype::OGRwkbGeometryType, + targettype::WKBGeometryType, options = StringList(C_NULL) ) return Geometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, @@ -301,7 +301,8 @@ end Fetch geometry type code """ -getgeomtype(geom::AbstractGeometry) = GDAL.ogr_g_getgeometrytype(geom.ptr) +getgeomtype(geom::AbstractGeometry) = + gdaltype(GDAL.ogr_g_getgeometrytype(geom.ptr)) """ geomname(geom::AbstractGeometry) @@ -1347,15 +1348,15 @@ Get flag to enable/disable returning non-linear geometries in the C API. """ getnonlineargeomflag() = Bool(GDAL.ogrgetnonlineargeometriesenabledflag()) -for (geom, wkbgeom) in ((:geomcollection, GDAL.wkbGeometryCollection), - (:linestring, GDAL.wkbLineString), - (:linearring, GDAL.wkbLinearRing), - (:multilinestring, GDAL.wkbMultiLineString), - (:multipoint, GDAL.wkbMultiPoint), - (:multipolygon, GDAL.wkbMultiPolygon), - (:multipolygon_noholes, GDAL.wkbMultiPolygon), - (:point, GDAL.wkbPoint), - (:polygon, GDAL.wkbPolygon)) +for (geom, wkbgeom) in ((:geomcollection, wkbGeometryCollection), + (:linestring, wkbLineString), + (:linearring, wkbLinearRing), + (:multilinestring, wkbMultiLineString), + (:multipoint, wkbMultiPoint), + (:multipolygon, wkbMultiPolygon), + (:multipolygon_noholes, wkbMultiPolygon), + (:point, wkbPoint), + (:polygon, wkbPolygon)) eval(quote $(Symbol("create$geom"))() = creategeom($wkbgeom) $(Symbol("unsafe_create$geom"))() = unsafe_creategeom($wkbgeom) diff --git a/src/types.jl b/src/types.jl index 183721ed..b0fea71a 100644 --- a/src/types.jl +++ b/src/types.jl @@ -359,7 +359,7 @@ const _GDALFIELDTYPES = Dict{OGRFieldType, GDAL.OGRFieldType}( ) convert(::Type{GDAL.OGRFieldType}, ft::OGRFieldType) = get(_GDALFIELDTYPES, ft) do - error("Unknown GDAL.OGRFieldType: $ft") + error("Unknown OGRFieldType: $ft") end "returns the `OGRFieldType` in julia" @@ -372,6 +372,241 @@ datatype(ft::OGRFieldType) = get(_FIELDTYPE, ft) do error("Unknown OGRFieldType: $ft") end +@enum(WKBGeometryType, + wkbUnknown = 0, + wkbPoint = 1, + wkbLineString = 2, + wkbPolygon = 3, + wkbMultiPoint = 4, + wkbMultiLineString = 5, + wkbMultiPolygon = 6, + wkbGeometryCollection = 7, + wkbCircularString = 8, + wkbCompoundCurve = 9, + wkbCurvePolygon = 10, + wkbMultiCurve = 11, + wkbMultiSurface = 12, + wkbCurve = 13, + wkbSurface = 14, + wkbPolyhedralSurface = 15, + wkbTIN = 16, + wkbTriangle = 17, + wkbNone = 18, + wkbLinearRing = 19, + wkbCircularStringZ = 20, + wkbCompoundCurveZ = 21, + wkbCurvePolygonZ = 22, + wkbMultiCurveZ = 23, + wkbMultiSurfaceZ = 24, + wkbCurveZ = 25, + wkbSurfaceZ = 26, + wkbPolyhedralSurfaceZ = 27, + wkbTINZ = 28, + wkbTriangleZ = 29, + wkbPointM = 30, + wkbLineStringM = 31, + wkbPolygonM = 32, + wkbMultiPointM = 33, + wkbMultiLineStringM = 34, + wkbMultiPolygonM = 35, + wkbGeometryCollectionM = 36, + wkbCircularStringM = 37, + wkbCompoundCurveM = 38, + wkbCurvePolygonM = 39, + wkbMultiCurveM = 40, + wkbMultiSurfaceM = 41, + wkbCurveM = 42, + wkbSurfaceM = 43, + wkbPolyhedralSurfaceM = 44, + wkbTINM = 45, + wkbTriangleM = 46, + wkbPointZM = 47, + wkbLineStringZM = 48, + wkbPolygonZM = 49, + wkbMultiPointZM = 50, + wkbMultiLineStringZM = 51, + wkbMultiPolygonZM = 52, + wkbGeometryCollectionZM = 53, + wkbCircularStringZM = 54, + wkbCompoundCurveZM = 55, + wkbCurvePolygonZM = 56, + wkbMultiCurveZM = 57, + wkbMultiSurfaceZM = 58, + wkbCurveZM = 59, + wkbSurfaceZM = 60, + wkbPolyhedralSurfaceZM = 61, + wkbTINZM = 62, + wkbTriangleZM = 63, + wkbPoint25D = 64, + wkbLineString25D = 65, + wkbPolygon25D = 66, + wkbMultiPoint25D = 67, + wkbMultiLineString25D = 68, + wkbMultiPolygon25D = 69, + wkbGeometryCollection25D = 70, +) + +const _WKBGEOMETRYTYPE = Dict{GDAL.OGRwkbGeometryType, WKBGeometryType}( + GDAL.wkbUnknown => wkbUnknown, + GDAL.wkbPoint => wkbPoint, + GDAL.wkbLineString => wkbLineString, + GDAL.wkbPolygon => wkbPolygon, + GDAL.wkbMultiPoint => wkbMultiPoint, + GDAL.wkbMultiLineString => wkbMultiLineString, + GDAL.wkbMultiPolygon => wkbMultiPolygon, + GDAL.wkbGeometryCollection => wkbGeometryCollection, + GDAL.wkbCircularString => wkbCircularString, + GDAL.wkbCompoundCurve => wkbCompoundCurve, + GDAL.wkbCurvePolygon => wkbCurvePolygon, + GDAL.wkbMultiCurve => wkbMultiCurve, + GDAL.wkbMultiSurface => wkbMultiSurface, + GDAL.wkbCurve => wkbCurve, + GDAL.wkbSurface => wkbSurface, + GDAL.wkbPolyhedralSurface => wkbPolyhedralSurface, + GDAL.wkbTIN => wkbTIN, + GDAL.wkbTriangle => wkbTriangle, + GDAL.wkbNone => wkbNone, + GDAL.wkbLinearRing => wkbLinearRing, + GDAL.wkbCircularStringZ => wkbCircularStringZ, + GDAL.wkbCompoundCurveZ => wkbCompoundCurveZ, + GDAL.wkbCurvePolygonZ => wkbCurvePolygonZ, + GDAL.wkbMultiCurveZ => wkbMultiCurveZ, + GDAL.wkbMultiSurfaceZ => wkbMultiSurfaceZ, + GDAL.wkbCurveZ => wkbCurveZ, + GDAL.wkbSurfaceZ => wkbSurfaceZ, + GDAL.wkbPolyhedralSurfaceZ => wkbPolyhedralSurfaceZ, + GDAL.wkbTINZ => wkbTINZ, + GDAL.wkbTriangleZ => wkbTriangleZ, + GDAL.wkbPointM => wkbPointM, + GDAL.wkbLineStringM => wkbLineStringM, + GDAL.wkbPolygonM => wkbPolygonM, + GDAL.wkbMultiPointM => wkbMultiPointM, + GDAL.wkbMultiLineStringM => wkbMultiLineStringM, + GDAL.wkbMultiPolygonM => wkbMultiPolygonM, + GDAL.wkbGeometryCollectionM => wkbGeometryCollectionM, + GDAL.wkbCircularStringM => wkbCircularStringM, + GDAL.wkbCompoundCurveM => wkbCompoundCurveM, + GDAL.wkbCurvePolygonM => wkbCurvePolygonM, + GDAL.wkbMultiCurveM => wkbMultiCurveM, + GDAL.wkbMultiSurfaceM => wkbMultiSurfaceM, + GDAL.wkbCurveM => wkbCurveM, + GDAL.wkbSurfaceM => wkbSurfaceM, + GDAL.wkbPolyhedralSurfaceM => wkbPolyhedralSurfaceM, + GDAL.wkbTINM => wkbTINM, + GDAL.wkbTriangleM => wkbTriangleM, + GDAL.wkbPointZM => wkbPointZM, + GDAL.wkbLineStringZM => wkbLineStringZM, + GDAL.wkbPolygonZM => wkbPolygonZM, + GDAL.wkbMultiPointZM => wkbMultiPointZM, + GDAL.wkbMultiLineStringZM => wkbMultiLineStringZM, + GDAL.wkbMultiPolygonZM => wkbMultiPolygonZM, + GDAL.wkbGeometryCollectionZM => wkbGeometryCollectionZM, + GDAL.wkbCircularStringZM => wkbCircularStringZM, + GDAL.wkbCompoundCurveZM => wkbCompoundCurveZM, + GDAL.wkbCurvePolygonZM => wkbCurvePolygonZM, + GDAL.wkbMultiCurveZM => wkbMultiCurveZM, + GDAL.wkbMultiSurfaceZM => wkbMultiSurfaceZM, + GDAL.wkbCurveZM => wkbCurveZM, + GDAL.wkbSurfaceZM => wkbSurfaceZM, + GDAL.wkbPolyhedralSurfaceZM => wkbPolyhedralSurfaceZM, + GDAL.wkbTINZM => wkbTINZM, + GDAL.wkbTriangleZM => wkbTriangleZM, + GDAL.wkbPoint25D => wkbPoint25D, + GDAL.wkbLineString25D => wkbLineString25D, + GDAL.wkbPolygon25D => wkbPolygon25D, + GDAL.wkbMultiPoint25D => wkbMultiPoint25D, + GDAL.wkbMultiLineString25D => wkbMultiLineString25D, + GDAL.wkbMultiPolygon25D => wkbMultiPolygon25D, + GDAL.wkbGeometryCollection25D => wkbGeometryCollection25D, +) + +const _WKBGEOMETRYTYPES = Dict{WKBGeometryType, GDAL.OGRwkbGeometryType}( + wkbUnknown => GDAL.wkbUnknown, + wkbPoint => GDAL.wkbPoint, + wkbLineString => GDAL.wkbLineString, + wkbPolygon => GDAL.wkbPolygon, + wkbMultiPoint => GDAL.wkbMultiPoint, + wkbMultiLineString => GDAL.wkbMultiLineString, + wkbMultiPolygon => GDAL.wkbMultiPolygon, + wkbGeometryCollection => GDAL.wkbGeometryCollection, + wkbCircularString => GDAL.wkbCircularString, + wkbCompoundCurve => GDAL.wkbCompoundCurve, + wkbCurvePolygon => GDAL.wkbCurvePolygon, + wkbMultiCurve => GDAL.wkbMultiCurve, + wkbMultiSurface => GDAL.wkbMultiSurface, + wkbCurve => GDAL.wkbCurve, + wkbSurface => GDAL.wkbSurface, + wkbPolyhedralSurface => GDAL.wkbPolyhedralSurface, + wkbTIN => GDAL.wkbTIN, + wkbTriangle => GDAL.wkbTriangle, + wkbNone => GDAL.wkbNone, + wkbLinearRing => GDAL.wkbLinearRing, + wkbCircularStringZ => GDAL.wkbCircularStringZ, + wkbCompoundCurveZ => GDAL.wkbCompoundCurveZ, + wkbCurvePolygonZ => GDAL.wkbCurvePolygonZ, + wkbMultiCurveZ => GDAL.wkbMultiCurveZ, + wkbMultiSurfaceZ => GDAL.wkbMultiSurfaceZ, + wkbCurveZ => GDAL.wkbCurveZ, + wkbSurfaceZ => GDAL.wkbSurfaceZ, + wkbPolyhedralSurfaceZ => GDAL.wkbPolyhedralSurfaceZ, + wkbTINZ => GDAL.wkbTINZ, + wkbTriangleZ => GDAL.wkbTriangleZ, + wkbPointM => GDAL.wkbPointM, + wkbLineStringM => GDAL.wkbLineStringM, + wkbPolygonM => GDAL.wkbPolygonM, + wkbMultiPointM => GDAL.wkbMultiPointM, + wkbMultiLineStringM => GDAL.wkbMultiLineStringM, + wkbMultiPolygonM => GDAL.wkbMultiPolygonM, + wkbGeometryCollectionM => GDAL.wkbGeometryCollectionM, + wkbCircularStringM => GDAL.wkbCircularStringM, + wkbCompoundCurveM => GDAL.wkbCompoundCurveM, + wkbCurvePolygonM => GDAL.wkbCurvePolygonM, + wkbMultiCurveM => GDAL.wkbMultiCurveM, + wkbMultiSurfaceM => GDAL.wkbMultiSurfaceM, + wkbCurveM => GDAL.wkbCurveM, + wkbSurfaceM => GDAL.wkbSurfaceM, + wkbPolyhedralSurfaceM => GDAL.wkbPolyhedralSurfaceM, + wkbTINM => GDAL.wkbTINM, + wkbTriangleM => GDAL.wkbTriangleM, + wkbPointZM => GDAL.wkbPointZM, + wkbLineStringZM => GDAL.wkbLineStringZM, + wkbPolygonZM => GDAL.wkbPolygonZM, + wkbMultiPointZM => GDAL.wkbMultiPointZM, + wkbMultiLineStringZM => GDAL.wkbMultiLineStringZM, + wkbMultiPolygonZM => GDAL.wkbMultiPolygonZM, + wkbGeometryCollectionZM => GDAL.wkbGeometryCollectionZM, + wkbCircularStringZM => GDAL.wkbCircularStringZM, + wkbCompoundCurveZM => GDAL.wkbCompoundCurveZM, + wkbCurvePolygonZM => GDAL.wkbCurvePolygonZM, + wkbMultiCurveZM => GDAL.wkbMultiCurveZM, + wkbMultiSurfaceZM => GDAL.wkbMultiSurfaceZM, + wkbCurveZM => GDAL.wkbCurveZM, + wkbSurfaceZM => GDAL.wkbSurfaceZM, + wkbPolyhedralSurfaceZM => GDAL.wkbPolyhedralSurfaceZM, + wkbTINZM => GDAL.wkbTINZM, + wkbTriangleZM => GDAL.wkbTriangleZM, + wkbPoint25D => GDAL.wkbPoint25D, + wkbLineString25D => GDAL.wkbLineString25D, + wkbPolygon25D => GDAL.wkbPolygon25D, + wkbMultiPoint25D => GDAL.wkbMultiPoint25D, + wkbMultiLineString25D => GDAL.wkbMultiLineString25D, + wkbMultiPolygon25D => GDAL.wkbMultiPolygon25D, + wkbGeometryCollection25D => GDAL.wkbGeometryCollection25D, +) + +function convert(::Type{GDAL.OGRwkbGeometryType}, wkbType::WKBGeometryType) + return get(_WKBGEOMETRYTYPES, wkbType) do + error("Unknown WKBGeometryType: $wkbType") + end +end + +"returns the `OGRFieldType` in julia" +function gdaltype(wkbType::GDAL.OGRwkbGeometryType) + return get(_WKBGEOMETRYTYPE, wkbType) do + error("Unknown GDAL.OGRwkbGeometryType: $wkbType") + end +end + @enum(GDALOpenFlag, OF_ReadOnly = GDAL.GDAL_OF_READONLY, # 0x00 OF_Update = GDAL.GDAL_OF_UPDATE, # 0x01 diff --git a/test/test_cookbook_geometry.jl b/test/test_cookbook_geometry.jl index 10bda492..07ef9a00 100644 --- a/test/test_cookbook_geometry.jl +++ b/test/test_cookbook_geometry.jl @@ -3,6 +3,8 @@ using Test import GeoInterface import GDAL, ArchGDAL; const AG = ArchGDAL +@testset "test_cookbook_geometry.jl" begin + @testset "Create a Point" begin x, y = 1198054.34, 648493.09 @@ -23,13 +25,13 @@ import GDAL, ArchGDAL; const AG = ArchGDAL end # Method 3 - AG.creategeom(GDAL.wkbPoint) do point + AG.creategeom(AG.wkbPoint) do point AG.addpoint!(point, x, y) @test AG.toWKT(point) == wktpoint end # Method 4 - point = AG.creategeom(GDAL.wkbPoint) + point = AG.creategeom(AG.wkbPoint) AG.addpoint!(point, x, y) @test AG.toWKT(point) == wktpoint @@ -58,7 +60,7 @@ end end # Method 3 - AG.creategeom(GDAL.wkbLineString) do line + AG.creategeom(AG.wkbLineString) do line AG.addpoint!(line, 1116651.439379124, 637392.6969887456) AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) @@ -67,7 +69,7 @@ end end # Method 4 - line = AG.creategeom(GDAL.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1116651.439379124, 637392.6969887456) AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) @@ -125,7 +127,7 @@ end end # Method 3 - AG.creategeom(GDAL.wkbLinearRing) do ring + AG.creategeom(AG.wkbLinearRing) do ring AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) AG.addpoint!(ring, 1161053.0218226474, 667456.2684348812) AG.addpoint!(ring, 1214704.933941905, 641092.8288590391) @@ -133,14 +135,14 @@ end AG.addpoint!(ring, 1218405.0658121984, 721108.1805541387) AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) - AG.creategeom(GDAL.wkbPolygon) do poly + AG.creategeom(AG.wkbPolygon) do poly AG.addgeom!(poly, ring) @test AG.toWKT(poly) == wktpoly end end # Method 4 - ring = AG.creategeom(GDAL.wkbLinearRing) + ring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) AG.addpoint!(ring, 1161053.0218226474, 667456.2684348812) AG.addpoint!(ring, 1214704.933941905, 641092.8288590391) @@ -148,7 +150,7 @@ end AG.addpoint!(ring, 1218405.0658121984, 721108.1805541387) AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) - poly = AG.creategeom(GDAL.wkbPolygon) + poly = AG.creategeom(AG.wkbPolygon) AG.addgeom!(poly, ring) @test AG.toWKT(poly) == wktpoly @@ -190,14 +192,14 @@ end # Method 2 AG.createpolygon() do poly - outring = AG.creategeom(GDAL.wkbLinearRing) + outring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) - innerring = AG.creategeom(GDAL.wkbLinearRing) + innerring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) @@ -210,15 +212,15 @@ end end # Method 3 - AG.creategeom(GDAL.wkbPolygon) do poly - outring = AG.creategeom(GDAL.wkbLinearRing) + AG.creategeom(AG.wkbPolygon) do poly + outring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) - innerring = AG.creategeom(GDAL.wkbLinearRing) + innerring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) @@ -231,8 +233,8 @@ end end # Method 4 - poly = AG.creategeom(GDAL.wkbPolygon) - outring = AG.creategeom(GDAL.wkbLinearRing) + poly = AG.creategeom(AG.wkbPolygon) + outring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) @@ -240,7 +242,7 @@ end AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addgeom!(poly, outring) - innerring = AG.creategeom(GDAL.wkbLinearRing) + innerring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) @@ -290,7 +292,7 @@ end end # Method 3 - AG.creategeom(GDAL.wkbMultiPoint) do multipoint + AG.creategeom(AG.wkbMultiPoint) do multipoint point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) @@ -301,7 +303,7 @@ end end # Method 4 - multipoint = AG.creategeom(GDAL.wkbMultiPoint) + multipoint = AG.creategeom(AG.wkbMultiPoint) point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) @@ -346,13 +348,13 @@ end end # Method 3 - AG.creategeom(GDAL.wkbMultiLineString) do multiline - line = AG.creategeom(GDAL.wkbLineString) + AG.creategeom(AG.wkbMultiLineString) do multiline + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1214242.4174581182, 617041.9717021306) AG.addpoint!(line, 1234593.142744733, 629529.9167643716) AG.addgeom!(multiline, line) - line = AG.creategeom(GDAL.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1184641.3624957693, 626754.8178616514) AG.addpoint!(line, 1219792.6152635587, 606866.6090588232) AG.addgeom!(multiline, line) @@ -361,12 +363,12 @@ end end # Method 4 - multiline = AG.creategeom(GDAL.wkbMultiLineString) - line = AG.creategeom(GDAL.wkbLineString) + multiline = AG.creategeom(AG.wkbMultiLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1214242.4174581182, 617041.9717021306) AG.addpoint!(line, 1234593.142744733, 629529.9167643716) AG.addgeom!(multiline, line) - line = AG.creategeom(GDAL.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1184641.3624957693, 626754.8178616514) AG.addpoint!(line, 1219792.6152635587, 606866.6090588232) AG.addgeom!(multiline, line) @@ -430,9 +432,9 @@ end end # Method 3 - AG.creategeom(GDAL.wkbMultiPolygon) do multipolygon - poly = AG.creategeom(GDAL.wkbPolygon) - ring = AG.creategeom(GDAL.wkbLinearRing) + AG.creategeom(AG.wkbMultiPolygon) do multipolygon + poly = AG.creategeom(AG.wkbPolygon) + ring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) AG.addpoint!(ring, 1204067.0548148106, 620742.1035724243) AG.addpoint!(ring, 1215167.4504256917, 620742.1035724243) @@ -441,8 +443,8 @@ end AG.addgeom!(poly, ring) AG.addgeom!(multipolygon,poly) - poly = AG.creategeom(GDAL.wkbPolygon) - ring = AG.creategeom(GDAL.wkbLinearRing) + poly = AG.creategeom(AG.wkbPolygon) + ring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) AG.addpoint!(ring, 1179553.6811741155, 626292.3013778647) AG.addpoint!(ring, 1194354.20865529, 626292.3013778647) @@ -455,9 +457,9 @@ end end # Method 4 - multipolygon = AG.creategeom(GDAL.wkbMultiPolygon) - poly = AG.creategeom(GDAL.wkbPolygon) - ring = AG.creategeom(GDAL.wkbLinearRing) + multipolygon = AG.creategeom(AG.wkbMultiPolygon) + poly = AG.creategeom(AG.wkbPolygon) + ring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) AG.addpoint!(ring, 1204067.0548148106, 620742.1035724243) AG.addpoint!(ring, 1215167.4504256917, 620742.1035724243) @@ -466,8 +468,8 @@ end AG.addgeom!(poly, ring) AG.addgeom!(multipolygon,poly) - poly = AG.creategeom(GDAL.wkbPolygon) - ring = AG.creategeom(GDAL.wkbLinearRing) + poly = AG.creategeom(AG.wkbPolygon) + ring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) AG.addpoint!(ring, 1179553.6811741155, 626292.3013778647) AG.addpoint!(ring, 1194354.20865529, 626292.3013778647) @@ -510,12 +512,12 @@ end end # Method 3 - AG.creategeom(GDAL.wkbGeometryCollection) do geomcol - point = AG.creategeom(GDAL.wkbPoint) + AG.creategeom(AG.wkbGeometryCollection) do geomcol + point = AG.creategeom(AG.wkbPoint) AG.addpoint!(point, -122.23, 47.09) AG.addgeom!(geomcol, point) - line = AG.creategeom(GDAL.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, -122.60, 47.14) AG.addpoint!(line, -122.48, 47.23) AG.addgeom!(geomcol, line) @@ -524,12 +526,12 @@ end end # Method 4 - geomcol = AG.creategeom(GDAL.wkbGeometryCollection) - point = AG.creategeom(GDAL.wkbPoint) + geomcol = AG.creategeom(AG.wkbGeometryCollection) + point = AG.creategeom(AG.wkbPoint) AG.addpoint!(point, -122.23, 47.09) AG.addgeom!(geomcol, point) - line = AG.creategeom(GDAL.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, -122.60, 47.14) AG.addpoint!(line, -122.48, 47.23) AG.addgeom!(geomcol, line) @@ -650,12 +652,12 @@ end AG.fromWKT(wkt) do pt bufferdist = 500 AG.buffer(pt, bufferdist) do poly - @test AG.getgeomtype(poly) == GDAL.wkbPolygon + @test AG.getgeomtype(poly) == AG.wkbPolygon end end # Method 2 - @test AG.getgeomtype(AG.buffer(AG.fromWKT(wkt), 500)) == GDAL.wkbPolygon + @test AG.getgeomtype(AG.buffer(AG.fromWKT(wkt), 500)) == AG.wkbPolygon end @testset "Calculate Envelope of a Geometry" begin @@ -759,12 +761,14 @@ end # Method 1 AG.fromWKT(wkt) do poly - @test AG.getgeomtype(poly) == GDAL.wkbPolygon - AG.forceto(poly, GDAL.wkbMultiPolygon) do mpoly - @test AG.getgeomtype(mpoly) == GDAL.wkbMultiPolygon + @test AG.getgeomtype(poly) == AG.wkbPolygon + AG.forceto(poly, AG.wkbMultiPolygon) do mpoly + @test AG.getgeomtype(mpoly) == AG.wkbMultiPolygon end end # Method 2 - @test AG.getgeomtype(AG.forceto(AG.fromWKT(wkt), GDAL.wkbMultiPolygon)) == GDAL.wkbMultiPolygon + @test AG.getgeomtype(AG.forceto(AG.fromWKT(wkt), AG.wkbMultiPolygon)) == AG.wkbMultiPolygon +end + end diff --git a/test/test_dataset.jl b/test/test_dataset.jl index 88d58a54..6e3132b6 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_dataset.jl" begin + @testset "Test methods for raster dataset" begin AG.read("data/utmsmall.tif") do dataset @testset "Method 1" begin @@ -73,7 +75,7 @@ end layer4 = AG.createlayer( name = "layer4", dataset = dataset4, - geom = GDAL.wkbLineString + geom = AG.wkbLineString ) @test AG.nlayer(dataset4) == 1 @@ -82,7 +84,7 @@ end AG.createlayer( name = "layer5", dataset = dataset5, - geom = GDAL.wkbLineString + geom = AG.wkbLineString ) do layer5 @test AG.nfeature(layer5) == 0 end @@ -95,3 +97,5 @@ end @test AG.nfield(layer5) == 0 @test AG.ngeom(layer5) == 1 end + +end diff --git a/test/test_feature.jl b/test/test_feature.jl index 35af5118..9156c540 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_feature.jl" begin + AG.read("data/point.geojson") do dataset layer = AG.getlayer(dataset, 0) AG.getfeature(layer, 0) do f1 @@ -37,8 +39,8 @@ AG.read("data/point.geojson") do dataset @test AG.findgeomindex(f1, "") == 0 @test AG.findgeomindex(f2, "geom") == -1 @test AG.findgeomindex(f2, "") == 0 - @test AG.gettype(AG.getgeomdefn(f1, 0)) == GDAL.wkbPoint - @test AG.gettype(AG.getgeomdefn(f2, 0)) == GDAL.wkbPoint + @test AG.gettype(AG.getgeomdefn(f1, 0)) == AG.wkbPoint + @test AG.gettype(AG.getgeomdefn(f2, 0)) == AG.wkbPoint end end @@ -90,7 +92,7 @@ end @testset "In-Memory Driver" begin AG.create(AG.getdriver("MEMORY")) do output - layer = AG.createlayer(dataset = output, geom=GDAL.wkbPolygon) + layer = AG.createlayer(dataset = output, geom = AG.wkbPolygon) AG.createfielddefn("int64field", AG.OFTInteger64) do fielddefn AG.addfielddefn!(layer, fielddefn) end @@ -168,3 +170,5 @@ end # untested # getstyletable + +end diff --git a/test/test_featurelayer.jl b/test/test_featurelayer.jl index fde501a9..a0211d19 100644 --- a/test/test_featurelayer.jl +++ b/test/test_featurelayer.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_featurelayer.jl" begin + @testset "Testing FeatureLayer Methods" begin AG.read("data/point.geojson") do dataset AG.copy(dataset) do tmpcopy @@ -26,7 +28,7 @@ import ArchGDAL; const AG = ArchGDAL name = "new layer", dataset = tmpcopy, spatialref = AG.getspatialref(tmplayer), - geom = GDAL.wkbPoint + geom = AG.wkbPoint ) @test AG.ngeom(AG.layerdefn(newlayer)) == 1 @test sprint(print, newlayer) == """ @@ -35,9 +37,9 @@ import ArchGDAL; const AG = ArchGDAL """ AG.writegeomdefn(newlayer, "new geom", - GDAL.wkbLineString) do gfd + AG.wkbLineString) do gfd @test AG.getname(gfd) == "new geom" - @test AG.gettype(gfd) == GDAL.wkbLineString + @test AG.gettype(gfd) == AG.wkbLineString end @test sprint(print, newlayer) == """ Layer: new layer @@ -63,7 +65,7 @@ import ArchGDAL; const AG = ArchGDAL Geometry 0 (): [wkbPoint] Geometry 1 (new geom): [wkbLineString] """ - AG.writegeomdefn!(newlayer, "new poly", GDAL.wkbPolygon) + AG.writegeomdefn!(newlayer, "new poly", AG.wkbPolygon) @test AG.ngeom(AG.layerdefn(newlayer)) == 3 @test sprint(print, newlayer) == """ Layer: new layer @@ -178,3 +180,5 @@ end # starttransaction(layer) # committransaction(layer) # rollbacktransaction(layer) + +end diff --git a/test/test_fielddefn.jl b/test/test_fielddefn.jl index c026f349..15fe9760 100644 --- a/test/test_fielddefn.jl +++ b/test/test_fielddefn.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_fielddefn.jl" begin + @testset "Tests for field defn" begin AG.createfielddefn("fieldname", AG.OFTInteger) do fd @test sprint(print, fd) == "fieldname (OFTInteger)" @@ -55,14 +57,14 @@ import ArchGDAL; const AG = ArchGDAL end @testset "Tests for Geom Field Defn" begin - AG.creategeomdefn("geomname", GDAL.wkbPolygon) do gfd + AG.creategeomdefn("geomname", AG.wkbPolygon) do gfd @test AG.getname(gfd) == "geomname" AG.setname!(gfd, "my name!") @test AG.getname(gfd) == "my name!" - @test AG.gettype(gfd) == GDAL.wkbPolygon - AG.settype!(gfd, GDAL.wkbPolyhedralSurface) - @test AG.gettype(gfd) == GDAL.wkbPolyhedralSurface + @test AG.gettype(gfd) == AG.wkbPolygon + AG.settype!(gfd, AG.wkbPolyhedralSurface) + @test AG.gettype(gfd) == AG.wkbPolyhedralSurface @test sprint(print, AG.getspatialref(gfd)) == "NULL Spatial Reference System" AG.getspatialref(gfd) do spref @@ -129,9 +131,9 @@ end AG.getname(AG.getfielddefn(fd,2)) == "fieldname" @test AG.ngeom(fd) == 1 - @test AG.getgeomtype(fd) == GDAL.wkbUnknown - AG.setgeomtype!(fd, GDAL.wkbPolygon) - @test AG.getgeomtype(fd) == GDAL.wkbPolygon + @test AG.getgeomtype(fd) == AG.wkbUnknown + AG.setgeomtype!(fd, AG.wkbPolygon) + @test AG.getgeomtype(fd) == AG.wkbPolygon @test AG.ngeom(fd) == 1 @test AG.isgeomignored(fd) == false @@ -170,3 +172,5 @@ end @test AG.nreference(fd) == 0 end end + +end diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index ab9d9454..3800e456 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_gdal_tutorials.jl" begin + @testset "Raster Tutorial" begin driver = AG.getdriver("GTiff") @@ -94,7 +96,7 @@ end geometry = AG.getgeom(feature) @test AG.geomname(geometry) == "POINT" - @test AG.getgeomtype(geometry) == GDAL.wkbPoint + @test AG.getgeomtype(geometry) == AG.wkbPoint @test AG.nfield(featuredefn) == 2 @test AG.getx(geometry, 0) ≈ 100.2785 @test AG.gety(geometry, 0) ≈ 0.0893 @@ -106,7 +108,7 @@ end layer = AG.createlayer( name = "point_out", dataset = dataset, - geom = GDAL.wkbPoint + geom = AG.wkbPoint ) AG.addfielddefn!(layer, "Name", AG.OFTString, nwidth = 32) featuredefn = AG.layerdefn(layer) @@ -119,3 +121,5 @@ end @test AG.nfeature(layer) == 1 end end + +end diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 58f8219f..bc5f4dc6 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -3,14 +3,16 @@ import GeoInterface, GeoFormatTypes, GDAL, ArchGDAL; const AG = ArchGDAL const GFT = GeoFormatTypes +@testset "test_geometry.jl" begin + @testset "Incomplete GeoInterface geometries" begin - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbCircularString)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbCompoundCurve)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbCurvePolygon)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbMultiSurface)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbPolyhedralSurface)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbTIN)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(GDAL.wkbTriangle)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbCircularString)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbCompoundCurve)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbCurvePolygon)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbMultiSurface)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbPolyhedralSurface)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbTIN)) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbTriangle)) end @testset "Create a Point" begin @@ -187,8 +189,8 @@ end AG.curvegeom(lgeom) do clgeom @test AG.toWKT(clgeom) == "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, GDAL.wkbMultiLineString))) == 2 - AG.forceto(lgeom, GDAL.wkbMultiLineString) do mlsgeom + @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom AG.polygonize(mlsgeom) do plgeom @test AG.ngeom(plgeom) == 2 end @@ -265,18 +267,18 @@ end end end - @test AG.getgeomtype(AG.getgeom(geom3, 0)) == GDAL.wkbPoint25D - @test AG.getgeomtype(AG.getgeom(geom3, 1)) == GDAL.wkbPolygon25D - @test AG.getgeomtype(AG.getgeom(geom3, 2)) == GDAL.wkbPolygon25D + @test AG.getgeomtype(AG.getgeom(geom3, 0)) == AG.wkbPoint25D + @test AG.getgeomtype(AG.getgeom(geom3, 1)) == AG.wkbPolygon25D + @test AG.getgeomtype(AG.getgeom(geom3, 2)) == AG.wkbPolygon25D @test sprint(print, AG.getgeom(geom3, 3)) == "NULL Geometry" AG.getgeom(geom3, 0) do geom4 - @test AG.getgeomtype(geom4) == GDAL.wkbPoint25D + @test AG.getgeomtype(geom4) == AG.wkbPoint25D end AG.getgeom(geom3, 1) do geom4 - @test AG.getgeomtype(geom4) == GDAL.wkbPolygon25D + @test AG.getgeomtype(geom4) == AG.wkbPolygon25D end AG.getgeom(geom3, 2) do geom4 - @test AG.getgeomtype(geom4) == GDAL.wkbPolygon25D + @test AG.getgeomtype(geom4) == AG.wkbPolygon25D end AG.getgeom(geom3, 3) do geom4 @test sprint(print, geom4) == "NULL Geometry" @@ -309,3 +311,5 @@ end @test GeoInterface.coordinates(point) ≈ [47.3488070138318, -122.5981499431438] end end end end end + +end diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index 59589482..8c6c8feb 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -3,6 +3,8 @@ using Statistics import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_ospy_examples.jl" begin + """ function to copy fields (not the data) from one layer to another parameters: @@ -94,7 +96,7 @@ AG.read("ospy/data1/sites.shp") do input outlayer = AG.createlayer( name = "hw1b", dataset = output, - geom = GDAL.wkbPoint + geom = AG.wkbPoint ) inlayerdefn = AG.layerdefn(inlayer) AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 0)) @@ -148,7 +150,7 @@ end layer = AG.createlayer( name = "hw2a", dataset = output, - geom = GDAL.wkbPolygon + geom = AG.wkbPolygon ) @test sprint(print, layer) == """ Layer: hw2a @@ -193,7 +195,7 @@ end # outlayer = AG.createlayer( # name = "hw2b", # dataset = output, - # geom = GDAL.wkbPolygon + # geom = AG.wkbPolygon # ) # infeaturedefn = AG.layerdefn(inlayer) # nameindex = AG.findfieldindex(infeaturedefn, "name") @@ -464,3 +466,5 @@ end end end end # # bandlist (omit to include all bands) # resampling="NEAREST") # resampling method end end end end + +end From d9ea813b87889e0d30407d28db1cafd0c5ccecc2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 18 Apr 2021 18:58:07 -0700 Subject: [PATCH 011/169] Encapsulate the tests in their own testsets for better organization of test error reports --- test/test_array.jl | 4 ++++ test/test_convert.jl | 5 ++++- test/test_cookbook_projection.jl | 4 ++++ test/test_display.jl | 4 ++++ test/test_drivers.jl | 3 +++ test/test_gdalutilities.jl | 4 ++++ test/test_geos_operations.jl | 6 +++++- test/test_iterators.jl | 4 ++++ test/test_rasterattrtable.jl | 4 ++++ test/test_rasterband.jl | 4 ++++ test/test_rasterio.jl | 4 ++++ test/test_spatialref.jl | 4 ++++ test/test_styletable.jl | 5 ++++- test/test_tables.jl | 4 ++++ test/test_types.jl | 4 ++++ test/test_utils.jl | 4 ++++ 16 files changed, 64 insertions(+), 3 deletions(-) diff --git a/test/test_array.jl b/test/test_array.jl index 17c63bac..6359bdaf 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -3,6 +3,8 @@ import GDAL using DiskArrays: eachchunk, haschunks, Chunked, GridChunks, readblock! import ArchGDAL; const AG = ArchGDAL +@testset "test_array.jl" begin + @testset "RasterDataset Type" begin AG.readraster("ospy/data4/aster.img") do ds @testset "Test forwarded methods" begin @@ -141,3 +143,5 @@ end @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end end + +end diff --git a/test/test_convert.jl b/test/test_convert.jl index de576cc7..9d76f20f 100644 --- a/test/test_convert.jl +++ b/test/test_convert.jl @@ -2,8 +2,9 @@ using Test import ArchGDAL; const AG = ArchGDAL import GeoFormatTypes; const GFT = GeoFormatTypes -# Tests high level convert methods +@testset "test_convert.jl" begin +# Tests high level convert methods @testset "convert point format" begin point = AG.createpoint(100, 70) json = convert(GFT.GeoJSON, point) @@ -28,3 +29,5 @@ end convert(GFT.ESRIWellKnownText, GFT.CRS(), GFT.EPSG(4326)))) == proj4326 end + +end diff --git a/test/test_cookbook_projection.jl b/test/test_cookbook_projection.jl index c2d860fc..f4f869ee 100644 --- a/test/test_cookbook_projection.jl +++ b/test/test_cookbook_projection.jl @@ -3,6 +3,8 @@ import GeoInterface, GeoFormatTypes, ArchGDAL const AG = ArchGDAL const GFT = GeoFormatTypes +@testset "test_cookbook_projection.jl" begin + @testset "Reproject a Geometry" begin @testset "Method 1" begin AG.importEPSG(2927) do source; AG.importEPSG(4326) do target @@ -95,3 +97,5 @@ end @test AG.toPROJ4(spatialref) == "+proj=longlat +datum=WGS84 +no_defs" end end + +end diff --git a/test/test_display.jl b/test/test_display.jl index 9bea3a7e..dc17aa9f 100644 --- a/test/test_display.jl +++ b/test/test_display.jl @@ -1,6 +1,8 @@ using Test import ArchGDAL; const AG = ArchGDAL +@testset "test_display.jl" begin + @testset "Testing Displays for different objects" begin AG.read("data/point.geojson") do dataset @test sprint(print, dataset) == """ @@ -68,3 +70,5 @@ end # untested # Geometry with length(toWKT(geom)) > 60 # should be able to see ... # Dataset with nlayer(dataset) > 5 + +end diff --git a/test/test_drivers.jl b/test/test_drivers.jl index 87fdb1ac..aa7fbfcc 100644 --- a/test/test_drivers.jl +++ b/test/test_drivers.jl @@ -1,6 +1,8 @@ using Test import ArchGDAL; const AG = ArchGDAL +@testset "test_drivers.jl" begin + @testset "Testing ConfigOptions" begin @test AG.getconfigoption("GDAL_CACHEMAX") == "" AG.setconfigoption("GDAL_CACHEMAX", "64") @@ -88,3 +90,4 @@ end @test_throws ArgumentError AG.extensiondriver(".not_an_extension") end +end diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index 5055241b..c3a747e6 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -1,6 +1,8 @@ using ArchGDAL, GDAL; AG = ArchGDAL using Test +@testset "test_gdalutilities.jl" begin + AG.read("data/utmsmall.tif") do ds_small @testset "GDAL Error" begin @test_throws GDAL.GDALError AG.gdalinfo(ds_small, ["-novalidoption"]) @@ -108,3 +110,5 @@ AG.read("data/point.geojson") do ds_point rm("data/point.csv") end end + +end diff --git a/test/test_geos_operations.jl b/test/test_geos_operations.jl index 116e9654..2e64eb84 100644 --- a/test/test_geos_operations.jl +++ b/test/test_geos_operations.jl @@ -1,7 +1,9 @@ using Test import ArchGDAL; const AG = ArchGDAL -function equivalent_to_wkt(geom::ArchGDAL.Geometry, wkt::String) +@testset "test_geos_operations.jl" begin + +function equivalent_to_wkt(geom::AG.Geometry, wkt::String) fromWKT(wkt) do test_geom @test toWKT(geom) == toWKT(test_geom) end @@ -219,3 +221,5 @@ end @test AG.toWKT(AG.simplifypreservetopology(g1, 43.2)) == "POLYGON ((56.5286666667 25.2101666667,56.529 25.2105,56.5288333333 25.2103333333,56.5286666667 25.2101666667))" end end + +end diff --git a/test/test_iterators.jl b/test/test_iterators.jl index e7040603..c2527161 100644 --- a/test/test_iterators.jl +++ b/test/test_iterators.jl @@ -1,6 +1,8 @@ using Test import ArchGDAL; const AG = ArchGDAL +@testset "test_iterators.jl" begin + @testset "Iterator interface Window Iterator" begin ds = AG.readraster("ospy/data4/aster.img") band = AG.getband(ds, 1) @@ -11,3 +13,5 @@ import ArchGDAL; const AG = ArchGDAL @test size(window) == (79, 89) @test length(window) == 7031 end + +end diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index 50b580c9..a2498e62 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_rasterattrtable.jl" begin + @testset "Testing Raster Attribute Tables" begin AG.createRAT() do rat @test AG.ncolumn(rat) == 0 @@ -124,3 +126,5 @@ end end end end + +end diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index e10a15b9..1e5f03a4 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_rasterband.jl" begin + @testset "Test methods for rasterband" begin AG.read("data/utmsmall.tif") do dataset ds_result = """ @@ -134,3 +136,5 @@ end # untested # setcategorynames!(rasterband, names) # getcolortable(band) do C_NULL + +end diff --git a/test/test_rasterio.jl b/test/test_rasterio.jl index 6be9fc4b..15114195 100644 --- a/test/test_rasterio.jl +++ b/test/test_rasterio.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_rasterio.jl" begin + AG.read("ospy/data4/aster.img") do ds @testset "version 1" begin band = AG.getband(ds, 1) @@ -203,3 +205,5 @@ end # @cplerr result "Access in DatasetRasterIO failed." # buffer # end + +end diff --git a/test/test_spatialref.jl b/test/test_spatialref.jl index de8be0e2..74ba57fb 100644 --- a/test/test_spatialref.jl +++ b/test/test_spatialref.jl @@ -3,6 +3,8 @@ import GDAL import ArchGDAL; const AG = ArchGDAL import GeoFormatTypes; const GFT = GeoFormatTypes +@testset "test_spatialref.jl" begin + @testset "Test Formats for Spatial Reference Systems" begin proj4326 = "+proj=longlat +datum=WGS84 +no_defs" proj26912 = "+proj=utm +zone=12 +datum=NAD83 +units=m +no_defs" @@ -258,3 +260,5 @@ end @test AG.getattrvalue(spatialref, "AUTHORITY", 1) == "4326" end end + +end diff --git a/test/test_styletable.jl b/test/test_styletable.jl index c98d9aec..945fad94 100644 --- a/test/test_styletable.jl +++ b/test/test_styletable.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_styletable.jl" begin + @testset "Testing StyleTable Methods" begin AG.createstylemanager() do sm @test AG.initialize!(sm) == true @@ -68,4 +70,5 @@ import ArchGDAL; const AG = ArchGDAL end end -# Untested: initialize!(stylemanager::StyleManager, feature::Feature) \ No newline at end of file +# Untested: initialize!(stylemanager::StyleManager, feature::Feature) +end diff --git a/test/test_tables.jl b/test/test_tables.jl index 81ca3bd3..512d61d1 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -2,6 +2,8 @@ using Test import ArchGDAL; const AG = ArchGDAL using Tables +@testset "test_tables.jl" begin + @testset "Tables Support" begin dataset = AG.read(joinpath(@__DIR__, "data/point.geojson")) dataset1 = AG.read(joinpath(@__DIR__, "data/multi_geom.csv"), options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"]) @@ -68,3 +70,5 @@ using Tables end end end + +end diff --git a/test/test_types.jl b/test/test_types.jl index ffc5164e..adc382d6 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -2,6 +2,8 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_types.jl" begin + @testset "Testing GDAL Type Methods" begin @testset "GDAL Open Flags" begin @test AG.OF_ReadOnly | 0x04 == 0x04 @@ -55,3 +57,5 @@ import ArchGDAL; const AG = ArchGDAL @test AG.gdaltype(GDAL.OFTMaxType) == AG.OFTInteger64List end end + +end diff --git a/test/test_utils.jl b/test/test_utils.jl index 51f06f77..45896325 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -2,9 +2,13 @@ using Test import GDAL import ArchGDAL; const AG = ArchGDAL +@testset "test_utils.jl" begin + @testset "metadataitem" begin driver = AG.getdriver("DERIVED") @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "" driver = AG.getdriver("GTiff") @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "tif tiff" end + +end From 912cb88a381bc75d40702044cf5e923fb0b2c22b Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 19 Apr 2021 00:28:18 -0700 Subject: [PATCH 012/169] Refactor src/types.jl (i) move constants into its own file (ii) use a macro for generating conversion methods between enums --- src/ArchGDAL.jl | 1 + src/constants.jl | 200 +++++++++++++++++++ src/types.jl | 492 +++++++++-------------------------------------- src/utils.jl | 29 +++ 4 files changed, 320 insertions(+), 402 deletions(-) create mode 100644 src/constants.jl diff --git a/src/ArchGDAL.jl b/src/ArchGDAL.jl index 69acd1b8..cadbfbf7 100644 --- a/src/ArchGDAL.jl +++ b/src/ArchGDAL.jl @@ -8,6 +8,7 @@ module ArchGDAL const GFT = GeoFormatTypes + include("constants.jl") include("utils.jl") include("types.jl") include("driver.jl") diff --git a/src/constants.jl b/src/constants.jl new file mode 100644 index 00000000..52f749d1 --- /dev/null +++ b/src/constants.jl @@ -0,0 +1,200 @@ +const GDALColorTable = GDAL.GDALColorTableH +const GDALCoordTransform = GDAL.OGRCoordinateTransformationH +const GDALDataset = GDAL.GDALDatasetH +const GDALDriver = GDAL.GDALDriverH +const GDALFeature = GDAL.OGRFeatureH +const GDALFeatureDefn = GDAL.OGRFeatureDefnH +const GDALFeatureLayer = GDAL.OGRLayerH +const GDALField = GDAL.OGRField +const GDALFieldDefn = GDAL.OGRFieldDefnH +const GDALGeometry = GDAL.OGRGeometryH +const GDALGeomFieldDefn = GDAL.OGRGeomFieldDefnH +const GDALProgressFunc = GDAL.GDALProgressFunc +const GDALRasterAttrTable = GDAL.GDALRasterAttributeTableH +const GDALRasterBand = GDAL.GDALRasterBandH +const GDALSpatialRef = GDAL.OGRSpatialReferenceH +const GDALStyleManager = GDAL.OGRStyleMgrH +const GDALStyleTable = GDAL.OGRStyleTableH +const GDALStyleTool = GDAL.OGRStyleToolH + +const StringList = Ptr{Cstring} + +CPLErr = GDAL.CPLErr +CPLXMLNodeType = GDAL.CPLXMLNodeType +GDALDataType = GDAL.GDALDataType +GDALAsyncStatusType = GDAL.GDALAsyncStatusType +GDALAccess = GDAL.GDALAccess +GDALRWFlag = GDAL.GDALRWFlag +GDALRIOResampleAlg = GDAL.GDALRIOResampleAlg +GDALColorInterp = GDAL.GDALColorInterp +GDALPaletteInterp = GDAL.GDALPaletteInterp +GDALRATFieldType = GDAL.GDALRATFieldType +GDALRATFieldUsage = GDAL.GDALRATFieldUsage +GDALTileOrganization = GDAL.GDALTileOrganization +GDALGridAlgorithm = GDAL.GDALGridAlgorithm +OGRwkbGeometryType = GDAL.OGRwkbGeometryType +OGRwkbVariant = GDAL.OGRwkbVariant +OGRwkbByteOrder = GDAL.OGRwkbByteOrder +OGRFieldSubType = GDAL.OGRFieldSubType +OGRJustification = GDAL.OGRJustification +OGRSTClassId = GDAL.OGRSTClassId +OGRSTUnitId = GDAL.OGRSTUnitId +OGRSTPenParam = GDAL.OGRSTPenParam +OGRSTBrushParam = GDAL.OGRSTBrushParam +OGRSTSymbolParam = GDAL.OGRSTSymbolParam +OGRSTLabelParam = GDAL.OGRSTLabelParam +GDALResampleAlg = GDAL.GDALResampleAlg +GWKAverageOrModeAlg = GDAL.GWKAverageOrModeAlg +OGRAxisOrientation = GDAL.OGRAxisOrientation + +"return the corresponding `DataType` in julia" +const _JLTYPE = Dict{GDALDataType, DataType}( + GDAL.GDT_Unknown => Any, + GDAL.GDT_Byte => UInt8, + GDAL.GDT_UInt16 => UInt16, + GDAL.GDT_Int16 => Int16, + GDAL.GDT_UInt32 => UInt32, + GDAL.GDT_Int32 => Int32, + GDAL.GDT_Float32 => Float32, + GDAL.GDT_Float64 => Float64, +) + +const _GDALTYPE = Dict{DataType,GDALDataType}( + Any => GDAL.GDT_Unknown, + UInt8 => GDAL.GDT_Byte, + UInt16 => GDAL.GDT_UInt16, + Int16 => GDAL.GDT_Int16, + UInt32 => GDAL.GDT_UInt32, + Int32 => GDAL.GDT_Int32, + Float32 => GDAL.GDT_Float32, + Float64 => GDAL.GDT_Float64, +) + +@enum(OGRFieldType, + OFTInteger = 0, + OFTIntegerList = 1, + OFTReal = 2, + OFTRealList = 3, + OFTString = 4, + OFTStringList = 5, + OFTWideString = 6, + OFTWideStringList = 7, + OFTBinary = 8, + OFTDate = 9, + OFTTime = 10, + OFTDateTime = 11, + OFTInteger64 = 12, + OFTInteger64List = 13, + OFTMaxType = 14, +) + +"return the corresponding `DataType` in julia" +const _FIELDTYPE = Dict{OGRFieldType, DataType}( + OFTInteger => Int32, + OFTIntegerList => Vector{Int32}, + OFTReal => Float64, + OFTRealList => Vector{Float64}, + OFTString => String, + OFTStringList => Vector{String}, + OFTWideString => Nothing, # deprecated + OFTWideStringList => Nothing, # deprecated + OFTBinary => Vector{UInt8}, + OFTDate => Dates.Date, + OFTTime => Dates.Time, + OFTDateTime => Dates.DateTime, + OFTInteger64 => Int64, + OFTInteger64List => Vector{Int64}, + # OFTMaxType => Nothing # unsupported +) + +@enum(WKBGeometryType, + wkbUnknown = 0, + wkbPoint = 1, + wkbLineString = 2, + wkbPolygon = 3, + wkbMultiPoint = 4, + wkbMultiLineString = 5, + wkbMultiPolygon = 6, + wkbGeometryCollection = 7, + wkbCircularString = 8, + wkbCompoundCurve = 9, + wkbCurvePolygon = 10, + wkbMultiCurve = 11, + wkbMultiSurface = 12, + wkbCurve = 13, + wkbSurface = 14, + wkbPolyhedralSurface = 15, + wkbTIN = 16, + wkbTriangle = 17, + wkbNone = 18, + wkbLinearRing = 19, + wkbCircularStringZ = 20, + wkbCompoundCurveZ = 21, + wkbCurvePolygonZ = 22, + wkbMultiCurveZ = 23, + wkbMultiSurfaceZ = 24, + wkbCurveZ = 25, + wkbSurfaceZ = 26, + wkbPolyhedralSurfaceZ = 27, + wkbTINZ = 28, + wkbTriangleZ = 29, + wkbPointM = 30, + wkbLineStringM = 31, + wkbPolygonM = 32, + wkbMultiPointM = 33, + wkbMultiLineStringM = 34, + wkbMultiPolygonM = 35, + wkbGeometryCollectionM = 36, + wkbCircularStringM = 37, + wkbCompoundCurveM = 38, + wkbCurvePolygonM = 39, + wkbMultiCurveM = 40, + wkbMultiSurfaceM = 41, + wkbCurveM = 42, + wkbSurfaceM = 43, + wkbPolyhedralSurfaceM = 44, + wkbTINM = 45, + wkbTriangleM = 46, + wkbPointZM = 47, + wkbLineStringZM = 48, + wkbPolygonZM = 49, + wkbMultiPointZM = 50, + wkbMultiLineStringZM = 51, + wkbMultiPolygonZM = 52, + wkbGeometryCollectionZM = 53, + wkbCircularStringZM = 54, + wkbCompoundCurveZM = 55, + wkbCurvePolygonZM = 56, + wkbMultiCurveZM = 57, + wkbMultiSurfaceZM = 58, + wkbCurveZM = 59, + wkbSurfaceZM = 60, + wkbPolyhedralSurfaceZM = 61, + wkbTINZM = 62, + wkbTriangleZM = 63, + wkbPoint25D = 64, + wkbLineString25D = 65, + wkbPolygon25D = 66, + wkbMultiPoint25D = 67, + wkbMultiLineString25D = 68, + wkbMultiPolygon25D = 69, + wkbGeometryCollection25D = 70, +) + +@enum(GDALOpenFlag, + OF_ReadOnly = GDAL.GDAL_OF_READONLY, # 0x00 + OF_Update = GDAL.GDAL_OF_UPDATE, # 0x01 + # OF_All = GDAL.GDAL_OF_ALL, # 0x00 + OF_Raster = GDAL.GDAL_OF_RASTER, # 0x02 + OF_Vector = GDAL.GDAL_OF_VECTOR, # 0x04 + OF_GNM = GDAL.GDAL_OF_GNM, # 0x08 + OF_Kind_Mask = GDAL.GDAL_OF_KIND_MASK, # 0x1e + OF_Shared = GDAL.GDAL_OF_SHARED, # 0x20 + OF_Verbose_Error = GDAL.GDAL_OF_VERBOSE_ERROR, # 0x40 + OF_Internal = GDAL.GDAL_OF_INTERNAL, # 0x80 + # OF_DEFAULT_BLOCK_ACCESS = GDAL.GDAL_OF_DEFAULT_BLOCK_ACCESS, # 0 + OF_Array_Block_Access = GDAL.GDAL_OF_ARRAY_BLOCK_ACCESS, # 0x0100 + OF_Hashset_Block_Access = GDAL.GDAL_OF_HASHSET_BLOCK_ACCESS, # 0x0200 + # OF_RESERVED_1 = GDAL.GDAL_OF_RESERVED_1, # 0x0300 + OF_Block_Access_Mask = GDAL.GDAL_OF_BLOCK_ACCESS_MASK, # 0x0300 +) diff --git a/src/types.jl b/src/types.jl index b0fea71a..abfb15de 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,25 +1,5 @@ import DiskArrays: AbstractDiskArray import Base.convert -const GDALColorTable = GDAL.GDALColorTableH -const GDALCoordTransform = GDAL.OGRCoordinateTransformationH -const GDALDataset = GDAL.GDALDatasetH -const GDALDriver = GDAL.GDALDriverH -const GDALFeature = GDAL.OGRFeatureH -const GDALFeatureDefn = GDAL.OGRFeatureDefnH -const GDALFeatureLayer = GDAL.OGRLayerH -const GDALField = GDAL.OGRField -const GDALFieldDefn = GDAL.OGRFieldDefnH -const GDALGeometry = GDAL.OGRGeometryH -const GDALGeomFieldDefn = GDAL.OGRGeomFieldDefnH -const GDALProgressFunc = GDAL.GDALProgressFunc -const GDALRasterAttrTable = GDAL.GDALRasterAttributeTableH -const GDALRasterBand = GDAL.GDALRasterBandH -const GDALSpatialRef = GDAL.OGRSpatialReferenceH -const GDALStyleManager = GDAL.OGRStyleMgrH -const GDALStyleTable = GDAL.OGRStyleTableH -const GDALStyleTool = GDAL.OGRStyleToolH - -const StringList = Ptr{Cstring} abstract type AbstractGeometry <: GeoInterface.AbstractGeometry end # needs to have a `ptr::GDALGeometry` attribute @@ -226,403 +206,111 @@ mutable struct ColorTable ptr::GDALColorTable end -CPLErr = GDAL.CPLErr -CPLXMLNodeType = GDAL.CPLXMLNodeType -GDALDataType = GDAL.GDALDataType -GDALAsyncStatusType = GDAL.GDALAsyncStatusType -GDALAccess = GDAL.GDALAccess -GDALRWFlag = GDAL.GDALRWFlag -GDALRIOResampleAlg = GDAL.GDALRIOResampleAlg -GDALColorInterp = GDAL.GDALColorInterp -GDALPaletteInterp = GDAL.GDALPaletteInterp -GDALRATFieldType = GDAL.GDALRATFieldType -GDALRATFieldUsage = GDAL.GDALRATFieldUsage -GDALTileOrganization = GDAL.GDALTileOrganization -GDALGridAlgorithm = GDAL.GDALGridAlgorithm -OGRwkbGeometryType = GDAL.OGRwkbGeometryType -OGRwkbVariant = GDAL.OGRwkbVariant -OGRwkbByteOrder = GDAL.OGRwkbByteOrder -OGRFieldSubType = GDAL.OGRFieldSubType -OGRJustification = GDAL.OGRJustification -OGRSTClassId = GDAL.OGRSTClassId -OGRSTUnitId = GDAL.OGRSTUnitId -OGRSTPenParam = GDAL.OGRSTPenParam -OGRSTBrushParam = GDAL.OGRSTBrushParam -OGRSTSymbolParam = GDAL.OGRSTSymbolParam -OGRSTLabelParam = GDAL.OGRSTLabelParam -GDALResampleAlg = GDAL.GDALResampleAlg -GWKAverageOrModeAlg = GDAL.GWKAverageOrModeAlg -OGRAxisOrientation = GDAL.OGRAxisOrientation - -"return the corresponding `DataType` in julia" -const _JLTYPE = Dict{GDALDataType, DataType}( - GDAL.GDT_Unknown => Any, - GDAL.GDT_Byte => UInt8, - GDAL.GDT_UInt16 => UInt16, - GDAL.GDT_Int16 => Int16, - GDAL.GDT_UInt32 => UInt32, - GDAL.GDT_Int32 => Int32, - GDAL.GDT_Float32 => Float32, - GDAL.GDT_Float64 => Float64) - "return the corresponding `DataType` in julia" datatype(gt::GDALDataType) = get(_JLTYPE, gt) do error("Unknown GDALDataType: $gt") end -const _GDALTYPE = Dict{DataType,GDALDataType}( - Any => GDAL.GDT_Unknown, - UInt8 => GDAL.GDT_Byte, - UInt16 => GDAL.GDT_UInt16, - Int16 => GDAL.GDT_Int16, - UInt32 => GDAL.GDT_UInt32, - Int32 => GDAL.GDT_Int32, - Float32 => GDAL.GDT_Float32, - Float64 => GDAL.GDT_Float64) - "return the corresponding `GDAL.GDALDataType`" gdaltype(dt::DataType) = get(_GDALTYPE, dt) do error("Unknown DataType: $dt") end -@enum(OGRFieldType, - OFTInteger = Int32(GDAL.OFTInteger), - OFTIntegerList = Int32(GDAL.OFTIntegerList), - OFTReal = Int32(GDAL.OFTReal), - OFTRealList = Int32(GDAL.OFTRealList), - OFTString = Int32(GDAL.OFTString), - OFTStringList = Int32(GDAL.OFTStringList), - OFTWideString = Int32(GDAL.OFTWideString), - OFTWideStringList = Int32(GDAL.OFTWideStringList), - OFTBinary = Int32(GDAL.OFTBinary), - OFTDate = Int32(GDAL.OFTDate), - OFTTime = Int32(GDAL.OFTTime), - OFTDateTime = Int32(GDAL.OFTDateTime), - OFTInteger64 = Int32(GDAL.OFTInteger64), - OFTInteger64List = Int32(GDAL.OFTInteger64List), - # OFTMaxType = Int32(GDAL.OFTMaxType), # unsupported -) - -"return the corresponding `DataType` in julia" -const _FIELDTYPE = Dict{OGRFieldType, DataType}( - OFTInteger => Int32, - OFTIntegerList => Vector{Int32}, - OFTReal => Float64, - OFTRealList => Vector{Float64}, - OFTString => String, - OFTStringList => Vector{String}, - OFTWideString => Nothing, # deprecated - OFTWideStringList => Nothing, # deprecated - OFTBinary => Vector{UInt8}, - OFTDate => Dates.Date, - OFTTime => Dates.Time, - OFTDateTime => Dates.DateTime, - OFTInteger64 => Int64, - OFTInteger64List => Vector{Int64}, - # OFTMaxType => Nothing # unsupported -) - -const _GDALFIELDTYPE = Dict{GDAL.OGRFieldType, OGRFieldType}( - GDAL.OFTInteger => OFTInteger, - GDAL.OFTIntegerList => OFTIntegerList, - GDAL.OFTReal => OFTReal, - GDAL.OFTRealList => OFTRealList, - GDAL.OFTString => OFTString, - GDAL.OFTStringList => OFTStringList, - GDAL.OFTWideString => OFTWideString, - GDAL.OFTWideStringList => OFTWideStringList, - GDAL.OFTBinary => OFTBinary, - GDAL.OFTDate => OFTDate, - GDAL.OFTTime => OFTTime, - GDAL.OFTDateTime => OFTDateTime, - GDAL.OFTInteger64 => OFTInteger64, - GDAL.OFTInteger64List => OFTInteger64List, - # GDAL.OFTMaxType => OFTMaxType, # unsupported -) - -const _GDALFIELDTYPES = Dict{OGRFieldType, GDAL.OGRFieldType}( - OFTInteger => GDAL.OFTInteger, - OFTIntegerList => GDAL.OFTIntegerList, - OFTReal => GDAL.OFTReal, - OFTRealList => GDAL.OFTRealList, - OFTString => GDAL.OFTString, - OFTStringList => GDAL.OFTStringList, - OFTWideString => GDAL.OFTWideString, - OFTWideStringList => GDAL.OFTWideStringList, - OFTBinary => GDAL.OFTBinary, - OFTDate => GDAL.OFTDate, - OFTTime => GDAL.OFTTime, - OFTDateTime => GDAL.OFTDateTime, - OFTInteger64 => GDAL.OFTInteger64, - OFTInteger64List => GDAL.OFTInteger64List, - # OFTMaxType => GDAL.OFTMaxType, # unsupported -) - -convert(::Type{GDAL.OGRFieldType}, ft::OGRFieldType) = get(_GDALFIELDTYPES, ft) do - error("Unknown OGRFieldType: $ft") -end - -"returns the `OGRFieldType` in julia" -gdaltype(ft::GDAL.OGRFieldType) = get(_GDALFIELDTYPE, ft) do - error("Unknown GDAL.OGRFieldType: $ft") -end - "return the corresponding `DataType` in julia" datatype(ft::OGRFieldType) = get(_FIELDTYPE, ft) do error("Unknown OGRFieldType: $ft") end -@enum(WKBGeometryType, - wkbUnknown = 0, - wkbPoint = 1, - wkbLineString = 2, - wkbPolygon = 3, - wkbMultiPoint = 4, - wkbMultiLineString = 5, - wkbMultiPolygon = 6, - wkbGeometryCollection = 7, - wkbCircularString = 8, - wkbCompoundCurve = 9, - wkbCurvePolygon = 10, - wkbMultiCurve = 11, - wkbMultiSurface = 12, - wkbCurve = 13, - wkbSurface = 14, - wkbPolyhedralSurface = 15, - wkbTIN = 16, - wkbTriangle = 17, - wkbNone = 18, - wkbLinearRing = 19, - wkbCircularStringZ = 20, - wkbCompoundCurveZ = 21, - wkbCurvePolygonZ = 22, - wkbMultiCurveZ = 23, - wkbMultiSurfaceZ = 24, - wkbCurveZ = 25, - wkbSurfaceZ = 26, - wkbPolyhedralSurfaceZ = 27, - wkbTINZ = 28, - wkbTriangleZ = 29, - wkbPointM = 30, - wkbLineStringM = 31, - wkbPolygonM = 32, - wkbMultiPointM = 33, - wkbMultiLineStringM = 34, - wkbMultiPolygonM = 35, - wkbGeometryCollectionM = 36, - wkbCircularStringM = 37, - wkbCompoundCurveM = 38, - wkbCurvePolygonM = 39, - wkbMultiCurveM = 40, - wkbMultiSurfaceM = 41, - wkbCurveM = 42, - wkbSurfaceM = 43, - wkbPolyhedralSurfaceM = 44, - wkbTINM = 45, - wkbTriangleM = 46, - wkbPointZM = 47, - wkbLineStringZM = 48, - wkbPolygonZM = 49, - wkbMultiPointZM = 50, - wkbMultiLineStringZM = 51, - wkbMultiPolygonZM = 52, - wkbGeometryCollectionZM = 53, - wkbCircularStringZM = 54, - wkbCompoundCurveZM = 55, - wkbCurvePolygonZM = 56, - wkbMultiCurveZM = 57, - wkbMultiSurfaceZM = 58, - wkbCurveZM = 59, - wkbSurfaceZM = 60, - wkbPolyhedralSurfaceZM = 61, - wkbTINZM = 62, - wkbTriangleZM = 63, - wkbPoint25D = 64, - wkbLineString25D = 65, - wkbPolygon25D = 66, - wkbMultiPoint25D = 67, - wkbMultiLineString25D = 68, - wkbMultiPolygon25D = 69, - wkbGeometryCollection25D = 70, -) - -const _WKBGEOMETRYTYPE = Dict{GDAL.OGRwkbGeometryType, WKBGeometryType}( - GDAL.wkbUnknown => wkbUnknown, - GDAL.wkbPoint => wkbPoint, - GDAL.wkbLineString => wkbLineString, - GDAL.wkbPolygon => wkbPolygon, - GDAL.wkbMultiPoint => wkbMultiPoint, - GDAL.wkbMultiLineString => wkbMultiLineString, - GDAL.wkbMultiPolygon => wkbMultiPolygon, - GDAL.wkbGeometryCollection => wkbGeometryCollection, - GDAL.wkbCircularString => wkbCircularString, - GDAL.wkbCompoundCurve => wkbCompoundCurve, - GDAL.wkbCurvePolygon => wkbCurvePolygon, - GDAL.wkbMultiCurve => wkbMultiCurve, - GDAL.wkbMultiSurface => wkbMultiSurface, - GDAL.wkbCurve => wkbCurve, - GDAL.wkbSurface => wkbSurface, - GDAL.wkbPolyhedralSurface => wkbPolyhedralSurface, - GDAL.wkbTIN => wkbTIN, - GDAL.wkbTriangle => wkbTriangle, - GDAL.wkbNone => wkbNone, - GDAL.wkbLinearRing => wkbLinearRing, - GDAL.wkbCircularStringZ => wkbCircularStringZ, - GDAL.wkbCompoundCurveZ => wkbCompoundCurveZ, - GDAL.wkbCurvePolygonZ => wkbCurvePolygonZ, - GDAL.wkbMultiCurveZ => wkbMultiCurveZ, - GDAL.wkbMultiSurfaceZ => wkbMultiSurfaceZ, - GDAL.wkbCurveZ => wkbCurveZ, - GDAL.wkbSurfaceZ => wkbSurfaceZ, - GDAL.wkbPolyhedralSurfaceZ => wkbPolyhedralSurfaceZ, - GDAL.wkbTINZ => wkbTINZ, - GDAL.wkbTriangleZ => wkbTriangleZ, - GDAL.wkbPointM => wkbPointM, - GDAL.wkbLineStringM => wkbLineStringM, - GDAL.wkbPolygonM => wkbPolygonM, - GDAL.wkbMultiPointM => wkbMultiPointM, - GDAL.wkbMultiLineStringM => wkbMultiLineStringM, - GDAL.wkbMultiPolygonM => wkbMultiPolygonM, - GDAL.wkbGeometryCollectionM => wkbGeometryCollectionM, - GDAL.wkbCircularStringM => wkbCircularStringM, - GDAL.wkbCompoundCurveM => wkbCompoundCurveM, - GDAL.wkbCurvePolygonM => wkbCurvePolygonM, - GDAL.wkbMultiCurveM => wkbMultiCurveM, - GDAL.wkbMultiSurfaceM => wkbMultiSurfaceM, - GDAL.wkbCurveM => wkbCurveM, - GDAL.wkbSurfaceM => wkbSurfaceM, - GDAL.wkbPolyhedralSurfaceM => wkbPolyhedralSurfaceM, - GDAL.wkbTINM => wkbTINM, - GDAL.wkbTriangleM => wkbTriangleM, - GDAL.wkbPointZM => wkbPointZM, - GDAL.wkbLineStringZM => wkbLineStringZM, - GDAL.wkbPolygonZM => wkbPolygonZM, - GDAL.wkbMultiPointZM => wkbMultiPointZM, - GDAL.wkbMultiLineStringZM => wkbMultiLineStringZM, - GDAL.wkbMultiPolygonZM => wkbMultiPolygonZM, - GDAL.wkbGeometryCollectionZM => wkbGeometryCollectionZM, - GDAL.wkbCircularStringZM => wkbCircularStringZM, - GDAL.wkbCompoundCurveZM => wkbCompoundCurveZM, - GDAL.wkbCurvePolygonZM => wkbCurvePolygonZM, - GDAL.wkbMultiCurveZM => wkbMultiCurveZM, - GDAL.wkbMultiSurfaceZM => wkbMultiSurfaceZM, - GDAL.wkbCurveZM => wkbCurveZM, - GDAL.wkbSurfaceZM => wkbSurfaceZM, - GDAL.wkbPolyhedralSurfaceZM => wkbPolyhedralSurfaceZM, - GDAL.wkbTINZM => wkbTINZM, - GDAL.wkbTriangleZM => wkbTriangleZM, - GDAL.wkbPoint25D => wkbPoint25D, - GDAL.wkbLineString25D => wkbLineString25D, - GDAL.wkbPolygon25D => wkbPolygon25D, - GDAL.wkbMultiPoint25D => wkbMultiPoint25D, - GDAL.wkbMultiLineString25D => wkbMultiLineString25D, - GDAL.wkbMultiPolygon25D => wkbMultiPolygon25D, - GDAL.wkbGeometryCollection25D => wkbGeometryCollection25D, -) - -const _WKBGEOMETRYTYPES = Dict{WKBGeometryType, GDAL.OGRwkbGeometryType}( - wkbUnknown => GDAL.wkbUnknown, - wkbPoint => GDAL.wkbPoint, - wkbLineString => GDAL.wkbLineString, - wkbPolygon => GDAL.wkbPolygon, - wkbMultiPoint => GDAL.wkbMultiPoint, - wkbMultiLineString => GDAL.wkbMultiLineString, - wkbMultiPolygon => GDAL.wkbMultiPolygon, - wkbGeometryCollection => GDAL.wkbGeometryCollection, - wkbCircularString => GDAL.wkbCircularString, - wkbCompoundCurve => GDAL.wkbCompoundCurve, - wkbCurvePolygon => GDAL.wkbCurvePolygon, - wkbMultiCurve => GDAL.wkbMultiCurve, - wkbMultiSurface => GDAL.wkbMultiSurface, - wkbCurve => GDAL.wkbCurve, - wkbSurface => GDAL.wkbSurface, - wkbPolyhedralSurface => GDAL.wkbPolyhedralSurface, - wkbTIN => GDAL.wkbTIN, - wkbTriangle => GDAL.wkbTriangle, - wkbNone => GDAL.wkbNone, - wkbLinearRing => GDAL.wkbLinearRing, - wkbCircularStringZ => GDAL.wkbCircularStringZ, - wkbCompoundCurveZ => GDAL.wkbCompoundCurveZ, - wkbCurvePolygonZ => GDAL.wkbCurvePolygonZ, - wkbMultiCurveZ => GDAL.wkbMultiCurveZ, - wkbMultiSurfaceZ => GDAL.wkbMultiSurfaceZ, - wkbCurveZ => GDAL.wkbCurveZ, - wkbSurfaceZ => GDAL.wkbSurfaceZ, - wkbPolyhedralSurfaceZ => GDAL.wkbPolyhedralSurfaceZ, - wkbTINZ => GDAL.wkbTINZ, - wkbTriangleZ => GDAL.wkbTriangleZ, - wkbPointM => GDAL.wkbPointM, - wkbLineStringM => GDAL.wkbLineStringM, - wkbPolygonM => GDAL.wkbPolygonM, - wkbMultiPointM => GDAL.wkbMultiPointM, - wkbMultiLineStringM => GDAL.wkbMultiLineStringM, - wkbMultiPolygonM => GDAL.wkbMultiPolygonM, - wkbGeometryCollectionM => GDAL.wkbGeometryCollectionM, - wkbCircularStringM => GDAL.wkbCircularStringM, - wkbCompoundCurveM => GDAL.wkbCompoundCurveM, - wkbCurvePolygonM => GDAL.wkbCurvePolygonM, - wkbMultiCurveM => GDAL.wkbMultiCurveM, - wkbMultiSurfaceM => GDAL.wkbMultiSurfaceM, - wkbCurveM => GDAL.wkbCurveM, - wkbSurfaceM => GDAL.wkbSurfaceM, - wkbPolyhedralSurfaceM => GDAL.wkbPolyhedralSurfaceM, - wkbTINM => GDAL.wkbTINM, - wkbTriangleM => GDAL.wkbTriangleM, - wkbPointZM => GDAL.wkbPointZM, - wkbLineStringZM => GDAL.wkbLineStringZM, - wkbPolygonZM => GDAL.wkbPolygonZM, - wkbMultiPointZM => GDAL.wkbMultiPointZM, - wkbMultiLineStringZM => GDAL.wkbMultiLineStringZM, - wkbMultiPolygonZM => GDAL.wkbMultiPolygonZM, - wkbGeometryCollectionZM => GDAL.wkbGeometryCollectionZM, - wkbCircularStringZM => GDAL.wkbCircularStringZM, - wkbCompoundCurveZM => GDAL.wkbCompoundCurveZM, - wkbCurvePolygonZM => GDAL.wkbCurvePolygonZM, - wkbMultiCurveZM => GDAL.wkbMultiCurveZM, - wkbMultiSurfaceZM => GDAL.wkbMultiSurfaceZM, - wkbCurveZM => GDAL.wkbCurveZM, - wkbSurfaceZM => GDAL.wkbSurfaceZM, - wkbPolyhedralSurfaceZM => GDAL.wkbPolyhedralSurfaceZM, - wkbTINZM => GDAL.wkbTINZM, - wkbTriangleZM => GDAL.wkbTriangleZM, - wkbPoint25D => GDAL.wkbPoint25D, - wkbLineString25D => GDAL.wkbLineString25D, - wkbPolygon25D => GDAL.wkbPolygon25D, - wkbMultiPoint25D => GDAL.wkbMultiPoint25D, - wkbMultiLineString25D => GDAL.wkbMultiLineString25D, - wkbMultiPolygon25D => GDAL.wkbMultiPolygon25D, - wkbGeometryCollection25D => GDAL.wkbGeometryCollection25D, -) - -function convert(::Type{GDAL.OGRwkbGeometryType}, wkbType::WKBGeometryType) - return get(_WKBGEOMETRYTYPES, wkbType) do - error("Unknown WKBGeometryType: $wkbType") - end -end - -"returns the `OGRFieldType` in julia" -function gdaltype(wkbType::GDAL.OGRwkbGeometryType) - return get(_WKBGEOMETRYTYPE, wkbType) do - error("Unknown GDAL.OGRwkbGeometryType: $wkbType") - end -end - -@enum(GDALOpenFlag, - OF_ReadOnly = GDAL.GDAL_OF_READONLY, # 0x00 - OF_Update = GDAL.GDAL_OF_UPDATE, # 0x01 - # OF_All = GDAL.GDAL_OF_ALL, # 0x00 - OF_Raster = GDAL.GDAL_OF_RASTER, # 0x02 - OF_Vector = GDAL.GDAL_OF_VECTOR, # 0x04 - OF_GNM = GDAL.GDAL_OF_GNM, # 0x08 - OF_Kind_Mask = GDAL.GDAL_OF_KIND_MASK, # 0x1e - OF_Shared = GDAL.GDAL_OF_SHARED, # 0x20 - OF_Verbose_Error = GDAL.GDAL_OF_VERBOSE_ERROR, # 0x40 - OF_Internal = GDAL.GDAL_OF_INTERNAL, # 0x80 - # OF_DEFAULT_BLOCK_ACCESS = GDAL.GDAL_OF_DEFAULT_BLOCK_ACCESS, # 0 - OF_Array_Block_Access = GDAL.GDAL_OF_ARRAY_BLOCK_ACCESS, # 0x0100 - OF_Hashset_Block_Access = GDAL.GDAL_OF_HASHSET_BLOCK_ACCESS, # 0x0200 - # OF_RESERVED_1 = GDAL.GDAL_OF_RESERVED_1, # 0x0300 - OF_Block_Access_Mask = GDAL.GDAL_OF_BLOCK_ACCESS_MASK) # 0x0300 +eval(@gdalenum(OGRFieldType::GDAL.OGRFieldType, + OFTInteger::GDAL.OFTInteger, + OFTIntegerList::GDAL.OFTIntegerList, + OFTReal::GDAL.OFTReal, + OFTRealList::GDAL.OFTRealList, + OFTString::GDAL.OFTString, + OFTStringList::GDAL.OFTStringList, + OFTWideString::GDAL.OFTWideString, + OFTWideStringList::GDAL.OFTWideStringList, + OFTBinary::GDAL.OFTBinary, + OFTDate::GDAL.OFTDate, + OFTTime::GDAL.OFTTime, + OFTDateTime::GDAL.OFTDateTime, + OFTInteger64::GDAL.OFTInteger64, + OFTInteger64List::GDAL.OFTInteger64List +)) + +eval(@gdalenum(WKBGeometryType::GDAL.OGRwkbGeometryType, + wkbUnknown::GDAL.wkbUnknown, + wkbPoint::GDAL.wkbPoint, + wkbLineString::GDAL.wkbLineString, + wkbPolygon::GDAL.wkbPolygon, + wkbMultiPoint::GDAL.wkbMultiPoint, + wkbMultiLineString::GDAL.wkbMultiLineString, + wkbMultiPolygon::GDAL.wkbMultiPolygon, + wkbGeometryCollection::GDAL.wkbGeometryCollection, + wkbCircularString::GDAL.wkbCircularString, + wkbCompoundCurve::GDAL.wkbCompoundCurve, + wkbCurvePolygon::GDAL.wkbCurvePolygon, + wkbMultiCurve::GDAL.wkbMultiCurve, + wkbMultiSurface::GDAL.wkbMultiSurface, + wkbCurve::GDAL.wkbCurve, + wkbSurface::GDAL.wkbSurface, + wkbPolyhedralSurface::GDAL.wkbPolyhedralSurface, + wkbTIN::GDAL.wkbTIN, + wkbTriangle::GDAL.wkbTriangle, + wkbNone::GDAL.wkbNone, + wkbLinearRing::GDAL.wkbLinearRing, + wkbCircularStringZ::GDAL.wkbCircularStringZ, + wkbCompoundCurveZ::GDAL.wkbCompoundCurveZ, + wkbCurvePolygonZ::GDAL.wkbCurvePolygonZ, + wkbMultiCurveZ::GDAL.wkbMultiCurveZ, + wkbMultiSurfaceZ::GDAL.wkbMultiSurfaceZ, + wkbCurveZ::GDAL.wkbCurveZ, + wkbSurfaceZ::GDAL.wkbSurfaceZ, + wkbPolyhedralSurfaceZ::GDAL.wkbPolyhedralSurfaceZ, + wkbTINZ::GDAL.wkbTINZ, + wkbTriangleZ::GDAL.wkbTriangleZ, + wkbPointM::GDAL.wkbPointM, + wkbLineStringM::GDAL.wkbLineStringM, + wkbPolygonM::GDAL.wkbPolygonM, + wkbMultiPointM::GDAL.wkbMultiPointM, + wkbMultiLineStringM::GDAL.wkbMultiLineStringM, + wkbMultiPolygonM::GDAL.wkbMultiPolygonM, + wkbGeometryCollectionM::GDAL.wkbGeometryCollectionM, + wkbCircularStringM::GDAL.wkbCircularStringM, + wkbCompoundCurveM::GDAL.wkbCompoundCurveM, + wkbCurvePolygonM::GDAL.wkbCurvePolygonM, + wkbMultiCurveM::GDAL.wkbMultiCurveM, + wkbMultiSurfaceM::GDAL.wkbMultiSurfaceM, + wkbCurveM::GDAL.wkbCurveM, + wkbSurfaceM::GDAL.wkbSurfaceM, + wkbPolyhedralSurfaceM::GDAL.wkbPolyhedralSurfaceM, + wkbTINM::GDAL.wkbTINM, + wkbTriangleM::GDAL.wkbTriangleM, + wkbPointZM::GDAL.wkbPointZM, + wkbLineStringZM::GDAL.wkbLineStringZM, + wkbPolygonZM::GDAL.wkbPolygonZM, + wkbMultiPointZM::GDAL.wkbMultiPointZM, + wkbMultiLineStringZM::GDAL.wkbMultiLineStringZM, + wkbMultiPolygonZM::GDAL.wkbMultiPolygonZM, + wkbGeometryCollectionZM::GDAL.wkbGeometryCollectionZM, + wkbCircularStringZM::GDAL.wkbCircularStringZM, + wkbCompoundCurveZM::GDAL.wkbCompoundCurveZM, + wkbCurvePolygonZM::GDAL.wkbCurvePolygonZM, + wkbMultiCurveZM::GDAL.wkbMultiCurveZM, + wkbMultiSurfaceZM::GDAL.wkbMultiSurfaceZM, + wkbCurveZM::GDAL.wkbCurveZM, + wkbSurfaceZM::GDAL.wkbSurfaceZM, + wkbPolyhedralSurfaceZM::GDAL.wkbPolyhedralSurfaceZM, + wkbTINZM::GDAL.wkbTINZM, + wkbTriangleZM::GDAL.wkbTriangleZM, + wkbPoint25D::GDAL.wkbPoint25D, + wkbLineString25D::GDAL.wkbLineString25D, + wkbPolygon25D::GDAL.wkbPolygon25D, + wkbMultiPoint25D::GDAL.wkbMultiPoint25D, + wkbMultiLineString25D::GDAL.wkbMultiLineString25D, + wkbMultiPolygon25D::GDAL.wkbMultiPolygon25D, + wkbGeometryCollection25D::GDAL.wkbGeometryCollection25D, +)) import Base.| diff --git a/src/utils.jl b/src/utils.jl index e4236760..ef90a17f 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,3 +1,32 @@ +macro gdalenum(args...) + @assert length(args) > 0 + @assert args[1].head == :(::) + type1 = esc(args[1].args[1]) + type2 = esc(args[1].args[2]) + forward_map = Expr[ + Expr(:tuple, esc.(a.args)...) for a in args[2:end] + ] + reverse_map = Expr[ + Expr(:tuple, esc.(reverse(a.args))...) for a in args[2:end] + ] + quote + function Base.convert(::Type{$type2}, ft::$type1) + fwd = Dict{$type1, $type2}(Tuple{$type1, $type2}[$(forward_map...)]) + return get(fwd, ft) do + error("Unknown type: $ft") + end + end + + "returns the corresponding type in ArchGDAL" + function ArchGDAL.gdaltype(ft::$type2) + rev = Dict{$type2, $type1}(Tuple{$type2, $type1}[$(reverse_map...)]) + return get(rev, ft) do + error("Unknown type: $ft") + end + end + end +end + macro gdal(args...) @assert length(args) > 0 @assert args[1].head == :(::) From 91a6af54f9700b1b79d76790403af289201601e6 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 19 Apr 2021 03:24:50 -0700 Subject: [PATCH 013/169] annotate function signatures with return types --- src/base/display.jl | 87 ++++++++--- src/base/iterators.jl | 113 +++++++++----- src/ogr/feature.jl | 143 ++++++++++-------- src/ogr/featuredefn.jl | 82 ++++++---- src/ogr/featurelayer.jl | 141 ++++++++++------- src/ogr/fielddefn.jl | 96 ++++++------ src/ogr/geometry.jl | 326 +++++++++++++++++++++++----------------- src/ogr/styletable.jl | 123 ++++++++++----- 8 files changed, 691 insertions(+), 420 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index 0fc761f7..e0724e80 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -1,11 +1,17 @@ -function Base.show(io::IO, drv::Driver) - drv.ptr == C_NULL && (return print(io, "NULL Driver")) +function Base.show(io::IO, drv::Driver)::IO + if drv.ptr == C_NULL + print(io, "NULL Driver") + return io + end print(io, "Driver: $(shortname(drv))/$(longname(drv))") return io end -function Base.show(io::IO, dataset::AbstractDataset) - dataset.ptr == C_NULL && (return print(io, "NULL Dataset")) +function Base.show(io::IO, dataset::AbstractDataset)::IO + if dataset.ptr == C_NULL + print(io, "NULL Dataset") + return io + end println(io, "GDAL Dataset ($(getdriver(dataset)))") println(io, "File(s): ") for (i,filename) in enumerate(filelist(dataset)) @@ -49,13 +55,16 @@ function Base.show(io::IO, dataset::AbstractDataset) end #Add method to avoid show from DiskArrays -Base.show(io::IO, raster::RasterDataset) = show(io, raster.ds) +Base.show(io::IO, raster::RasterDataset)::IO = show(io, raster.ds) -Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset) = +Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::IO = show(io, raster.ds) -function summarize(io::IO, rasterband::AbstractRasterBand) - rasterband.ptr == C_NULL && (return print(io, "NULL RasterBand")) +function summarize(io::IO, rasterband::AbstractRasterBand)::IO + if rasterband.ptr == C_NULL + print(io, "NULL RasterBand") + return io + end access = accessflag(rasterband) color = getname(getcolorinterp(rasterband)) xsize = width(rasterband) @@ -66,11 +75,18 @@ function summarize(io::IO, rasterband::AbstractRasterBand) return io end -Base.show(io::IO, rasterband::AbstractRasterBand) = +Base.show(io::IO, rasterband::AbstractRasterBand)::IO = show(io, "text/plain", rasterband) -function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand) - rasterband.ptr == C_NULL && (return print(io, "NULL RasterBand")) +function Base.show( + io::IO, + ::MIME"text/plain", + rasterband::AbstractRasterBand + )::IO + if rasterband.ptr == C_NULL + print(io, "NULL RasterBand") + return io + end summarize(io, rasterband) (x,y) = blocksize(rasterband) sc = getscale(rasterband) @@ -90,8 +106,11 @@ function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand) end # assumes that the layer is reset, and will reset it after display -function Base.show(io::IO, layer::AbstractFeatureLayer) - layer.ptr == C_NULL && (return println(io, "NULL Layer")) +function Base.show(io::IO, layer::AbstractFeatureLayer)::IO + if layer.ptr == C_NULL + println(io, "NULL Layer") + return io + end layergeomtype = getgeomtype(layer) println(io, "Layer: $(getname(layer))") featuredefn = layerdefn(layer) @@ -152,8 +171,11 @@ function Base.show(io::IO, layer::AbstractFeatureLayer) return io end -function Base.show(io::IO, featuredefn::AbstractFeatureDefn) - featuredefn.ptr == C_NULL && (return print(io, "NULL FeatureDefn")) +function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO + if featuredefn.ptr == C_NULL + print(io, "NULL FeatureDefn") + return io + end n = ngeom(featuredefn) ngeomdisplay = min(n, 3) for i in 1:ngeomdisplay @@ -172,20 +194,29 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn) return io end -function Base.show(io::IO, fd::AbstractFieldDefn) - fd.ptr == C_NULL && (return print(io, "NULL FieldDefn")) +function Base.show(io::IO, fd::AbstractFieldDefn)::IO + if fd.ptr == C_NULL + print(io, "NULL FieldDefn") + return io + end print(io, "$(getname(fd)) ($(gettype(fd)))") return io end -function Base.show(io::IO, gfd::AbstractGeomFieldDefn) - gfd.ptr == C_NULL && (return print(io, "NULL GeomFieldDefn")) +function Base.show(io::IO, gfd::AbstractGeomFieldDefn)::IO + if gfd.ptr == C_NULL + print(io, "NULL GeomFieldDefn") + return io + end print(io, "$(getname(gfd)) ($(gettype(gfd)))") return io end -function Base.show(io::IO, feature::Feature) - feature.ptr == C_NULL && (return println(io, "NULL Feature")) +function Base.show(io::IO, feature::Feature)::IO + if feature.ptr == C_NULL + println(io, "NULL Feature") + return io + end println(io, "Feature") n = ngeom(feature) for i in 1:min(n, 3) @@ -203,8 +234,11 @@ function Base.show(io::IO, feature::Feature) return io end -function Base.show(io::IO, spref::AbstractSpatialRef) - spref.ptr == C_NULL && (return print(io, "NULL Spatial Reference System")) +function Base.show(io::IO, spref::AbstractSpatialRef)::IO + if spref.ptr == C_NULL + print(io, "NULL Spatial Reference System") + return io + end projstr = toPROJ4(spref) if length(projstr) > 45 projstart = projstr[1:35] @@ -216,8 +250,11 @@ function Base.show(io::IO, spref::AbstractSpatialRef) return io end -function Base.show(io::IO, geom::AbstractGeometry) - geom.ptr == C_NULL && (return print(io, "NULL Geometry")) +function Base.show(io::IO, geom::AbstractGeometry)::IO + if geom.ptr == C_NULL + print(io, "NULL Geometry") + return io + end compact = get(io, :compact, false) if !compact diff --git a/src/base/iterators.jl b/src/base/iterators.jl index 653725ce..1fa2871d 100644 --- a/src/base/iterators.jl +++ b/src/base/iterators.jl @@ -1,4 +1,7 @@ -function Base.iterate(layer::AbstractFeatureLayer, state::Int=0) +function Base.iterate( + layer::AbstractFeatureLayer, + state::Integer = 0 + )::Union{Nothing, Tuple{Feature, Int64}} layer.ptr == C_NULL && return nothing state == 0 && resetreading!(layer) ptr = GDAL.ogr_l_getnextfeature(layer.ptr) @@ -10,30 +13,40 @@ function Base.iterate(layer::AbstractFeatureLayer, state::Int=0) end end -Base.eltype(layer::AbstractFeatureLayer) = Feature +Base.eltype(layer::AbstractFeatureLayer)::DataType = Feature -Base.length(layer::AbstractFeatureLayer) = nfeature(layer, true) +Base.length(layer::AbstractFeatureLayer)::Integer = nfeature(layer, true) -struct BlockIterator - rows::Cint - cols::Cint - ni::Cint - nj::Cint - n::Cint - xbsize::Cint - ybsize::Cint +struct BlockIterator{T <: Integer} + rows::T + cols::T + ni::T + nj::T + n::T + xbsize::T + ybsize::T end -function blocks(raster::AbstractRasterBand) +function blocks( + ::Type{T}, + raster::AbstractRasterBand + )::BlockIterator{T} where {T <: Integer} (xbsize, ybsize) = blocksize(raster) - rows = height(raster) - cols = width(raster) - ni = ceil(Cint, rows / ybsize) - nj = ceil(Cint, cols / xbsize) - return BlockIterator(rows, cols, ni, nj, ni * nj, xbsize, ybsize) + rows = T(height(raster)) + cols = T(width(raster)) + ni = ceil(T, rows / ybsize) + nj = ceil(T, cols / xbsize) + return BlockIterator{T}(rows, cols, ni, nj, ni * nj, xbsize, ybsize) end -function Base.iterate(obj::BlockIterator, iter::Int=0) +function blocks(raster::AbstractRasterBand)::BlockIterator{Int64} + return blocks(Int64, raster) +end + +function Base.iterate( + obj::BlockIterator{T}, + iter::T = 0 + )::Union{Nothing, Tuple{Tuple{Tuple{T, T}, Tuple{T, T}}, T}} where T iter == obj.n && return nothing j = floor(Int, iter / obj.ni) i = iter % obj.ni @@ -47,21 +60,41 @@ function Base.iterate(obj::BlockIterator, iter::Int=0) else obj.cols - j * obj.xbsize end - return (((i, j), (nrows, ncols)), iter+1) + return (((i, j), (nrows, ncols)), iter + 1) end -struct WindowIterator - blockiter::BlockIterator +struct WindowIterator{T <: Integer} + blockiter::BlockIterator{T} 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.IteratorSize(::Type{WindowIterator{T}}) where {T <: Integer} + return Base.HasShape{2}() +end + +function Base.IteratorEltype(::Type{WindowIterator{T}}) where {T <: Integer} + return Base.HasEltype() +end + +function Base.eltype(::WindowIterator{T})::DataType where {T <: Integer} + return Tuple{UnitRange{T}, UnitRange{T}} +end + +function windows( + ::Type{T}, + raster::AbstractRasterBand + )::WindowIterator{T} where {T <: Integer} + return WindowIterator{T}(blocks(T, raster)) +end -function Base.iterate(obj::WindowIterator, iter::Int=0) +windows(raster::AbstractRasterBand)::WindowIterator{Int64} = + windows(Int64, raster) + +function Base.iterate( + obj::WindowIterator{T}, + iter::T = 0 + )::Union{Nothing, Tuple{Tuple{UnitRange{T}, UnitRange{T}}, T}} where T handle = obj.blockiter next = Base.iterate(handle, iter) next == nothing && return nothing @@ -72,21 +105,33 @@ function Base.iterate(obj::WindowIterator, iter::Int=0) ) end -mutable struct BufferIterator{T <: Real} +mutable struct BufferIterator{R <: Real, T <: Integer} raster::AbstractRasterBand - w::WindowIterator - buffer::Array{T, 2} + w::WindowIterator{T} + buffer::Matrix{R} end -function bufferwindows(raster::AbstractRasterBand) - return BufferIterator( +function bufferwindows( + ::Type{T}, + raster::AbstractRasterBand + )::BufferIterator{pixeltype(raster), T} where {T <: Integer} + return BufferIterator{pixeltype(raster), T}( raster, - windows(raster), - Array{pixeltype(raster)}(undef, blocksize(raster)...) + windows(T, raster), + Matrix{pixeltype(raster)}(undef, blocksize(raster)...) ) end -function Base.iterate(obj::BufferIterator, iter::Int=0) +function bufferwindows( + raster::AbstractRasterBand + )::BufferIterator{pixeltype(raster), Int64} + return bufferwindows(Int64, raster) +end + +function Base.iterate( + obj::BufferIterator{R, T}, + iter::T = 0 + )::Union{Nothing, Tuple{Matrix{R}, T}} where {R <: Real, T <: Integer} next = Base.iterate(obj.w, iter) next == nothing && return nothing ((cols, rows), iter) = next diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 0dcdcf37..1fa7c9dd 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -6,7 +6,7 @@ Duplicate feature. The newly created feature is owned by the caller, and will have its own reference to the OGRFeatureDefn. """ -unsafe_clone(feature::Feature) = Feature(GDAL.ogr_f_clone(feature.ptr)) +unsafe_clone(feature::Feature)::Feature = Feature(GDAL.ogr_f_clone(feature.ptr)) """ destroy(feature::Feature) @@ -19,7 +19,7 @@ to delete a feature created within the DLL. If the delete is done in the calling application the memory will be freed onto the application heap which is inappropriate. """ -function destroy(feature::Feature) +function destroy(feature::Feature)::Nothing GDAL.ogr_f_destroy(feature.ptr) feature.ptr = C_NULL return nothing @@ -42,10 +42,10 @@ passed geometry, but instead makes a copy of it. `OGRERR_NONE` if successful, or `OGR_UNSUPPORTED_GEOMETRY_TYPE` if the geometry type is illegal for the `OGRFeatureDefn` (checking not yet implemented). """ -function setgeom!(feature::Feature, geom::AbstractGeometry) +function setgeom!(feature::Feature, geom::AbstractGeometry)::Feature result = GDAL.ogr_f_setgeometry(feature.ptr, geom.ptr) @ogrerr result "OGRErr $result: Failed to set feature geometry." - return result + return feature end """ @@ -53,7 +53,7 @@ end Returns a clone of the geometry corresponding to the feature. """ -function getgeom(feature::Feature) +function getgeom(feature::Feature)::IGeometry result = GDAL.ogr_f_getgeometryref(feature.ptr) return if result == C_NULL IGeometry() @@ -62,7 +62,7 @@ function getgeom(feature::Feature) end end -function unsafe_getgeom(feature::Feature) +function unsafe_getgeom(feature::Feature)::Geometry result = GDAL.ogr_f_getgeometryref(feature.ptr) return if result == C_NULL Geometry() @@ -78,7 +78,7 @@ Fetch number of fields on this feature. This will always be the same as the field count for the OGRFeatureDefn. """ -nfield(feature::Feature) = GDAL.ogr_f_getfieldcount(feature.ptr) +nfield(feature::Feature)::Integer = GDAL.ogr_f_getfieldcount(feature.ptr) """ getfielddefn(feature::Feature, i::Integer) @@ -93,7 +93,7 @@ Fetch definition for this field. an handle to the field definition (from the `FeatureDefn`). This is an internal reference, and should not be deleted or modified. """ -getfielddefn(feature::Feature, i::Integer) = +getfielddefn(feature::Feature, i::Integer)::IFieldDefnView = IFieldDefnView(GDAL.ogr_f_getfielddefnref(feature.ptr, i)) """ @@ -111,8 +111,12 @@ the field index, or -1 if no matching field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. """ -findfieldindex(feature::Feature, name::Union{AbstractString, Symbol}) = - GDAL.ogr_f_getfieldindex(feature.ptr, name) +function findfieldindex( + feature::Feature, + name::Union{AbstractString, Symbol} + )::Integer + return GDAL.ogr_f_getfieldindex(feature.ptr, name) +end """ isfieldset(feature::Feature, i::Integer) @@ -123,7 +127,7 @@ Test if a field has ever been assigned a value or not. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -isfieldset(feature::Feature, i::Integer) = +isfieldset(feature::Feature, i::Integer)::Bool = Bool(GDAL.ogr_f_isfieldset(feature.ptr, i)) """ @@ -135,8 +139,10 @@ Clear a field, marking it as unset. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -unsetfield!(feature::Feature, i::Integer) = - (GDAL.ogr_f_unsetfield(feature.ptr, i); feature) +function unsetfield!(feature::Feature, i::Integer)::Feature + GDAL.ogr_f_unsetfield(feature.ptr, i) + return feature +end # """ # OGR_F_GetRawFieldRef(OGRFeatureH hFeat, @@ -163,7 +169,7 @@ Fetch field value as integer. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asint(feature::Feature, i::Integer) = +asint(feature::Feature, i::Integer)::Int32 = GDAL.ogr_f_getfieldasinteger(feature.ptr, i) """ @@ -175,7 +181,7 @@ Fetch field value as integer 64 bit. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asint64(feature::Feature, i::Integer) = +asint64(feature::Feature, i::Integer)::Int64 = GDAL.ogr_f_getfieldasinteger64(feature.ptr, i) """ @@ -187,7 +193,7 @@ Fetch field value as a double. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asdouble(feature::Feature, i::Integer) = +asdouble(feature::Feature, i::Integer)::Float64 = GDAL.ogr_f_getfieldasdouble(feature.ptr, i) """ @@ -199,7 +205,7 @@ Fetch field value as a string. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asstring(feature::Feature, i::Integer) = +asstring(feature::Feature, i::Integer)::String = GDAL.ogr_f_getfieldasstring(feature.ptr, i) """ @@ -217,7 +223,7 @@ the field value. This list is internal, and should not be modified, or freed. Its lifetime may be very brief. If *pnCount is zero on return the returned pointer may be NULL or non-NULL. """ -function asintlist(feature::Feature, i::Integer) +function asintlist(feature::Feature, i::Integer)::Vector{Int32} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasintegerlist(feature.ptr, i, n) return (n.x == 0) ? Int32[] : unsafe_wrap(Array{Int32}, ptr, n.x) @@ -238,7 +244,7 @@ the field value. This list is internal, and should not be modified, or freed. Its lifetime may be very brief. If *pnCount is zero on return the returned pointer may be NULL or non-NULL. """ -function asint64list(feature::Feature, i::Integer) +function asint64list(feature::Feature, i::Integer)::Vector{Int64} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasinteger64list(feature.ptr, i, n) return (n.x == 0) ? Int64[] : unsafe_wrap(Array{Int64}, ptr, n.x) @@ -259,7 +265,7 @@ the field value. This list is internal, and should not be modified, or freed. Its lifetime may be very brief. If *pnCount is zero on return the returned pointer may be NULL or non-NULL. """ -function asdoublelist(feature::Feature, i::Integer) +function asdoublelist(feature::Feature, i::Integer)::Vector{Float64} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasdoublelist(feature.ptr, i, n) return (n.x == 0) ? Float64[] : unsafe_wrap(Array{Float64}, ptr, n.x) @@ -278,7 +284,7 @@ Fetch field value as a list of strings. the field value. This list is internal, and should not be modified, or freed. Its lifetime may be very brief. """ -asstringlist(feature::Feature, i::Integer) = +asstringlist(feature::Feature, i::Integer)::Vector{String} = GDAL.ogr_f_getfieldasstringlist(feature.ptr, i) """ @@ -294,10 +300,10 @@ Fetch field value as binary. the field value. This list is internal, and should not be modified, or freed. Its lifetime may be very brief. """ -function asbinary(feature::Feature, i::Integer) +function asbinary(feature::Feature, i::Integer)::Vector{UInt8} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasbinary(feature.ptr, i, n) - return (n.x == 0) ? UInt8[] : unsafe_wrap(Array{UInt8}, ptr, n.x) + return (n.x == 0) ? UInt8[] : unsafe_wrap(Vector{UInt8}, ptr, n.x) end """ @@ -313,7 +319,7 @@ OFTDate, OFTTime and OFTDateTime fields. ### Returns `true` on success or `false` on failure. """ -function asdatetime(feature::Feature, i::Integer) +function asdatetime(feature::Feature, i::Integer)::DateTime pyr = Ref{Cint}(); pmth = Ref{Cint}(); pday = Ref{Cint}() phr = Ref{Cint}(); pmin = Ref{Cint}(); psec = Ref{Cint}(); ptz=Ref{Cint}() result = Bool(GDAL.ogr_f_getfieldasdatetime(feature.ptr, i, pyr, pmth, pday, @@ -354,7 +360,9 @@ end # pfSecond,pnTZFlag) # end -getdefault(feature::Feature, i::Integer) = getdefault(getfielddefn(feature, i)) +function getdefault(feature::Feature, i::Integer)::String + return getdefault(getfielddefn(feature, i)) +end const _FETCHFIELD = Dict{OGRFieldType, Function}( OFTInteger => asint, #0 @@ -409,37 +417,41 @@ field types may be unaffected. """ function setfield! end -function setfield!(feature::Feature, i::Integer, value::Int32) +function setfield!(feature::Feature, i::Integer, value::Int32)::Feature GDAL.ogr_f_setfieldinteger(feature.ptr, i, value) return feature end -function setfield!(feature::Feature, i::Integer, value::Int64) +function setfield!(feature::Feature, i::Integer, value::Int64)::Feature GDAL.ogr_f_setfieldinteger64(feature.ptr, i, value) return feature end -function setfield!(feature::Feature, i::Integer, value::Float64) +function setfield!(feature::Feature, i::Integer, value::Float64)::Feature GDAL.ogr_f_setfielddouble(feature.ptr, i, value) return feature end -function setfield!(feature::Feature, i::Integer, value::AbstractString) +function setfield!(feature::Feature, i::Integer, value::AbstractString)::Feature GDAL.ogr_f_setfieldstring(feature.ptr, i, value) return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{Int32}) +function setfield!(feature::Feature, i::Integer, value::Vector{Int32})::Feature GDAL.ogr_f_setfieldintegerlist(feature.ptr, i, length(value), value) return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{Int64}) +function setfield!(feature::Feature, i::Integer, value::Vector{Int64})::Feature GDAL.ogr_f_setfieldinteger64list(feature.ptr, i, length(value), value) return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{Float64}) +function setfield!( + feature::Feature, + i::Integer, + value::Vector{Float64} + )::Feature GDAL.ogr_f_setfielddoublelist(feature.ptr, i, length(value), value) return feature end @@ -448,7 +460,7 @@ function setfield!( feature::Feature, i::Integer, value::Vector{T} - ) where T <: AbstractString + )::Feature where T <: AbstractString GDAL.ogr_f_setfieldstringlist(feature.ptr, i, value) return feature end @@ -468,12 +480,17 @@ end # Ptr{OGRField}),arg1,arg2,arg3) # end -function setfield!(feature::Feature, i::Integer, value::Vector{UInt8}) +function setfield!(feature::Feature, i::Integer, value::Vector{UInt8})::Feature GDAL.ogr_f_setfieldbinary(feature.ptr, i, sizeof(value), value) return feature end -function setfield!(feature::Feature, i::Integer, dt::DateTime, tzflag::Int = 0) +function setfield!( + feature::Feature, + i::Integer, + dt::DateTime, + tzflag::Int = 0 + )::Feature GDAL.ogr_f_setfielddatetime( feature.ptr, i, @@ -495,7 +512,7 @@ Fetch number of geometry fields on this feature. This will always be the same as the geometry field count for OGRFeatureDefn. """ -ngeom(feature::Feature) = GDAL.ogr_f_getgeomfieldcount(feature.ptr) +ngeom(feature::Feature)::Integer = GDAL.ogr_f_getgeomfieldcount(feature.ptr) """ getgeomdefn(feature::Feature, i::Integer) @@ -510,8 +527,9 @@ Fetch definition for this geometry field. The field definition (from the OGRFeatureDefn). This is an internal reference, and should not be deleted or modified. """ -getgeomdefn(feature::Feature, i::Integer) = - IGeomFieldDefnView(GDAL.ogr_f_getgeomfielddefnref(feature.ptr, i)) +function getgeomdefn(feature::Feature, i::Integer)::IGeomFieldDefnView + return IGeomFieldDefnView(GDAL.ogr_f_getgeomfielddefnref(feature.ptr, i)) +end """ findgeomindex(feature::Feature, name::AbstractString="") @@ -528,7 +546,7 @@ the geometry field index, or -1 if no matching geometry field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetGeomFieldIndex()` method. """ -findgeomindex(feature::Feature, name::AbstractString="") = +findgeomindex(feature::Feature, name::AbstractString = "")::Integer = GDAL.ogr_f_getgeomfieldindex(feature.ptr, name) """ @@ -540,7 +558,7 @@ Returns a clone of the feature geometry at index `i`. * `feature`: the feature to get geometry from. * `i`: geometry field to get. """ -function getgeom(feature::Feature, i::Integer) +function getgeom(feature::Feature, i::Integer)::IGeometry result = GDAL.ogr_f_getgeomfieldref(feature.ptr, i) return if result == C_NULL IGeometry() @@ -549,7 +567,7 @@ function getgeom(feature::Feature, i::Integer) end end -function unsafe_getgeom(feature::Feature, i::Integer) +function unsafe_getgeom(feature::Feature, i::Integer)::Geometry result = GDAL.ogr_f_getgeomfieldref(feature.ptr, i) return if result == C_NULL Geometry() @@ -576,7 +594,7 @@ the passed geometry, but instead makes a copy of it. `OGRERR_NONE` if successful, or `OGR_UNSUPPORTED_GEOMETRY_TYPE` if the geometry type is illegal for the `OGRFeatureDefn` (checking not yet implemented). """ -function setgeom!(feature::Feature, i::Integer, geom::AbstractGeometry) +function setgeom!(feature::Feature, i::Integer, geom::AbstractGeometry)::Feature result = GDAL.ogr_f_setgeomfield(feature.ptr, i, geom.ptr) @ogrerr result "OGRErr $result: Failed to set feature geometry" return feature @@ -590,7 +608,7 @@ Get feature identifier. ### Returns feature id or `OGRNullFID` (`-1`) if none has been assigned. """ -getfid(feature::Feature) = GDAL.ogr_f_getfid(feature.ptr) +getfid(feature::Feature) = GDAL.ogr_f_getfid(feature.ptr)::Integer """ setfid!(feature::Feature, i::Integer) @@ -604,7 +622,7 @@ Set the feature identifier. ### Returns On success OGRERR_NONE, or on failure some other value. """ -function setfid!(feature::Feature, i::Integer) +function setfid!(feature::Feature, i::Integer)::Feature result = GDAL.ogr_f_setfid(feature.ptr, i) @ogrerr result "OGRErr $result: Failed to set FID $i" return feature @@ -634,7 +652,11 @@ otherwise an error code. """ function setfrom! end -function setfrom!(feature1::Feature, feature2::Feature, forgiving::Bool = false) +function setfrom!( + feature1::Feature, + feature2::Feature, + forgiving::Bool = false + )::Feature result = GDAL.ogr_f_setfrom(feature1.ptr, feature2.ptr, forgiving) @ogrerr result "OGRErr $result: Failed to set feature" return feature1 @@ -645,7 +667,7 @@ function setfrom!( feature2::Feature, indices::Vector{Cint}, forgiving::Bool = false - ) + )::Feature result = GDAL.ogr_f_setfromwithmap(feature1.ptr, feature2.ptr, forgiving, indices) @ogrerr result "OGRErr $result: Failed to set feature with map" @@ -658,7 +680,8 @@ end Fetch style string for this feature. """ -getstylestring(feature::Feature) = GDAL.ogr_f_getstylestring(feature.ptr) +getstylestring(feature::Feature)::String = + GDAL.ogr_f_getstylestring(feature.ptr) """ setstylestring!(feature::Feature, style::AbstractString) @@ -668,7 +691,7 @@ Set feature style string. This method operate exactly as `setstylestringdirectly!()` except that it doesn't assume ownership of the passed string, but makes a copy of it. """ -function setstylestring!(feature::Feature, style::AbstractString) +function setstylestring!(feature::Feature, style::AbstractString)::Feature GDAL.ogr_f_setstylestring(feature.ptr, style) return feature end @@ -678,7 +701,7 @@ end Fetch style table for this feature. """ -getstyletable(feature::Feature) = +getstyletable(feature::Feature)::StyleTable = StyleTable(GDAL.ogr_f_getstyletable(feature.ptr)) """ @@ -686,7 +709,7 @@ getstyletable(feature::Feature) = Set the style table for this feature. """ -function setstyletable!(feature::Feature, styletable::StyleTable) +function setstyletable!(feature::Feature, styletable::StyleTable)::Feature GDAL.ogr_f_setstyletable(feature.ptr, styletable.ptr) return feature end @@ -710,7 +733,7 @@ than what can be obtained with the rest of the API, but it may be useful in round-tripping scenarios where some characteristics of the underlying format are not captured otherwise by the OGR abstraction. """ -getnativedata(feature::Feature) = GDAL.ogr_f_getnativedata(feature.ptr) +getnativedata(feature::Feature)::String = GDAL.ogr_f_getnativedata(feature.ptr) """ setnativedata!(feature::Feature, data::AbstractString) @@ -722,7 +745,7 @@ driver that created this feature, or that is aimed at an output driver. The native data may be in different format, which is indicated by GetNativeMediaType(). """ -function setnativedata!(feature::Feature, data::AbstractString) +function setnativedata!(feature::Feature, data::AbstractString)::Feature GDAL.ogr_f_setnativedata(feature.ptr, data) return feature end @@ -736,7 +759,8 @@ The native media type is the identifier for the format of the native data. It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type), e.g. \"application/vnd.geo+json\" for JSON. """ -getmediatype(feature::Feature) = GDAL.ogr_f_getnativemediatype(feature.ptr) +getmediatype(feature::Feature)::String = + GDAL.ogr_f_getnativemediatype(feature.ptr) """ setmediatype!(feature::Feature, mediatype::AbstractString) @@ -747,7 +771,7 @@ The native media type is the identifier for the format of the native data. It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type), e.g. \"application/vnd.geo+json\" for JSON. """ -function setmediatype!(feature::Feature, mediatype::AbstractString) +function setmediatype!(feature::Feature, mediatype::AbstractString)::Feature GDAL.ogr_f_setnativemediatype(feature.ptr, mediatype) return feature end @@ -765,10 +789,11 @@ Fill unset fields with default values that might be defined. """ function fillunsetwithdefault!( feature::Feature; - notnull::Bool = true, - options = StringList(C_NULL) - ) - return GDAL.ogr_f_fillunsetwithdefault(feature.ptr, notnull, options) + notnull::Bool = true, + options = StringList(C_NULL) + )::Feature + GDAL.ogr_f_fillunsetwithdefault(feature.ptr, notnull, options) + return feature end """ @@ -793,5 +818,5 @@ fails, then it will fail for all interpretations). ### Returns `true` if all enabled validation tests pass. """ -validate(feature::Feature, flags::Integer, emiterror::Bool) = +validate(feature::Feature, flags::Integer, emiterror::Bool)::Bool = Bool(GDAL.ogr_f_validate(feature.ptr, flags, emiterror)) diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index 6221939c..da51c57e 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -6,7 +6,7 @@ Create a new feature definition object to hold field definitions. The `FeatureDefn` maintains a reference count, but this starts at zero, and should normally be incremented by the owner. """ -unsafe_createfeaturedefn(name::AbstractString) = +unsafe_createfeaturedefn(name::AbstractString)::FeatureDefn = FeatureDefn(GDAL.ogr_fd_create(name)) """ @@ -19,34 +19,36 @@ The count is used to track the number of `Feature`s referencing this definition. ### Returns The updated reference count. """ -reference(featuredefn::FeatureDefn) = GDAL.ogr_fd_reference(featuredefn.ptr) +reference(featuredefn::FeatureDefn)::Integer = + GDAL.ogr_fd_reference(featuredefn.ptr) """ dereference(featuredefn::FeatureDefn) Decrements the reference count by one, and returns the updated count. """ -dereference(featuredefn::FeatureDefn) = GDAL.ogr_fd_dereference(featuredefn.ptr) +dereference(featuredefn::FeatureDefn)::Integer = + GDAL.ogr_fd_dereference(featuredefn.ptr) """ nreference(featuredefn::AbstractFeatureDefn) Fetch the current reference count. """ -nreference(featuredefn::AbstractFeatureDefn) = +nreference(featuredefn::AbstractFeatureDefn)::Integer = GDAL.ogr_fd_getreferencecount(featuredefn.ptr) "Destroy a feature definition object and release all memory associated with it" -function destroy(featuredefn::FeatureDefn) +function destroy(featuredefn::FeatureDefn)::Nothing GDAL.ogr_fd_destroy(featuredefn.ptr) featuredefn.ptr = C_NULL - return featuredefn + return nothing end "Destroy a feature definition view" -function destroy(featuredefn::IFeatureDefnView) +function destroy(featuredefn::IFeatureDefnView)::Nothing featuredefn.ptr = C_NULL - return featuredefn + return nothing end """ @@ -54,21 +56,24 @@ end Drop a reference, and destroy if unreferenced. """ -release(featuredefn::FeatureDefn) = GDAL.ogr_fd_release(featuredefn.ptr) +function release(featuredefn::FeatureDefn)::Nothing + GDAL.ogr_fd_release(featuredefn.ptr) + return nothing +end """ getname(featuredefn::AbstractFeatureDefn) Get name of the OGRFeatureDefn passed as an argument. """ -getname(featuredefn::AbstractFeatureDefn) = GDAL.ogr_fd_getname(featuredefn.ptr) +getname(featuredefn::AbstractFeatureDefn)::String = GDAL.ogr_fd_getname(featuredefn.ptr) """ nfield(featuredefn::AbstractFeatureDefn) Fetch number of fields on the passed feature definition. """ -nfield(featuredefn::AbstractFeatureDefn) = +nfield(featuredefn::AbstractFeatureDefn)::Integer = GDAL.ogr_fd_getfieldcount(featuredefn.ptr) """ @@ -84,10 +89,10 @@ Fetch field definition of the passed feature definition. an handle to an internal field definition object or NULL if invalid index. This object should not be modified or freed by the application. """ -getfielddefn(featuredefn::FeatureDefn, i::Integer) = +getfielddefn(featuredefn::FeatureDefn, i::Integer)::FieldDefn = FieldDefn(GDAL.ogr_fd_getfielddefn(featuredefn.ptr, i)) -getfielddefn(featuredefn::IFeatureDefnView, i::Integer) = +getfielddefn(featuredefn::IFeatureDefnView, i::Integer)::IFieldDefnView = IFieldDefnView(GDAL.ogr_fd_getfielddefn(featuredefn.ptr, i)) """ @@ -105,7 +110,7 @@ This uses the OGRFeatureDefn::GetFieldIndex() method. function findfieldindex( featuredefn::AbstractFeatureDefn, name::Union{AbstractString, Symbol} - ) + )::Integer return GDAL.ogr_fd_getfieldindex(featuredefn.ptr, name) end @@ -121,7 +126,10 @@ This function should only be called while there are no OGRFeature objects in existence based on this OGRFeatureDefn. The OGRFieldDefn passed in is copied, and remains the responsibility of the caller. """ -function addfielddefn!(featuredefn::FeatureDefn, fielddefn::FieldDefn) +function addfielddefn!( + featuredefn::FeatureDefn, + fielddefn::FieldDefn + )::FeatureDefn GDAL.ogr_fd_addfielddefn(featuredefn.ptr, fielddefn.ptr) return featuredefn end @@ -137,7 +145,7 @@ function directly, but use `OGR_L_DeleteField()` instead. This method should only be called while there are no OGRFeature objects in existence based on this OGRFeatureDefn. """ -function deletefielddefn!(featuredefn::FeatureDefn, i::Integer) +function deletefielddefn!(featuredefn::FeatureDefn, i::Integer)::FeatureDefn result = GDAL.ogr_fd_deletefielddefn(featuredefn.ptr, i) @ogrerr result "Failed to delete field $i in the feature definition" return featuredefn @@ -161,7 +169,10 @@ existence based on this OGRFeatureDefn. at position `i` after reordering, its position before reordering was `indices[i]`. """ -function reorderfielddefns!(featuredefn::FeatureDefn, indices::Vector{Cint}) +function reorderfielddefns!( + featuredefn::FeatureDefn, + indices::Vector{Cint} + )::FeatureDefn result = GDAL.ogr_fd_reorderfielddefns(featuredefn.ptr, indices) @ogrerr result "Failed to reorder $indices in the feature definition" return featuredefn @@ -196,7 +207,10 @@ type. The default upon creation is `wkbUnknown` which allows for any geometry type. The geometry type should generally not be changed after any OGRFeatures have been created against this definition. """ -function setgeomtype!(featuredefn::FeatureDefn, etype::WKBGeometryType) +function setgeomtype!( + featuredefn::FeatureDefn, + etype::WKBGeometryType + )::FeatureDefn GDAL.ogr_fd_setgeomtype(featuredefn.ptr, etype) return featuredefn end @@ -206,7 +220,7 @@ end Determine whether the geometry can be omitted when fetching features. """ -isgeomignored(featuredefn::AbstractFeatureDefn) = +isgeomignored(featuredefn::AbstractFeatureDefn)::Bool = Bool(GDAL.ogr_fd_isgeometryignored(featuredefn.ptr)) """ @@ -214,7 +228,7 @@ isgeomignored(featuredefn::AbstractFeatureDefn) = Set whether the geometry can be omitted when fetching features. """ -function setgeomignored!(featuredefn::FeatureDefn, ignore::Bool) +function setgeomignored!(featuredefn::FeatureDefn, ignore::Bool)::FeatureDefn GDAL.ogr_fd_setgeometryignored(featuredefn.ptr, ignore) return featuredefn end @@ -224,7 +238,7 @@ end Determine whether the style can be omitted when fetching features. """ -isstyleignored(featuredefn::AbstractFeatureDefn) = +isstyleignored(featuredefn::AbstractFeatureDefn)::Bool = Bool(GDAL.ogr_fd_isstyleignored(featuredefn.ptr)) """ @@ -232,7 +246,7 @@ isstyleignored(featuredefn::AbstractFeatureDefn) = Set whether the style can be omitted when fetching features. """ -function setstyleignored!(featuredefn::FeatureDefn, ignore::Bool) +function setstyleignored!(featuredefn::FeatureDefn, ignore::Bool)::FeatureDefn GDAL.ogr_fd_setstyleignored(featuredefn.ptr, ignore) return featuredefn end @@ -242,7 +256,7 @@ end Fetch number of geometry fields on the passed feature definition. """ -ngeom(featuredefn::AbstractFeatureDefn) = +ngeom(featuredefn::AbstractFeatureDefn)::Integer = GDAL.ogr_fd_getgeomfieldcount(featuredefn.ptr) """ @@ -257,10 +271,10 @@ Fetch geometry field definition of the passed feature definition. an internal field definition object or `NULL` if invalid index. This object should not be modified or freed by the application. """ -getgeomdefn(featuredefn::FeatureDefn, i::Integer = 0) = +getgeomdefn(featuredefn::FeatureDefn, i::Integer = 0)::GeomFieldDefn = GeomFieldDefn(GDAL.ogr_fd_getgeomfielddefn(featuredefn.ptr, i)) -getgeomdefn(featuredefn::IFeatureDefnView, i::Integer = 0) = +getgeomdefn(featuredefn::IFeatureDefnView, i::Integer = 0)::IGeomFieldDefnView = IGeomFieldDefnView(GDAL.ogr_fd_getgeomfielddefn(featuredefn.ptr, i)) """ @@ -274,8 +288,12 @@ name (case insensitively) is returned. ### Returns the geometry field index, or -1 if no match found. """ -findgeomindex(featuredefn::AbstractFeatureDefn, name::AbstractString = "") = - GDAL.ogr_fd_getgeomfieldindex(featuredefn.ptr, name) +function findgeomindex( + featuredefn::AbstractFeatureDefn, + name::AbstractString = "" + )::Integer + return GDAL.ogr_fd_getgeomfieldindex(featuredefn.ptr, name) +end """ addgeomdefn!(featuredefn::FeatureDefn, geomfielddefn::AbstractGeomFieldDefn) @@ -295,7 +313,7 @@ existence based on this OGRFeatureDefn. function addgeomdefn!( featuredefn::FeatureDefn, geomfielddefn::AbstractGeomFieldDefn - ) + )::FeatureDefn # `geomfielddefn` is copied, and remains the responsibility of the caller. GDAL.ogr_fd_addgeomfielddefn(featuredefn.ptr, geomfielddefn.ptr) return featuredefn @@ -312,7 +330,7 @@ function directly, but use OGRLayer::DeleteGeomField() instead. This method should only be called while there are no OGRFeature objects in existence based on this OGRFeatureDefn. """ -function deletegeomdefn!(featuredefn::FeatureDefn, i::Integer) +function deletegeomdefn!(featuredefn::FeatureDefn, i::Integer)::FeatureDefn result = GDAL.ogr_fd_deletegeomfielddefn(featuredefn.ptr, i) @ogrerr result "Failed to delete geom field $i in the feature definition" return featuredefn @@ -326,7 +344,7 @@ Test if the feature definition is identical to the other one. function issame( featuredefn1::AbstractFeatureDefn, featuredefn2::AbstractFeatureDefn - ) + )::Bool return Bool(GDAL.ogr_fd_issame(featuredefn1.ptr, featuredefn2.ptr)) end @@ -341,7 +359,7 @@ OGRFeatures that depend on it is likely to result in a crash. Starting with GDAL 2.1, returns NULL in case out of memory situation. """ -function unsafe_createfeature(featuredefn::AbstractFeatureDefn) +function unsafe_createfeature(featuredefn::AbstractFeatureDefn)::Feature return Feature(GDALFeature(GDAL.ogr_f_create(featuredefn.ptr))) end @@ -350,5 +368,5 @@ end Fetch feature definition. """ -getfeaturedefn(feature::Feature) = +getfeaturedefn(feature::Feature)::IFeatureDefnView = IFeatureDefnView(GDAL.ogr_f_getdefnref(feature.ptr)) diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index 650e8d57..bbe1628a 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -1,14 +1,14 @@ -function destroy(layer::AbstractFeatureLayer) +function destroy(layer::AbstractFeatureLayer)::Nothing layer.ptr = GDALFeatureLayer(C_NULL) - return layer + return nothing end -function destroy(layer::IFeatureLayer) +function destroy(layer::IFeatureLayer)::Nothing layer.ptr = GDALFeatureLayer(C_NULL) layer.ownedby = Dataset() layer.spatialref = SpatialRef() - return layer + return nothing end """ @@ -32,7 +32,7 @@ function createlayer(; geom::WKBGeometryType = wkbUnknown, spatialref::AbstractSpatialRef = SpatialRef(), options = StringList(C_NULL) - ) + )::IFeatureLayer return IFeatureLayer( GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, options), @@ -47,7 +47,7 @@ function unsafe_createlayer(; geom::WKBGeometryType = wkbUnknown, spatialref::AbstractSpatialRef = SpatialRef(), options = StringList(C_NULL) - ) + )::FeatureLayer return FeatureLayer(GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, options)) end @@ -73,7 +73,7 @@ function copy( dataset::AbstractDataset = create(getdriver("Memory")), name::AbstractString = "copy($(getname(layer)))", options = StringList(C_NULL) - ) + )::IFeatureLayer return IFeatureLayer( GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options), ownedby = dataset @@ -85,7 +85,7 @@ function unsafe_copy( dataset::AbstractDataset = create(getdriver("Memory")), name::AbstractString = "copy($(getname(layer)))", options = StringList(C_NULL) - ) + )::FeatureLayer return FeatureLayer(GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options)) end @@ -95,14 +95,14 @@ end Return the layer name. """ -getname(layer::AbstractFeatureLayer) = GDAL.ogr_l_getname(layer.ptr) +getname(layer::AbstractFeatureLayer)::String = GDAL.ogr_l_getname(layer.ptr) """ getgeomtype(layer::AbstractFeatureLayer) Return the layer geometry type. """ -getgeomtype(layer::AbstractFeatureLayer) = +getgeomtype(layer::AbstractFeatureLayer)::WKBGeometryType = gdaltype(GDAL.ogr_l_getgeomtype(layer.ptr)) """ @@ -110,7 +110,7 @@ getgeomtype(layer::AbstractFeatureLayer) = Returns the current spatial filter for this layer. """ -function getspatialfilter(layer::AbstractFeatureLayer) +function getspatialfilter(layer::AbstractFeatureLayer)::IGeometry result = GDALGeometry(GDAL.ogr_l_getspatialfilter(Ptr{Cvoid}(layer.ptr))) return if result == C_NULL IGeometry(result) @@ -126,7 +126,7 @@ end Returns a clone of the spatial reference system for this layer. """ -function getspatialref(layer::AbstractFeatureLayer) +function getspatialref(layer::AbstractFeatureLayer)::ISpatialRef result = GDAL.ogr_l_getspatialref(layer.ptr) return if result == C_NULL ISpatialRef() @@ -137,7 +137,7 @@ function getspatialref(layer::AbstractFeatureLayer) end end -function unsafe_getspatialref(layer::AbstractFeatureLayer) +function unsafe_getspatialref(layer::AbstractFeatureLayer)::SpatialRef result = GDAL.ogr_l_getspatialref(layer.ptr) return if result == C_NULL SpatialRef() @@ -177,14 +177,19 @@ In the future this may be generalized. Note that only the last spatial filter set is applied, even if several successive calls are done with different iGeomField values. """ -function setspatialfilter!(layer::AbstractFeatureLayer, geom::Geometry) +function setspatialfilter!( + layer::L, + geom::Geometry + )::L where {L <: AbstractFeatureLayer} # This method makes an internal copy of `geom`. The input `geom` remains # the responsibility of the caller, and may be safely destroyed. GDAL.ogr_l_setspatialfilter(layer.ptr, geom.ptr) return layer end -function clearspatialfilter!(layer::AbstractFeatureLayer) +function clearspatialfilter!( + layer::L + )::L where {L <: AbstractFeatureLayer} GDAL.ogr_l_setspatialfilter(layer.ptr, GDALGeometry(C_NULL)) return layer end @@ -207,12 +212,12 @@ The only way to clear a spatial filter set with this method is to call `OGRLayer::SetSpatialFilter(NULL)`. """ function setspatialfilter!( - layer::AbstractFeatureLayer, + layer::L, xmin::Real, ymin::Real, xmax::Real, ymax::Real - ) + )::L where {L <: AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterrect(layer.ptr, xmin, ymin, xmax, ymax) return layer end @@ -245,17 +250,20 @@ layer (as returned by OGRLayer::GetSpatialRef()). In the future this may be generalized. """ function setspatialfilter!( - layer::AbstractFeatureLayer, + layer::L, i::Integer, geom::AbstractGeometry - ) + )::L where {L <: AbstractFeatureLayer} # This method makes an internal copy of `geom`. The input `geom` remains # the responsibility of the caller, and may be safely destroyed. GDAL.ogr_l_setspatialfilterex(layer.ptr, i, geom.ptr) return layer end -function clearspatialfilter!(layer::AbstractFeatureLayer, i::Integer) +function clearspatialfilter!( + layer::L, + i::Integer + )::L where {L <: AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterex(layer.ptr, i, GDALGeometry(C_NULL)) return layer end @@ -275,13 +283,13 @@ Set a new rectangular spatial filter. * `ymax`: the maximum Y coordinate for the rectangular region. """ function setspatialfilter!( - layer::AbstractFeatureLayer, + layer::L, i::Integer, xmin::Real, ymin::Real, xmax::Real, ymax::Real - ) + )::L where {L <: AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterrectex(layer.ptr, i, xmin, ymin, xmax, ymax) return layer end @@ -311,14 +319,17 @@ broader than those of OGR SQL. Note that installing a query string will generally result in resetting the current reading position (ala `resetreading!()`). """ -function setattributefilter!(layer::AbstractFeatureLayer, query::AbstractString) +function setattributefilter!( + layer::L, + query::AbstractString + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_setattributefilter(layer.ptr, query) @ogrerr result """Failed to set a new attribute query. The query expression might be in error.""" return layer end -function clearattributefilter!(layer::AbstractFeatureLayer) +function clearattributefilter!(layer::L)::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_setattributefilter(layer.ptr, C_NULL) @ogrerr result "OGRErr $result: Failed to clear attribute query." return layer @@ -331,7 +342,7 @@ Reset feature reading to start on the first feature. This affects `nextfeature()`. """ -function resetreading!(layer::AbstractFeatureLayer) +function resetreading!(layer::L)::L where {L <: AbstractFeatureLayer} GDAL.ogr_l_resetreading(layer.ptr) return layer end @@ -363,7 +374,7 @@ on drivers. If a transaction is committed/aborted, the current sequential reading may or may not be valid after that operation and a call to `resetreading!()` might be needed. """ -function unsafe_nextfeature(layer::AbstractFeatureLayer) +function unsafe_nextfeature(layer::AbstractFeatureLayer)::Feature return Feature(GDALFeature(GDAL.ogr_l_getnextfeature(layer.ptr))) end @@ -390,7 +401,10 @@ then calls `nextfeature()` `i` times is used. To determine if fast seeking is available on the layer, use the `testcapability()` method with a value of `OLCFastSetNextByIndex`. """ -function setnextbyindex!(layer::AbstractFeatureLayer, i::Integer) +function setnextbyindex!( + layer::L, + i::Integer + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_setnextbyindex(layer.ptr, i) @ogrerr result "Failed to move the cursor to index $i" return layer @@ -425,7 +439,7 @@ interrupted by a OGR_L_GetFeature() call. The returned feature is now owned by the caller, and should be freed with `destroy()`. """ -unsafe_getfeature(layer::AbstractFeatureLayer, i::Integer) = +unsafe_getfeature(layer::AbstractFeatureLayer, i::Integer)::Feature = Feature(GDALFeature(GDAL.ogr_l_getfeature(layer.ptr, i))) """ @@ -460,13 +474,16 @@ OGRNullFID, then the native implementation may use that as the feature id of the new feature, but not necessarily. Upon successful return the passed feature will have been updated with the new feature id. """ -function addfeature!(layer::AbstractFeatureLayer, feature::Feature) +function addfeature!( + layer::L, + feature::Feature + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_createfeature(layer.ptr, feature.ptr) @ogrerr result "Failed to create and write feature in layer." return layer end -function addfeature(f::Function, layer::AbstractFeatureLayer) +function addfeature(f::Function, layer::L)::L where {L <: AbstractFeatureLayer} feature = unsafe_createfeature(layer) return try f(feature) @@ -484,10 +501,13 @@ Create and returns a new feature based on the layer definition. The newly feature is owned by the layer (it will increase the number of features the layer by one), but the feature has not been written to the layer yet. """ -unsafe_createfeature(layer::AbstractFeatureLayer) = +unsafe_createfeature(layer::AbstractFeatureLayer)::Feature = unsafe_createfeature(layerdefn(layer)) -function createfeature(f::Function, layer::AbstractFeatureLayer) +function createfeature( + f::Function, + layer::L + )::L where {L <: AbstractFeatureLayer} feature = unsafe_createfeature(layer) return try f(feature) @@ -508,7 +528,10 @@ by the driver. Most drivers do not support feature deletion, and will return OGRERR_UNSUPPORTED_OPERATION. The OGR_L_TestCapability() function may be called with OLCDeleteFeature to check if the driver supports feature deletion. """ -function deletefeature!(layer::AbstractFeatureLayer, i::Integer) +function deletefeature!( + layer::L, + i::Integer + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_deletefeature(layer.ptr, i) # OGRERR_NONE if the operation works, otherwise an appropriate error code # (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist). @@ -524,7 +547,7 @@ Returns a view of the schema information for this layer. ### Remarks The `featuredefn` is owned by the `layer` and should not be modified. """ -layerdefn(layer::AbstractFeatureLayer) = +layerdefn(layer::AbstractFeatureLayer)::IFeatureDefnView = IFeatureDefnView(GDAL.ogr_l_getlayerdefn(layer.ptr)) """ @@ -541,7 +564,7 @@ function findfieldindex( layer::AbstractFeatureLayer, field::Union{AbstractString, Symbol}, exactmatch::Bool - ) + )::Integer return GDAL.ogr_l_findfieldindex(layer.ptr, field, exactmatch) end @@ -555,7 +578,7 @@ Fetch the feature count in this layer, or `-1` if the count is not known. * `force`: flag indicating whether the count should be computed even if it is expensive. (`false` by default.) """ -nfeature(layer::AbstractFeatureLayer, force::Bool = false) = +nfeature(layer::AbstractFeatureLayer, force::Bool = false)::Integer = GDAL.ogr_l_getfeaturecount(layer.ptr, force) """ @@ -563,14 +586,14 @@ nfeature(layer::AbstractFeatureLayer, force::Bool = false) = Fetch number of geometry fields on the feature layer. """ -ngeom(layer::AbstractFeatureLayer) = ngeom(layerdefn(layer)) +ngeom(layer::AbstractFeatureLayer)::Integer = ngeom(layerdefn(layer)) """ nfield(layer::AbstractFeatureLayer) Fetch number of fields on the feature layer. """ -nfield(layer::AbstractFeatureLayer) = nfield(layerdefn(layer)) +nfield(layer::AbstractFeatureLayer)::Integer = nfield(layerdefn(layer)) """ envelope(layer::AbstractFeatureLayer, force::Bool = false) @@ -601,14 +624,21 @@ meaningful extents could be collected. Note that some implementations of this method may alter the read cursor of the layer. """ -function envelope(layer::AbstractFeatureLayer, i::Integer, force::Bool = false) +function envelope( + layer::AbstractFeatureLayer, + i::Integer, + force::Bool = false + )::GDAL.OGREnvelope envelope = Ref{GDAL.OGREnvelope}(GDAL.OGREnvelope(0, 0, 0, 0)) result = GDAL.ogr_l_getextentex(layer.ptr, i, envelope, force) @ogrerr result "Extent not known" return envelope[] end -function envelope(layer::AbstractFeatureLayer, force::Bool = false) +function envelope( + layer::AbstractFeatureLayer, + force::Bool = false + )::GDAL.OGREnvelope envelope = Ref{GDAL.OGREnvelope}(GDAL.OGREnvelope(0, 0, 0, 0)) result = GDAL.ogr_l_getextent(layer.ptr, envelope, force) @ogrerr result "Extent not known" @@ -702,7 +732,7 @@ the caller. * `OLCCurveGeometries` / \"CurveGeometries\": `true` if this layer supports writing curve geometries or may return such geometries. (GDAL 2.0). """ -testcapability(layer::AbstractFeatureLayer, capability::AbstractString) = +testcapability(layer::AbstractFeatureLayer, capability::AbstractString)::Bool = Bool(GDAL.ogr_l_testcapability(layer.ptr, capability)) function listcapability( @@ -725,7 +755,7 @@ function listcapability( GDAL.OLCCreateGeomField, GDAL.OLCCurveGeometries, GDAL.OLCMeasuredGeometries) - ) + )::Dict{String, Bool} return Dict{String, Bool}([ c => testcapability(layer,c) for c in capabilities ]) @@ -774,10 +804,10 @@ fields with not-null constraints, this is generally before creating any feature to the layer. """ function addfielddefn!( - layer::AbstractFeatureLayer, + layer::L, field::AbstractFieldDefn, approx::Bool = false - ) + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_createfield(layer.ptr, field.ptr, approx) @ogrerr result "Failed to create new field" return layer @@ -814,10 +844,10 @@ fields with not-null constraints, this is generally before creating any feature to the layer. """ function addgeomdefn!( - layer::AbstractFeatureLayer, + layer::L, field::AbstractGeomFieldDefn, approx::Bool = false - ) + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_creategeomfield(layer.ptr, field.ptr, approx) # OGRERR_NONE on success. @ogrerr result "Failed to create new geometry field" @@ -1003,7 +1033,8 @@ Increment layer reference count. ### Returns The reference count after incrementing. """ -reference(layer::AbstractFeatureLayer) = GDAL.ogr_l_reference(layer.ptr) +reference(layer::AbstractFeatureLayer)::Integer = + GDAL.ogr_l_reference(layer.ptr) """ dereference(layer::AbstractFeatureLayer) @@ -1013,14 +1044,16 @@ Decrement layer reference count. ### Returns The reference count after decrementing. """ -dereference(layer::AbstractFeatureLayer) = GDAL.ogr_l_dereference(layer.ptr) +dereference(layer::AbstractFeatureLayer)::Integer = + GDAL.ogr_l_dereference(layer.ptr) """ nreference(layer::AbstractFeatureLayer) The current reference count for the layer object itself. """ -nreference(layer::AbstractFeatureLayer) = GDAL.ogr_l_getrefcount(layer.ptr) +nreference(layer::AbstractFeatureLayer)::Integer = + GDAL.ogr_l_getrefcount(layer.ptr) # """ # Flush pending changes to disk. @@ -1058,14 +1091,15 @@ nreference(layer::AbstractFeatureLayer) = GDAL.ogr_l_getrefcount(layer.ptr) The name of the FID column in the database, or \"\" if not supported. """ -fidcolumnname(layer::AbstractFeatureLayer) = GDAL.ogr_l_getfidcolumn(layer.ptr) +fidcolumnname(layer::AbstractFeatureLayer)::String = + GDAL.ogr_l_getfidcolumn(layer.ptr) """ geomcolumnname(layer::AbstractFeatureLayer) The name of the geometry column in the database, or \"\" if not supported. """ -geomcolumnname(layer::AbstractFeatureLayer) = +geomcolumnname(layer::AbstractFeatureLayer)::String = GDAL.ogr_l_getgeometrycolumn(layer.ptr) """ @@ -1088,7 +1122,10 @@ Besides field names of the layers, the following special fields can be passed: By default, no fields are ignored. """ -function setignoredfields!(layer::AbstractFeatureLayer, fieldnames) +function setignoredfields!( + layer::L, + fieldnames + )::L where {L <: AbstractFeatureLayer} result = GDAL.ogr_l_setignoredfields(layer.ptr, fieldnames) # OGRERR_NONE if all field names have been resolved (even if the driver # does not support this method) diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index d8574ff5..7d7e7412 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -5,36 +5,37 @@ Create a new field definition. By default, fields have no width, precision, are nullable and not ignored. """ -unsafe_createfielddefn(name::AbstractString, etype::OGRFieldType) = +unsafe_createfielddefn(name::AbstractString, etype::OGRFieldType)::FieldDefn = FieldDefn(GDAL.ogr_fld_create(name, etype)) "Destroy a field definition." -function destroy(fielddefn::FieldDefn) +function destroy(fielddefn::FieldDefn)::Nothing GDAL.ogr_fld_destroy(fielddefn.ptr) fielddefn.ptr = C_NULL - return fielddefn + return nothing end -function destroy(fielddefn::IFieldDefnView) +function destroy(fielddefn::IFieldDefnView)::Nothing fielddefn.ptr = C_NULL - return fielddefn + return nothing end "Set the name of this field." -function setname!(fielddefn::FieldDefn, name::AbstractString) +function setname!(fielddefn::FieldDefn, name::AbstractString)::FieldDefn GDAL.ogr_fld_setname(fielddefn.ptr, name) return fielddefn end "Fetch the name of this field." -getname(fielddefn::AbstractFieldDefn) = GDAL.ogr_fld_getnameref(fielddefn.ptr) +getname(fielddefn::AbstractFieldDefn)::String = + GDAL.ogr_fld_getnameref(fielddefn.ptr) "Fetch the type of this field." -gettype(fielddefn::AbstractFieldDefn) = +gettype(fielddefn::AbstractFieldDefn)::OGRFieldType = gdaltype(GDAL.ogr_fld_gettype(fielddefn.ptr)) "Set the type of this field." -function settype!(fielddefn::FieldDefn, etype::OGRFieldType) +function settype!(fielddefn::FieldDefn, etype::OGRFieldType)::FieldDefn GDAL.ogr_fld_settype(fielddefn.ptr, etype) return fielddefn end @@ -50,7 +51,7 @@ Fetch subtype of this field. ### Returns field subtype. """ -getsubtype(fielddefn::AbstractFieldDefn) = +getsubtype(fielddefn::AbstractFieldDefn)::GDAL.OGRFieldSubType = GDAL.ogr_fld_getsubtype(fielddefn.ptr) """ @@ -65,7 +66,7 @@ OGRFeatureDefn. * `fielddefn`: handle to the field definition to set type to. * `subtype`: the new field subtype. """ -function setsubtype!(fielddefn::FieldDefn, subtype::OGRFieldSubType) +function setsubtype!(fielddefn::FieldDefn, subtype::OGRFieldSubType)::FieldDefn GDAL.ogr_fld_setsubtype(fielddefn.ptr, subtype) return fielddefn end @@ -77,7 +78,7 @@ Get the justification for this field. Note: no driver is know to use the concept of field justification. """ -getjustify(fielddefn::AbstractFieldDefn) = +getjustify(fielddefn::AbstractFieldDefn)::GDAL.OGRJustification = GDAL.ogr_fld_getjustify(fielddefn.ptr) """ @@ -87,7 +88,10 @@ Set the justification for this field. Note: no driver is know to use the concept of field justification. """ -function setjustify!(fielddefn::FieldDefn, ejustify::OGRJustification) +function setjustify!( + fielddefn::FieldDefn, + ejustify::OGRJustification + )::FieldDefn GDAL.ogr_fld_setjustify(fielddefn.ptr, ejustify) return fielddefn end @@ -100,7 +104,8 @@ Get the formatting width for this field. ### Returns the width, zero means no specified width. """ -getwidth(fielddefn::AbstractFieldDefn) = GDAL.ogr_fld_getwidth(fielddefn.ptr) +getwidth(fielddefn::AbstractFieldDefn)::Integer = + GDAL.ogr_fld_getwidth(fielddefn.ptr) """ setwidth!(fielddefn::FieldDefn, width::Integer) @@ -110,7 +115,7 @@ Set the formatting width for this field in characters. This should never be done to an OGRFieldDefn that is already part of an OGRFeatureDefn. """ -function setwidth!(fielddefn::FieldDefn, width::Integer) +function setwidth!(fielddefn::FieldDefn, width::Integer)::FieldDefn GDAL.ogr_fld_setwidth(fielddefn.ptr, width) return fielddefn end @@ -122,7 +127,7 @@ Get the formatting precision for this field. This should normally be zero for fields of types other than OFTReal. """ -getprecision(fielddefn::AbstractFieldDefn) = +getprecision(fielddefn::AbstractFieldDefn)::Integer = GDAL.ogr_fld_getprecision(fielddefn.ptr) """ @@ -132,7 +137,7 @@ Set the formatting precision for this field in characters. This should normally be zero for fields of types other than OFTReal. """ -function setprecision!(fielddefn::FieldDefn, precision::Integer) +function setprecision!(fielddefn::FieldDefn, precision::Integer)::FieldDefn GDAL.ogr_fld_setprecision(fielddefn.ptr, precision) return fielddefn end @@ -157,7 +162,7 @@ function setparams!( nwidth::Integer = 0, nprecision::Integer = 0, justify::OGRJustification = GDAL.OJUndefined - ) + )::FieldDefn GDAL.ogr_fld_set(fielddefn.ptr, name, etype, nwidth, nprecision, justify) return fielddefn end @@ -167,7 +172,7 @@ end Return whether this field should be omitted when fetching features. """ -isignored(fielddefn::AbstractFieldDefn) = +isignored(fielddefn::AbstractFieldDefn)::Bool = Bool(GDAL.ogr_fld_isignored(fielddefn.ptr)) """ @@ -175,7 +180,7 @@ isignored(fielddefn::AbstractFieldDefn) = Set whether this field should be omitted when fetching features. """ -function setignored!(fielddefn::FieldDefn, ignore::Bool) +function setignored!(fielddefn::FieldDefn, ignore::Bool)::FieldDefn GDAL.ogr_fld_setignored(fielddefn.ptr, ignore) return fielddefn end @@ -192,7 +197,7 @@ that OGRFeature::IsFieldSet() will necessarily return `true`, as fields can be temporarily unset and null/not-null validation is usually done when OGRLayer::CreateFeature()/SetFeature() is called. """ -isnullable(fielddefn::AbstractFieldDefn) = +isnullable(fielddefn::AbstractFieldDefn)::Bool = Bool(GDAL.ogr_fld_isnullable(fielddefn.ptr)) """ @@ -206,7 +211,7 @@ to set a not-null constraint. Drivers that support writing not-null constraint will advertize the GDAL_DCAP_NOTNULL_FIELDS driver metadata item. """ -function setnullable!(fielddefn::FieldDefn, nullable::Bool) +function setnullable!(fielddefn::FieldDefn, nullable::Bool)::FieldDefn GDAL.ogr_fld_setnullable(fielddefn.ptr, nullable) return fielddefn end @@ -216,7 +221,7 @@ end Get default field value """ -function getdefault(fielddefn::AbstractFieldDefn) +function getdefault(fielddefn::AbstractFieldDefn)::String result = @gdal(OGR_Fld_GetDefault::Cstring, fielddefn.ptr::GDALFieldDefn) return if result == C_NULL "" @@ -247,7 +252,7 @@ datetime literal value, format should be 'YYYY/MM/DD HH:MM:SS[.sss]' Drivers that support writing DEFAULT clauses will advertize the GDAL_DCAP_DEFAULT_FIELDS driver metadata item. """ -function setdefault!(fielddefn::AbstractFieldDefn, default) +function setdefault!(fielddefn::T, default)::T where {T <: AbstractFieldDefn} GDAL.ogr_fld_setdefault(fielddefn.ptr, default) return fielddefn end @@ -261,7 +266,7 @@ Driver specific default values are those that are not NULL, a numeric value, a literal value enclosed between single quote characters, CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or datetime literal value. """ -isdefaultdriverspecific(fielddefn::AbstractFieldDefn) = +isdefaultdriverspecific(fielddefn::AbstractFieldDefn)::Bool = Bool(GDAL.ogr_fld_isdefaultdriverspecific(fielddefn.ptr)) """ @@ -269,39 +274,46 @@ isdefaultdriverspecific(fielddefn::AbstractFieldDefn) = Create a new field geometry definition. """ -unsafe_creategeomdefn(name::AbstractString, etype::WKBGeometryType) = - GeomFieldDefn(GDAL.ogr_gfld_create(name, etype)) +function unsafe_creategeomdefn( + name::AbstractString, + etype::WKBGeometryType + )::GeomFieldDefn + return GeomFieldDefn(GDAL.ogr_gfld_create(name, etype)) +end "Destroy a geometry field definition." -function destroy(geomdefn::GeomFieldDefn) +function destroy(geomdefn::GeomFieldDefn)::Nothing GDAL.ogr_gfld_destroy(geomdefn.ptr) geomdefn.ptr = C_NULL geomdefn.spatialref = SpatialRef() - return geomdefn + return nothing end "Destroy a geometry field definition." -function destroy(geomdefn::IGeomFieldDefnView) +function destroy(geomdefn::IGeomFieldDefnView)::Nothing geomdefn.ptr = C_NULL - return geomdefn + return nothing end "Set the name of this field." -function setname!(geomdefn::GeomFieldDefn, name::AbstractString) +function setname!(geomdefn::GeomFieldDefn, name::AbstractString)::GeomFieldDefn GDAL.ogr_gfld_setname(geomdefn.ptr, name) return geomdefn end "Fetch name of this field." -getname(geomdefn::AbstractGeomFieldDefn) = +getname(geomdefn::AbstractGeomFieldDefn)::String = GDAL.ogr_gfld_getnameref(geomdefn.ptr) "Fetch geometry type of this field." -gettype(geomdefn::AbstractGeomFieldDefn) = +gettype(geomdefn::AbstractGeomFieldDefn)::WKBGeometryType = gdaltype(GDAL.ogr_gfld_gettype(geomdefn.ptr)) "Set the geometry type of this field." -function settype!(geomdefn::GeomFieldDefn, etype::WKBGeometryType) +function settype!( + geomdefn::GeomFieldDefn, + etype::WKBGeometryType + )::GeomFieldDefn GDAL.ogr_gfld_settype(geomdefn.ptr, etype) return geomdefn end @@ -311,7 +323,7 @@ end Returns a clone of the spatial reference system for this field. May be NULL. """ -function getspatialref(geomdefn::AbstractGeomFieldDefn) +function getspatialref(geomdefn::AbstractGeomFieldDefn)::ISpatialRef result = GDAL.ogr_gfld_getspatialref(geomdefn.ptr) if result == C_NULL return ISpatialRef() @@ -322,7 +334,7 @@ function getspatialref(geomdefn::AbstractGeomFieldDefn) end end -function unsafe_getspatialref(geomdefn::AbstractGeomFieldDefn) +function unsafe_getspatialref(geomdefn::AbstractGeomFieldDefn)::SpatialRef result = GDAL.ogr_gfld_getspatialref(geomdefn.ptr) if result == C_NULL return SpatialRef() @@ -344,7 +356,7 @@ a new reference on the passed object (if non-NULL). function setspatialref!( geomdefn::GeomFieldDefn, spatialref::AbstractSpatialRef - ) + )::GeomFieldDefn clonespatialref = clone(spatialref) GDAL.ogr_gfld_setspatialref(geomdefn.ptr, clonespatialref.ptr) geomdefn.spatialref = clonespatialref @@ -365,7 +377,7 @@ OGRLayer::CreateFeature()/SetFeature() is called. Note that not-nullable geometry fields might also contain 'empty' geometries. """ -isnullable(geomdefn::AbstractGeomFieldDefn) = +isnullable(geomdefn::AbstractGeomFieldDefn)::Bool = Bool(GDAL.ogr_gfld_isnullable(geomdefn.ptr)) """ @@ -379,7 +391,7 @@ to set a not-null constraint. Drivers that support writing not-null constraint will advertize the GDAL_DCAP_NOTNULL_GEOMFIELDS driver metadata item. """ -function setnullable!(geomdefn::GeomFieldDefn, nullable::Bool) +function setnullable!(geomdefn::GeomFieldDefn, nullable::Bool)::GeomFieldDefn GDAL.ogr_gfld_setnullable(geomdefn.ptr, nullable) return geomdefn end @@ -389,7 +401,7 @@ end Return whether this field should be omitted when fetching features. """ -isignored(geomdefn::AbstractGeomFieldDefn) = +isignored(geomdefn::AbstractGeomFieldDefn)::Bool = Bool(GDAL.ogr_gfld_isignored(geomdefn.ptr)) """ @@ -397,7 +409,7 @@ isignored(geomdefn::AbstractGeomFieldDefn) = Set whether this field should be omitted when fetching features. """ -function setignored!(geomdefn::GeomFieldDefn, ignore::Bool) +function setignored!(geomdefn::GeomFieldDefn, ignore::Bool)::GeomFieldDefn GDAL.ogr_gfld_setignored(geomdefn.ptr, ignore) return geomdefn end diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 8436e923..2b899da5 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -8,7 +8,7 @@ binary (WKB) representation. ### Parameters * `data`: pointer to the input BLOB data. """ -function fromWKB(data) +function fromWKB(data)::IGeometry geom = Ref{GDALGeometry}() result = @gdal(OGR_G_CreateFromWkb::GDAL.OGRErr, data::Ptr{Cuchar}, @@ -20,7 +20,7 @@ function fromWKB(data) return IGeometry(geom[]) end -function unsafe_fromWKB(data) +function unsafe_fromWKB(data)::Geometry geom = Ref{GDALGeometry}() result = @gdal(OGR_G_CreateFromWkb::GDAL.OGRErr, data::Ptr{Cuchar}, @@ -43,7 +43,7 @@ Create a geometry object of the appropriate type from its well known text geometry to be created. The pointer is updated to point just beyond that last character consumed. """ -function fromWKT(data::Vector{String}) +function fromWKT(data::Vector{String})::IGeometry geom = Ref{GDALGeometry}() result = @gdal(OGR_G_CreateFromWkt::GDAL.OGRErr, data::StringList, @@ -54,7 +54,7 @@ function fromWKT(data::Vector{String}) return IGeometry(geom[]) end -function unsafe_fromWKT(data::Vector{String}) +function unsafe_fromWKT(data::Vector{String})::Geometry geom = Ref{GDALGeometry}() result = @gdal(OGR_G_CreateFromWkt::GDAL.OGRErr, data::StringList, @@ -65,9 +65,10 @@ function unsafe_fromWKT(data::Vector{String}) return Geometry(geom[]) end -fromWKT(data::String, args...) = fromWKT([data], args...) +fromWKT(data::String, args...)::IGeometry = fromWKT([data], args...) -unsafe_fromWKT(data::String, args...) = unsafe_fromWKT([data], args...) +unsafe_fromWKT(data::String, args...)::Geometry = + unsafe_fromWKT([data], args...) """ Destroy geometry object. @@ -75,9 +76,10 @@ Destroy geometry object. Equivalent to invoking delete on a geometry, but it guaranteed to take place within the context of the GDAL/OGR heap. """ -function destroy(geom::AbstractGeometry) +function destroy(geom::AbstractGeometry)::Nothing GDAL.ogr_g_destroygeometry(geom.ptr) geom.ptr = C_NULL + return nothing end """ @@ -85,7 +87,7 @@ end Returns a copy of the geometry with the original spatial reference system. """ -function clone(geom::AbstractGeometry) +function clone(geom::AbstractGeometry)::IGeometry if geom.ptr == C_NULL return IGeometry() else @@ -93,7 +95,7 @@ function clone(geom::AbstractGeometry) end end -function unsafe_clone(geom::AbstractGeometry) +function unsafe_clone(geom::AbstractGeometry)::Geometry if geom.ptr == C_NULL return Geometry() else @@ -109,10 +111,10 @@ Create an empty geometry of desired type. This is equivalent to allocating the desired geometry with new, but the allocation is guaranteed to take place in the context of the GDAL/OGR heap. """ -creategeom(geomtype::WKBGeometryType) = +creategeom(geomtype::WKBGeometryType)::IGeometry = IGeometry(GDAL.ogr_g_creategeometry(geomtype)) -unsafe_creategeom(geomtype::WKBGeometryType) = +unsafe_creategeom(geomtype::WKBGeometryType)::Geometry = Geometry(GDAL.ogr_g_creategeometry(geomtype)) """ @@ -139,7 +141,7 @@ function forceto( geom::AbstractGeometry, targettype::WKBGeometryType, options = StringList(C_NULL) - ) + )::IGeometry return IGeometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options)) end @@ -148,7 +150,7 @@ function unsafe_forceto( geom::AbstractGeometry, targettype::WKBGeometryType, options = StringList(C_NULL) - ) + )::Geometry return Geometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options)) end @@ -162,7 +164,7 @@ This function corresponds to the SFCOM IGeometry::GetDimension() method. It indicates the dimension of the geometry, but does not indicate the dimension of the underlying space (as indicated by OGR_G_GetCoordinateDimension() function). """ -geomdim(geom::AbstractGeometry) = GDAL.ogr_g_getdimension(geom.ptr) +geomdim(geom::AbstractGeometry)::Integer = GDAL.ogr_g_getdimension(geom.ptr) """ getcoorddim(geom::AbstractGeometry) @@ -173,7 +175,7 @@ Get the dimension of the coordinates in this geometry. In practice this will return 2 or 3. It can also return 0 in the case of an empty point. """ -getcoorddim(geom::AbstractGeometry) = +getcoorddim(geom::AbstractGeometry)::Integer = GDAL.ogr_g_getcoordinatedimension(geom.ptr) """ @@ -187,7 +189,7 @@ dimension of a geometry collection, a compound curve, a polygon, etc. will affect the children geometries. This will also remove the M dimension if present before this call. """ -function setcoorddim!(geom::AbstractGeometry, dim::Integer) +function setcoorddim!(geom::G, dim::Integer)::G where {G <: AbstractGeometry} GDAL.ogr_g_setcoordinatedimension(geom.ptr ,dim) return geom end @@ -197,7 +199,7 @@ end Computes and returns the bounding envelope for this geometry. """ -function envelope(geom::AbstractGeometry) +function envelope(geom::AbstractGeometry)::GDAL.OGREnvelope envelope = Ref{GDAL.OGREnvelope}(GDAL.OGREnvelope(0, 0, 0, 0)) GDAL.ogr_g_getenvelope(geom.ptr, envelope) return envelope[] @@ -208,7 +210,7 @@ end Computes and returns the bounding envelope (3D) for this geometry """ -function envelope3d(geom::AbstractGeometry) +function envelope3d(geom::AbstractGeometry)::GDAL.OGREnvelope3D envelope = Ref{GDAL.OGREnvelope3D}(GDAL.OGREnvelope3D(0, 0, 0, 0, 0, 0)) GDAL.ogr_g_getenvelope3d(geom.ptr, envelope) return envelope[] @@ -219,7 +221,7 @@ end Returns a bounding box polygon (CW) built from envelope coordinates """ -function boundingbox(geom::AbstractGeometry) +function boundingbox(geom::AbstractGeometry)::IGeometry coordinates = envelope(geom) MinX, MaxX = coordinates.MinX, coordinates.MaxX MinY, MaxY = coordinates.MinY, coordinates.MaxY @@ -238,8 +240,11 @@ Convert a geometry well known binary format. * `geom`: handle on the geometry to convert to a well know binary data from. * `order`: One of wkbXDR or [wkbNDR] indicating MSB or LSB byte order resp. """ -function toWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = GDAL.wkbNDR) - buffer = Array{Cuchar}(undef, wkbsize(geom)) +function toWKB( + geom::AbstractGeometry, + order::OGRwkbByteOrder = GDAL.wkbNDR + )::Vector{Cuchar} + buffer = Vector{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttowkb(geom.ptr, order, buffer) @ogrerr result "Failed to export geometry to WKB" return buffer @@ -254,7 +259,10 @@ Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. * `geom`: handle on the geometry to convert to a well know binary data from. * `order`: One of wkbXDR or [wkbNDR] indicating MSB or LSB byte order resp. """ -function toISOWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = GDAL.wkbNDR) +function toISOWKB( + geom::AbstractGeometry, + order::OGRwkbByteOrder = GDAL.wkbNDR + )::Vector{Cuchar} buffer = Array{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttoisowkb(geom.ptr, order, buffer) @ogrerr result "Failed to export geometry to ISO WKB" @@ -266,14 +274,14 @@ end Returns size (in bytes) of related binary representation. """ -wkbsize(geom::AbstractGeometry) = GDAL.ogr_g_wkbsize(geom.ptr) +wkbsize(geom::AbstractGeometry)::Integer = GDAL.ogr_g_wkbsize(geom.ptr) """ toWKT(geom::AbstractGeometry) Convert a geometry into well known text format. """ -function toWKT(geom::AbstractGeometry) +function toWKT(geom::AbstractGeometry)::String wkt_ptr = Ref(Cstring(C_NULL)) result = GDAL.ogr_g_exporttowkt(geom.ptr, wkt_ptr) @ogrerr result "OGRErr $result: failed to export geometry to WKT" @@ -287,7 +295,7 @@ end Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known text format. """ -function toISOWKT(geom::AbstractGeometry) +function toISOWKT(geom::AbstractGeometry)::String isowkt_ptr = Ref(Cstring(C_NULL)) result = GDAL.ogr_g_exporttoisowkt(geom.ptr, isowkt_ptr) @ogrerr result "OGRErr $result: failed to export geometry to ISOWKT" @@ -301,7 +309,7 @@ end Fetch geometry type code """ -getgeomtype(geom::AbstractGeometry) = +getgeomtype(geom::AbstractGeometry)::WKBGeometryType = gdaltype(GDAL.ogr_g_getgeometrytype(geom.ptr)) """ @@ -309,14 +317,14 @@ getgeomtype(geom::AbstractGeometry) = Fetch WKT name for geometry type. """ -geomname(geom::AbstractGeometry) = GDAL.ogr_g_getgeometryname(geom.ptr) +geomname(geom::AbstractGeometry)::String = GDAL.ogr_g_getgeometryname(geom.ptr) """ flattento2d!(geom::AbstractGeometry) Convert geometry to strictly 2D. """ -function flattento2d!(geom::AbstractGeometry) +function flattento2d!(geom::G)::G where {G <: AbstractGeometry} GDAL.ogr_g_flattento2d(geom.ptr) return geom end @@ -329,7 +337,7 @@ Force rings to be closed. If this geometry, or any contained geometries has polygon rings that are not closed, they will be closed by adding the starting point at the end. """ -function closerings!(geom::AbstractGeometry) +function closerings!(geom::G)::G where {G <: AbstractGeometry} GDAL.ogr_g_closerings(geom.ptr) return geom end @@ -346,23 +354,23 @@ geometries supported by this parser, but they are too numerous to list here. The following GML2 elements are parsed : Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, MultiGeometry. """ -fromGML(data) = IGeometry(GDAL.ogr_g_createfromgml(data)) +fromGML(data)::IGeometry = IGeometry(GDAL.ogr_g_createfromgml(data)) -unsafe_fromGML(data) = Geometry(GDAL.ogr_g_createfromgml(data)) +unsafe_fromGML(data)::Geometry = Geometry(GDAL.ogr_g_createfromgml(data)) """ toGML(geom::AbstractGeometry) Convert a geometry into GML format. """ -toGML(geom::AbstractGeometry) = GDAL.ogr_g_exporttogml(geom.ptr) +toGML(geom::AbstractGeometry)::String = GDAL.ogr_g_exporttogml(geom.ptr) """ toKML(geom::AbstractGeometry, altitudemode = C_NULL) Convert a geometry into KML format. """ -toKML(geom::AbstractGeometry, altitudemode = C_NULL) = +toKML(geom::AbstractGeometry, altitudemode = C_NULL)::String = GDAL.ogr_g_exporttokml(geom.ptr, altitudemode) # ↑ * `altitudemode`: value to write in altitudeMode element, or NULL. @@ -371,7 +379,7 @@ toKML(geom::AbstractGeometry, altitudemode = C_NULL) = Convert a geometry into GeoJSON format. """ -toJSON(geom::AbstractGeometry) = GDAL.ogr_g_exporttojson(geom.ptr) +toJSON(geom::AbstractGeometry)::String = GDAL.ogr_g_exporttojson(geom.ptr) """ toJSON(geom::AbstractGeometry, options) @@ -385,7 +393,7 @@ Convert a geometry into GeoJSON format. ### Returns A GeoJSON fragment or NULL in case of error. """ -toJSON(geom::AbstractGeometry, options) = +toJSON(geom::AbstractGeometry, options)::String = GDAL.ogr_g_exporttojsonex(geom.ptr, options) """ @@ -393,9 +401,10 @@ toJSON(geom::AbstractGeometry, options) = Create a geometry object from its GeoJSON representation. """ -fromJSON(data::String) = IGeometry(GDAL.ogr_g_creategeometryfromjson(data)) +fromJSON(data::String)::IGeometry = + IGeometry(GDAL.ogr_g_creategeometryfromjson(data)) -unsafe_fromJSON(data::String) = +unsafe_fromJSON(data::String)::Geometry = Geometry(GDAL.ogr_g_creategeometryfromjson(data)) # """ @@ -424,27 +433,27 @@ Returns a clone of the spatial reference system for the geometry. (The original SRS may be shared with many objects, and should not be modified.) """ -function getspatialref(geom::AbstractGeometry) +function getspatialref(geom::AbstractGeometry)::ISpatialRef if geom.ptr == C_NULL return ISpatialRef() end result = GDAL.ogr_g_getspatialreference(geom.ptr) - if result == C_NULL - return ISpatialRef() + return if result == C_NULL + ISpatialRef() else - return ISpatialRef(GDAL.osrclone(result)) + ISpatialRef(GDAL.osrclone(result)) end end -function unsafe_getspatialref(geom::AbstractGeometry) +function unsafe_getspatialref(geom::AbstractGeometry)::SpatialRef if geom.ptr == C_NULL return SpatialRef() end result = GDAL.ogr_g_getspatialreference(geom.ptr) - if result == C_NULL - return SpatialRef() + return if result == C_NULL + SpatialRef() else - return SpatialRef(GDAL.osrclone(result)) + SpatialRef(GDAL.osrclone(result)) end end @@ -457,7 +466,10 @@ Apply arbitrary coordinate transformation to geometry. * `geom`: handle on the geometry to apply the transform to. * `coordtransform`: handle on the transformation to apply. """ -function transform!(geom::AbstractGeometry, coordtransform::CoordTransform) +function transform!( + geom::G, + coordtransform::CoordTransform + )::G where {G <: AbstractGeometry} result = GDAL.ogr_g_transform(geom.ptr, coordtransform.ptr) @ogrerr result "Failed to transform geometry" return geom @@ -501,10 +513,10 @@ Compute a simplified geometry. * `geom`: the geometry. * `tol`: the distance tolerance for the simplification. """ -simplify(geom::AbstractGeometry, tol::Real) = +simplify(geom::AbstractGeometry, tol::Real)::IGeometry = IGeometry(GDAL.ogr_g_simplify(geom.ptr, tol)) -unsafe_simplify(geom::AbstractGeometry, tol::Real) = +unsafe_simplify(geom::AbstractGeometry, tol::Real)::Geometry = Geometry(GDAL.ogr_g_simplify(geom.ptr, tol)) """ @@ -516,10 +528,10 @@ Simplify the geometry while preserving topology. * `geom`: the geometry. * `tol`: the distance tolerance for the simplification. """ -simplifypreservetopology(geom::AbstractGeometry, tol::Real) = +simplifypreservetopology(geom::AbstractGeometry, tol::Real)::IGeometry = IGeometry(GDAL.ogr_g_simplifypreservetopology(geom.ptr, tol)) -unsafe_simplifypreservetopology(geom::AbstractGeometry, tol::Real) = +unsafe_simplifypreservetopology(geom::AbstractGeometry, tol::Real)::Geometry = Geometry(GDAL.ogr_g_simplifypreservetopology(geom.ptr, tol)) """ @@ -533,14 +545,19 @@ Return a Delaunay triangulation of the vertices of the geometry. * `onlyedges`: if `true`, will return a MULTILINESTRING, otherwise it will return a GEOMETRYCOLLECTION containing triangular POLYGONs. """ -delaunaytriangulation(geom::AbstractGeometry, tol::Real, onlyedges::Bool) = - IGeometry(GDAL.ogr_g_delaunaytriangulation(geom.ptr, tol, onlyedges)) +function delaunaytriangulation( + geom::AbstractGeometry, + tol::Real, + onlyedges::Bool + )::IGeometry + return IGeometry(GDAL.ogr_g_delaunaytriangulation(geom.ptr, tol, onlyedges)) +end function unsafe_delaunaytriangulation( geom::AbstractGeometry, tol::Real, onlyedges::Bool - ) + )::Geometry return Geometry(GDAL.ogr_g_delaunaytriangulation(geom.ptr, tol, onlyedges)) end @@ -556,7 +573,7 @@ computation is performed in 2d only * `geom`: the geometry to segmentize * `maxlength`: the maximum distance between 2 points after segmentization """ -function segmentize!(geom::AbstractGeometry, maxlength::Real) +function segmentize!(geom::G, maxlength::Real)::G where {G <: AbstractGeometry} GDAL.ogr_g_segmentize(geom.ptr, maxlength) return geom end @@ -570,7 +587,7 @@ Determines whether two geometries intersect. If GEOS is enabled, then this is done in rigorous fashion otherwise `true` is returned if the envelopes (bounding boxes) of the two geometries overlap. """ -intersects(g1::AbstractGeometry, g2::AbstractGeometry) = +intersects(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_intersects(g1.ptr, g2.ptr)) """ @@ -578,7 +595,7 @@ intersects(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if the geometries are equivalent. """ -equals(g1::AbstractGeometry, g2::AbstractGeometry) = +equals(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_equals(g1.ptr, g2.ptr)) """ @@ -586,7 +603,7 @@ equals(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if the geometries are disjoint. """ -disjoint(g1::AbstractGeometry, g2::AbstractGeometry) = +disjoint(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_disjoint(g1.ptr, g2.ptr)) """ @@ -594,7 +611,7 @@ disjoint(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if the geometries are touching. """ -touches(g1::AbstractGeometry, g2::AbstractGeometry) = +touches(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_touches(g1.ptr, g2.ptr)) """ @@ -602,7 +619,7 @@ touches(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if the geometries are crossing. """ -crosses(g1::AbstractGeometry, g2::AbstractGeometry) = +crosses(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_crosses(g1.ptr, g2.ptr)) """ @@ -610,7 +627,7 @@ crosses(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if g1 is contained within g2. """ -within(g1::AbstractGeometry, g2::AbstractGeometry) = +within(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_within(g1.ptr, g2.ptr)) """ @@ -618,7 +635,7 @@ within(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if g1 contains g2. """ -contains(g1::AbstractGeometry, g2::AbstractGeometry) = +contains(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_contains(g1.ptr, g2.ptr)) """ @@ -626,7 +643,7 @@ contains(g1::AbstractGeometry, g2::AbstractGeometry) = Returns `true` if the geometries overlap. """ -overlaps(g1::AbstractGeometry, g2::AbstractGeometry) = +overlaps(g1::AbstractGeometry, g2::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_overlaps(g1.ptr, g2.ptr)) """ @@ -637,9 +654,10 @@ Returns the boundary of the geometry. A new geometry object is created and returned containing the boundary of the geometry on which the method is invoked. """ -boundary(geom::AbstractGeometry) = IGeometry(GDAL.ogr_g_boundary(geom.ptr)) +boundary(geom::AbstractGeometry)::IGeometry = + IGeometry(GDAL.ogr_g_boundary(geom.ptr)) -unsafe_boundary(geom::AbstractGeometry) = +unsafe_boundary(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_boundary(geom.ptr)) """ @@ -650,9 +668,10 @@ Returns the convex hull of the geometry. A new geometry object is created and returned containing the convex hull of the geometry on which the method is invoked. """ -convexhull(geom::AbstractGeometry) = IGeometry(GDAL.ogr_g_convexhull(geom.ptr)) +convexhull(geom::AbstractGeometry)::IGeometry = + IGeometry(GDAL.ogr_g_convexhull(geom.ptr)) -unsafe_convexhull(geom::AbstractGeometry) = +unsafe_convexhull(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_convexhull(geom.ptr)) """ @@ -678,11 +697,16 @@ accuracy of the result. * `quadsegs`: the number of segments used to approximate a 90 degree (quadrant) of curvature. """ -buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30) = +buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30)::IGeometry = IGeometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) -unsafe_buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30) = - Geometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) +function unsafe_buffer( + geom::AbstractGeometry, + dist::Real, + quadsegs::Integer = 30 + )::Geometry + return Geometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) +end """ intersection(g1::AbstractGeometry, g2::AbstractGeometry) @@ -694,10 +718,10 @@ Generates a new geometry which is the region of intersection of the two geometries operated on. The OGR_G_Intersects() function can be used to test if two geometries intersect. """ -intersection(g1::AbstractGeometry, g2::AbstractGeometry) = +intersection(g1::AbstractGeometry, g2::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_intersection(g1.ptr, g2.ptr)) -unsafe_intersection(g1::AbstractGeometry, g2::AbstractGeometry) = +unsafe_intersection(g1::AbstractGeometry, g2::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_intersection(g1.ptr, g2.ptr)) """ @@ -705,10 +729,10 @@ unsafe_intersection(g1::AbstractGeometry, g2::AbstractGeometry) = Returns a new geometry representing the union of the geometries. """ -union(g1::AbstractGeometry, g2::AbstractGeometry) = +union(g1::AbstractGeometry, g2::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_union(g1.ptr, g2.ptr)) -unsafe_union(g1::AbstractGeometry, g2::AbstractGeometry) = +unsafe_union(g1::AbstractGeometry, g2::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_union(g1.ptr, g2.ptr)) """ @@ -721,10 +745,10 @@ the current implementation based on GEOS can operate on other geometry types than the types that are supported by SQL/MM-Part 3 : surfaces (polygons) and multisurfaces (multipolygons). """ -pointonsurface(geom::AbstractGeometry) = +pointonsurface(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_pointonsurface(geom.ptr)) -unsafe_pointonsurface(geom::AbstractGeometry) = +unsafe_pointonsurface(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_pointonsurface(geom.ptr)) """ @@ -737,10 +761,10 @@ the other geometry removed. A new geometry representing the difference of the geometries, or NULL if the difference is empty. """ -difference(g1::AbstractGeometry, g2::AbstractGeometry) = +difference(g1::AbstractGeometry, g2::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_difference(g1.ptr, g2.ptr)) -unsafe_difference(g1::AbstractGeometry, g2::AbstractGeometry) = +unsafe_difference(g1::AbstractGeometry, g2::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_difference(g1.ptr, g2.ptr)) """ @@ -749,10 +773,10 @@ unsafe_difference(g1::AbstractGeometry, g2::AbstractGeometry) = Returns a new geometry representing the symmetric difference of the geometries or NULL if the difference is empty or an error occurs. """ -symdifference(g1::AbstractGeometry, g2::AbstractGeometry) = +symdifference(g1::AbstractGeometry, g2::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_symdifference(g1.ptr, g2.ptr)) -unsafe_symdifference(g1::AbstractGeometry, g2::AbstractGeometry) = +unsafe_symdifference(g1::AbstractGeometry, g2::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_symdifference(g1.ptr, g2.ptr)) """ @@ -760,7 +784,7 @@ unsafe_symdifference(g1::AbstractGeometry, g2::AbstractGeometry) = Returns the distance between the geometries or -1 if an error occurs. """ -distance(g1::AbstractGeometry, g2::AbstractGeometry) = +distance(g1::AbstractGeometry, g2::AbstractGeometry)::Float64 = GDAL.ogr_g_distance(g1.ptr, g2.ptr) """ @@ -768,14 +792,14 @@ distance(g1::AbstractGeometry, g2::AbstractGeometry) = Returns the length of the geometry, or 0.0 for unsupported geometry types. """ -geomlength(geom::AbstractGeometry) = GDAL.ogr_g_length(geom.ptr) +geomlength(geom::AbstractGeometry)::Float64 = GDAL.ogr_g_length(geom.ptr) """ geomarea(geom::AbstractGeometry) Returns the area of the geometry or 0.0 for unsupported geometry types. """ -geomarea(geom::AbstractGeometry) = GDAL.ogr_g_area(geom.ptr) +geomarea(geom::AbstractGeometry)::Float64 = GDAL.ogr_g_area(geom.ptr) """ centroid!(geom::AbstractGeometry, centroid::AbstractGeometry) @@ -791,7 +815,10 @@ multipoint, linestring, geometrycollection such as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces (polygons). SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons). """ -function centroid!(geom::AbstractGeometry, centroid::AbstractGeometry) +function centroid!( + geom::AbstractGeometry, + centroid::G + )::G where {G <: AbstractGeometry} result = GDAL.ogr_g_centroid(geom.ptr, centroid.ptr) @ogrerr result "Failed to compute the geometry centroid" return centroid @@ -810,13 +837,13 @@ multipoint, linestring, geometrycollection such as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces (polygons). SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons).) """ -function centroid(geom::AbstractGeometry) +function centroid(geom::AbstractGeometry)::IGeometry point = createpoint() centroid!(geom, point) return point end -function unsafe_centroid(geom::AbstractGeometry) +function unsafe_centroid(geom::AbstractGeometry)::Geometry point = unsafe_createpoint() centroid!(geom, point) return point @@ -835,10 +862,10 @@ Fetch point at given distance along curve. ### Returns a point or NULL. """ -pointalongline(geom::AbstractGeometry, distance::Real) = +pointalongline(geom::AbstractGeometry, distance::Real)::IGeometry = IGeometry(GDAL.ogr_g_value(geom.ptr, distance)) -unsafe_pointalongline(geom::AbstractGeometry, distance::Real) = +unsafe_pointalongline(geom::AbstractGeometry, distance::Real)::Geometry = Geometry(GDAL.ogr_g_value(geom.ptr, distance)) """ @@ -849,7 +876,7 @@ Clear geometry information. This restores the geometry to its initial state after construction, and before assignment of actual geometry. """ -function empty!(geom::AbstractGeometry) +function empty!(geom::G)::G where {G <: AbstractGeometry} GDAL.ogr_g_empty(geom.ptr) return geom end @@ -859,28 +886,28 @@ end Returns `true` if the geometry has no points, otherwise `false`. """ -isempty(geom::AbstractGeometry) = Bool(GDAL.ogr_g_isempty(geom.ptr)) +isempty(geom::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_isempty(geom.ptr)) """ isvalid(geom::AbstractGeometry) Returns `true` if the geometry is valid, otherwise `false`. """ -isvalid(geom::AbstractGeometry) = Bool(GDAL.ogr_g_isvalid(geom.ptr)) +isvalid(geom::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_isvalid(geom.ptr)) """ issimple(geom::AbstractGeometry) Returns `true` if the geometry is simple, otherwise `false`. """ -issimple(geom::AbstractGeometry) = Bool(GDAL.ogr_g_issimple(geom.ptr)) +issimple(geom::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_issimple(geom.ptr)) """ isring(geom::AbstractGeometry) Returns `true` if the geometry is a ring, otherwise `false`. """ -isring(geom::AbstractGeometry) = Bool(GDAL.ogr_g_isring(geom.ptr)) +isring(geom::AbstractGeometry)::Bool = Bool(GDAL.ogr_g_isring(geom.ptr)) """ polygonize(geom::AbstractGeometry) @@ -892,9 +919,10 @@ reassembled Polygons: NULL will be returned if the input collection doesn't correspond to a MultiLinestring, or when reassembling Edges into Polygons is impossible due to topological inconsistencies. """ -polygonize(geom::AbstractGeometry) = IGeometry(GDAL.ogr_g_polygonize(geom.ptr)) +polygonize(geom::AbstractGeometry)::IGeometry = + IGeometry(GDAL.ogr_g_polygonize(geom.ptr)) -unsafe_polygonize(geom::AbstractGeometry) = +unsafe_polygonize(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_polygonize(geom.ptr)) # """ @@ -933,21 +961,21 @@ unsafe_polygonize(geom::AbstractGeometry) = Fetch the x coordinate of a point from a geometry, at index i. """ -getx(geom::AbstractGeometry, i::Integer) = GDAL.ogr_g_getx(geom.ptr, i) +getx(geom::AbstractGeometry, i::Integer)::Float64 = GDAL.ogr_g_getx(geom.ptr, i) """ gety(geom::AbstractGeometry, i::Integer) Fetch the y coordinate of a point from a geometry, at index i. """ -gety(geom::AbstractGeometry, i::Integer) = GDAL.ogr_g_gety(geom.ptr, i) +gety(geom::AbstractGeometry, i::Integer)::Float64 = GDAL.ogr_g_gety(geom.ptr, i) """ getz(geom::AbstractGeometry, i::Integer) Fetch the z coordinate of a point from a geometry, at index i. """ -getz(geom::AbstractGeometry, i::Integer) = GDAL.ogr_g_getz(geom.ptr, i) +getz(geom::AbstractGeometry, i::Integer)::Float64 = GDAL.ogr_g_getz(geom.ptr, i) """ getpoint(geom::AbstractGeometry, i::Integer) @@ -957,8 +985,8 @@ Fetch a point in line string or a point geometry, at index i. ### Parameters * `i`: the vertex to fetch, from 0 to getNumPoints()-1, zero for a point. """ -getpoint(geom::AbstractGeometry, i::Integer) = - getpoint!(geom, i, Ref{Cdouble}(), Ref{Cdouble}(), Ref{Cdouble}()) +getpoint(geom::AbstractGeometry, i::Integer)::Tuple{Float64, Float64, Float64} = + getpoint!(geom, i, Ref{Float64}(), Ref{Float64}(), Ref{Float64}()) function getpoint!(geom::AbstractGeometry, i::Integer, x, y, z) GDAL.ogr_g_getpoint(geom.ptr, i, x, y, z) @@ -974,7 +1002,7 @@ Set number of points in a geometry. * `geom`: the geometry. * `n`: the new number of points for geometry. """ -function setpointcount!(geom::AbstractGeometry, n::Integer) +function setpointcount!(geom::G, n::Integer)::G where {G <: AbstractGeometry} GDAL.ogr_g_setpointcount(geom.ptr, n) return geom end @@ -995,17 +1023,22 @@ Set the location of a vertex in a point or linestring geometry. function setpoint! end function setpoint!( - geom::AbstractGeometry, + geom::G, i::Integer, x::Real, y::Real, z::Real - ) + )::G where {G <: AbstractGeometry} GDAL.ogr_g_setpoint(geom.ptr, i, x, y, z) return geom end -function setpoint!(geom::AbstractGeometry, i::Integer, x::Real, y::Real) +function setpoint!( + geom::G, + i::Integer, + x::Real, + y::Real + )::G where {G <: AbstractGeometry} GDAL.ogr_g_setpoint_2d(geom.ptr, i, x, y) return geom end @@ -1024,12 +1057,17 @@ Add a point to a geometry (line string or point). """ function addpoint! end -function addpoint!(geom::AbstractGeometry, x::Real, y::Real, z::Real) +function addpoint!( + geom::G, + x::Real, + y::Real, + z::Real + )::G where {G <: AbstractGeometry} GDAL.ogr_g_addpoint(geom.ptr, x, y, z) return geom end -function addpoint!(geom::AbstractGeometry, x::Real, y::Real) +function addpoint!(geom::G, x::Real, y::Real)::G where {G <: AbstractGeometry} GDAL.ogr_g_addpoint_2d(geom.ptr, x, y) return geom end @@ -1076,7 +1114,7 @@ This corresponds to wkbGeometryCollection[25D], and * `0` for other geometry types. """ -function ngeom(geom::AbstractGeometry) +function ngeom(geom::AbstractGeometry)::Integer n = GDAL.ogr_g_getpointcount(geom.ptr) n == 0 ? GDAL.ogr_g_getgeometrycount(geom.ptr) : n end @@ -1093,13 +1131,13 @@ For a polygon, `getgeom(polygon,i)` returns the exterior ring if * `geom`: the geometry container from which to get a geometry from. * `i`: index of the geometry to fetch, between 0 and getNumGeometries() - 1. """ -function getgeom(geom::AbstractGeometry, i::Integer) +function getgeom(geom::AbstractGeometry, i::Integer)::IGeometry # NOTE(yeesian): GDAL.ogr_g_getgeometryref(geom, i) returns an handle to a # geometry within the container. The returned geometry remains owned by the # container, and should not be modified. The handle is only valid until the # next change to the geometry container. Use OGR_G_Clone() to make a copy. if geom.ptr == C_NULL - return Geometry() + return IGeometry() end result = GDAL.ogr_g_getgeometryref(geom.ptr, i) if result == C_NULL @@ -1109,7 +1147,7 @@ function getgeom(geom::AbstractGeometry, i::Integer) end end -function unsafe_getgeom(geom::AbstractGeometry, i::Integer) +function unsafe_getgeom(geom::AbstractGeometry, i::Integer)::Geometry # NOTE(yeesian): GDAL.ogr_g_getgeometryref(geom, i) returns an handle to a # geometry within the container. The returned geometry remains owned by the # container, and should not be modified. The handle is only valid until the @@ -1142,7 +1180,10 @@ interior rings. * `geomcontainer`: existing geometry. * `subgeom`: geometry to add to the existing geometry. """ -function addgeom!(geomcontainer::AbstractGeometry, subgeom::AbstractGeometry) +function addgeom!( + geomcontainer::G, + subgeom::AbstractGeometry + )::G where {G <: AbstractGeometry} result = GDAL.ogr_g_addgeometry(geomcontainer.ptr, subgeom.ptr) @ogrerr result "Failed to add geometry. The geometry type could be illegal" return geomcontainer @@ -1185,7 +1226,11 @@ Remove a geometry from an exiting geometry container. The default is `true` as the existing geometry is considered to own the geometries in it. """ -function removegeom!(geom::AbstractGeometry, i::Integer, todelete::Bool = true) +function removegeom!( + geom::G, + i::Integer, + todelete::Bool = true + )::G where {G <: AbstractGeometry} result = GDAL.ogr_g_removegeometry(geom.ptr, i, todelete) @ogrerr result "Failed to remove geometry. The index could be out of range." return geom @@ -1202,7 +1247,10 @@ Remove all geometries from an exiting geometry container. The default is `true` as the existing geometry is considered to own the geometries in it. """ -function removeallgeoms!(geom::AbstractGeometry, todelete::Bool = true) +function removeallgeoms!( + geom::G, + todelete::Bool = true + )::G where {G <: AbstractGeometry} result = GDAL.ogr_g_removegeometry(geom.ptr, -1, todelete) @ogrerr result "Failed to remove all geometries." return geom @@ -1218,7 +1266,7 @@ Returns if this geometry is or has curve geometry. * `nonlinear`: set it to `true` to check if the geometry is or contains a CIRCULARSTRING. """ -hascurvegeom(geom::AbstractGeometry, nonlinear::Bool) = +hascurvegeom(geom::AbstractGeometry, nonlinear::Bool)::Bool = Bool(GDAL.ogr_g_hascurvegeometry(geom.ptr, nonlinear)) """ @@ -1236,20 +1284,25 @@ MULTICURVE or MULTISURFACE in it, by approximating curve geometries. * `options`: options as a null-terminated list of strings or NULL. See OGRGeometryFactory::curveToLineString() for valid options. """ -lineargeom(geom::AbstractGeometry, stepsize::Real = 0) = +lineargeom(geom::AbstractGeometry, stepsize::Real = 0)::IGeometry = IGeometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, C_NULL)) -unsafe_lineargeom(geom::AbstractGeometry, stepsize::Real = 0) = +unsafe_lineargeom(geom::AbstractGeometry, stepsize::Real = 0)::Geometry = Geometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, C_NULL)) -lineargeom(geom::AbstractGeometry, options::Vector, stepsize::Real = 0) = - IGeometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) +function lineargeom( + geom::AbstractGeometry, + options::Vector, + stepsize::Real = 0 + )::IGeometry + return IGeometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) +end function unsafe_lineargeom( geom::AbstractGeometry, options::Vector, stepsize::Real = 0 - ) + )::Geometry return Geometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) end @@ -1266,10 +1319,10 @@ If the geometry has no curve portion, the returned geometry will be a clone. The reverse function is OGR_G_GetLinearGeometry(). """ -curvegeom(geom::AbstractGeometry) = +curvegeom(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_getcurvegeometry(geom.ptr, C_NULL)) -unsafe_curvegeom(geom::AbstractGeometry) = +unsafe_curvegeom(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_getcurvegeometry(geom.ptr, C_NULL)) """ @@ -1293,7 +1346,7 @@ function polygonfromedges( tol::Real; besteffort::Bool = false, autoclose::Bool = false - ) + )::IGeometry perr = Ref{GDAL.OGRErr}() result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, tol, perr) @@ -1306,7 +1359,7 @@ function unsafe_polygonfromedges( tol::Real; besteffort::Bool = false, autoclose::Bool = false - ) + )::Geometry perr = Ref{GDAL.OGRErr}() result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, tol, perr) @@ -1338,15 +1391,17 @@ other libraries or applications. ### Returns a point or NULL. """ -setnonlineargeomflag!(flag::Bool) = +function setnonlineargeomflag!(flag::Bool)::Nothing GDAL.ogrsetnonlineargeometriesenabledflag(flag) + return nothing +end """ getnonlineargeomflag() Get flag to enable/disable returning non-linear geometries in the C API. """ -getnonlineargeomflag() = Bool(GDAL.ogrgetnonlineargeometriesenabledflag()) +getnonlineargeomflag()::Bool = Bool(GDAL.ogrgetnonlineargeometriesenabledflag()) for (geom, wkbgeom) in ((:geomcollection, wkbGeometryCollection), (:linestring, wkbLineString), @@ -1358,18 +1413,19 @@ for (geom, wkbgeom) in ((:geomcollection, wkbGeometryCollection), (:point, wkbPoint), (:polygon, wkbPolygon)) eval(quote - $(Symbol("create$geom"))() = creategeom($wkbgeom) - $(Symbol("unsafe_create$geom"))() = unsafe_creategeom($wkbgeom) + $(Symbol("create$geom"))()::IGeometry = creategeom($wkbgeom) + $(Symbol("unsafe_create$geom"))()::Geometry = + unsafe_creategeom($wkbgeom) end) end -for f in (:create, :unsafe_create) +for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) for (args, typedargs) in ( ((:x,:y), (:(x::Real),:(y::Real))), ((:x,:y,:z), (:(x::Real),:(y::Real),:(z::Real))) ) eval(quote - function $(Symbol("$(f)point"))($(typedargs...)) + function $(Symbol("$(f)point"))($(typedargs...))::$rt geom = $(Symbol("$(f)point"))() addpoint!(geom, $(args...)) return geom @@ -1386,7 +1442,7 @@ for f in (:create, :unsafe_create) ) for geom in (:linestring, :linearring) eval(quote - function $(Symbol("$f$geom"))($(typedargs...)) + function $(Symbol("$f$geom"))($(typedargs...))::$rt geom = $(Symbol("$f$geom"))() for pt in zip($(args...)) addpoint!(geom, pt...) @@ -1398,7 +1454,7 @@ for f in (:create, :unsafe_create) for (geom,component) in ((:polygon, :linearring),) eval(quote - function $(Symbol("$f$geom"))($(typedargs...)) + function $(Symbol("$f$geom"))($(typedargs...))::$rt geom = $(Symbol("$f$geom"))() subgeom = $(Symbol("unsafe_create$component"))($(args...)) result = GDAL.ogr_g_addgeometrydirectly( @@ -1413,7 +1469,7 @@ for f in (:create, :unsafe_create) for (geom,component) in ((:multipoint, :point),) eval(quote - function $(Symbol("$f$geom"))($(typedargs...)) + function $(Symbol("$f$geom"))($(typedargs...))::$rt geom = $(Symbol("$f$geom"))() for pt in zip($(args...)) subgeom = $(Symbol("unsafe_create$component"))(pt) @@ -1433,7 +1489,7 @@ for f in (:create, :unsafe_create) Tuple{<:Real,<:Real}, Tuple{<:Real,<:Real,<:Real}) eval(quote - function $(Symbol("$(f)point"))(coords::$typeargs) + function $(Symbol("$(f)point"))(coords::$typeargs)::$rt geom = $(Symbol("$(f)point"))() addpoint!(geom, coords...) return geom @@ -1446,7 +1502,7 @@ for f in (:create, :unsafe_create) Vector{Vector{Cdouble}}) for geom in (:linestring, :linearring) eval(quote - function $(Symbol("$f$geom"))(coords::$typeargs) + function $(Symbol("$f$geom"))(coords::$typeargs)::$rt geom = $(Symbol("$f$geom"))() for coord in coords addpoint!(geom, coord...) @@ -1458,7 +1514,7 @@ for f in (:create, :unsafe_create) for (geom,component) in ((:polygon, :linearring),) eval(quote - function $(Symbol("$f$geom"))(coords::$typeargs) + function $(Symbol("$f$geom"))(coords::$typeargs)::$rt geom = $(Symbol("$f$geom"))() subgeom = $(Symbol("unsafe_create$component"))(coords) result = GDAL.ogr_g_addgeometrydirectly( @@ -1492,7 +1548,7 @@ for f in (:create, :unsafe_create) ) for typearg in typeargs, (geom, component) in variants eval(quote - function $(Symbol("$f$geom"))(coords::$typearg) + function $(Symbol("$f$geom"))(coords::$typearg)::$rt geom = $(Symbol("$f$geom"))() for coord in coords subgeom = $(Symbol("unsafe_create$component"))(coord) diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index 4af83caf..504ba0f5 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -9,7 +9,7 @@ OGRStyleMgr factory. ### Returns an handle to the new style manager object. """ -unsafe_createstylemanager(styletable = GDALStyleTable(C_NULL)) = +unsafe_createstylemanager(styletable = GDALStyleTable(C_NULL))::StyleManager = StyleManager(GDAL.ogr_sm_create(styletable)) """ @@ -18,7 +18,7 @@ Destroy Style Manager. ### Parameters * `stylemanager`: handle to the style manager to destroy. """ -function destroy(sm::StyleManager) +function destroy(sm::StyleManager)::Nothing GDAL.ogr_sm_destroy(sm.ptr) sm.ptr = C_NULL return nothing @@ -37,7 +37,7 @@ Initialize style manager from the style string of a feature. ### Returns the style string read from the feature, or NULL in case of error. """ -initialize!(stylemanager::StyleManager, feature::Feature) = +initialize!(stylemanager::StyleManager, feature::Feature)::String = GDAL.ogr_sm_initfromfeature(stylemanager.ptr, feature.ptr) """ @@ -49,9 +49,9 @@ Initialize style manager from the style string. * `stylemanager`: handle to the style manager. * `stylestring`: the style string to use (can be NULL). ### Returns -`true` on success, `false` on errors. +`true` on success, `false` on error. """ -initialize!(stylemanager::StyleManager, stylestring = C_NULL) = +initialize!(stylemanager::StyleManager, stylestring = C_NULL)::Bool = Bool(GDAL.ogr_sm_initstylestring(stylemanager.ptr, stylestring)) """ @@ -70,10 +70,10 @@ the number of parts (style tools) in the style. """ function npart end -npart(stylemanager::StyleManager) = +npart(stylemanager::StyleManager)::Integer = GDAL.ogr_sm_getpartcount(stylemanager.ptr, C_NULL) -npart(stylemanager::StyleManager, stylestring::AbstractString) = +npart(stylemanager::StyleManager, stylestring::AbstractString)::Integer = GDAL.ogr_sm_getpartcount(stylemanager.ptr, stylestring) """ @@ -91,8 +91,13 @@ Fetch a part (style tool) from the current style. ### Returns OGRStyleToolH of the requested part (style tools) or NULL on error. """ -unsafe_getpart(stylemanager::StyleManager, id::Integer, stylestring = C_NULL) = +function unsafe_getpart( + stylemanager::StyleManager, + id::Integer, + stylestring = C_NULL + )::StyleTool StyleTool(GDAL.ogr_sm_getpart(stylemanager.ptr, id, stylestring)) +end """ addpart!(stylemanager::StyleManager, styletool::StyleTool) @@ -104,9 +109,9 @@ Add a part (style tool) to the current style. * `styletool`: the style tool defining the part to add. ### Returns -`true` on success, `false` on errors. +`true` on success, `false` on error. """ -addpart!(stylemanager::StyleManager, styletool::StyleTool) = +addpart!(stylemanager::StyleManager, styletool::StyleTool)::Bool = Bool(GDAL.ogr_sm_addpart(stylemanager.ptr, styletool.ptr)) """ @@ -121,17 +126,17 @@ Add a style to the current style table. the style stored in the manager. ### Returns -`true` on success, `false` on errors. +`true` on success, `false` on error. """ function addstyle!( stylemanager::StyleManager, stylename::AbstractString, stylestring::AbstractString - ) + )::Bool return Bool(GDAL.ogr_sm_addstyle(stylemanager.ptr, stylename, stylestring)) end -addstyle!(stylemanager::StyleManager, stylename::AbstractString) = +addstyle!(stylemanager::StyleManager, stylename::AbstractString)::Bool = Bool(GDAL.ogr_sm_addstyle(stylemanager.ptr, stylename, C_NULL)) """ @@ -146,7 +151,7 @@ OGRStyleTool factory. ### Returns an handle to the new style tool object or NULL if the creation failed. """ -unsafe_createstyletool(classid::OGRSTClassId) = +unsafe_createstyletool(classid::OGRSTClassId)::StyleTool = StyleTool(GDAL.ogr_st_create(classid)) """ @@ -155,7 +160,7 @@ Destroy Style Tool. ### Parameters * `styletool`: handle to the style tool to destroy. """ -function destroy(styletool::StyleTool) +function destroy(styletool::StyleTool)::Nothing GDAL.ogr_st_destroy(styletool.ptr) styletool.ptr = C_NULL return nothing @@ -173,7 +178,7 @@ Determine type of Style Tool. the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2), OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the OGRStyleToolH is invalid. """ -gettype(styletool::StyleTool) = GDAL.ogr_st_gettype(styletool.ptr) +gettype(styletool::StyleTool)::GDAL.OGRSTClassId = GDAL.ogr_st_gettype(styletool.ptr) """ getunit(styletool::StyleTool) @@ -186,7 +191,7 @@ Get Style Tool units. ### Returns the style tool units. """ -getunit(styletool::StyleTool) = GDAL.ogr_st_getunit(styletool.ptr) +getunit(styletool::StyleTool)::GDAL.OGRSTUnitId = GDAL.ogr_st_getunit(styletool.ptr) """ setunit!(styletool::StyleTool, newunit::OGRSTUnitId, scale::Real) @@ -198,8 +203,14 @@ Set Style Tool units. * `newunit`: the new unit. * `scale`: ground to paper scale factor. """ -setunit!(styletool::StyleTool, newunit::OGRSTUnitId, scale::Real) = +function setunit!( + styletool::StyleTool, + newunit::OGRSTUnitId, + scale::Real + )::StyleTool GDAL.ogr_st_setunit(styletool.ptr, newunit, scale) + return styletool +end """ asstring(styletool::StyleTool, id::Integer) @@ -218,10 +229,10 @@ Get Style Tool parameter value as a string. ### Returns the parameter value as a string and sets `nullflag`. """ -asstring(styletool::StyleTool, id::Integer, nullflag::Ref{Cint}) = +asstring(styletool::StyleTool, id::Integer, nullflag::Ref{Cint})::String = GDAL.ogr_st_getparamstr(styletool.ptr, id, nullflag) -asstring(styletool::StyleTool, id::Integer) = +asstring(styletool::StyleTool, id::Integer)::String = asstring(styletool, id, Ref{Cint}(0)) """ @@ -240,8 +251,13 @@ Get Style Tool parameter value as an integer. ### Returns the parameter value as an integer and sets `nullflag`. """ -asint(styletool::StyleTool, id::Integer, nullflag::Ref{Cint} = Ref{Cint}(0)) = - GDAL.ogr_st_getparamnum(styletool.ptr, id, nullflag) +function asint( + styletool::StyleTool, + id::Integer, + nullflag::Ref{Cint} = Ref{Cint}(0) + )::Int32 + return GDAL.ogr_st_getparamnum(styletool.ptr, id, nullflag) +end """ asdouble(styletool::StyleTool, id::Integer, nullflag = Ref{Cint}(0)) @@ -263,7 +279,7 @@ function asdouble( styletool::StyleTool, id::Integer, nullflag::Ref{Cint} = Ref{Cint}(0) - ) + )::Float64 return GDAL.ogr_st_getparamdbl(styletool.ptr, id, nullflag) end @@ -281,14 +297,32 @@ Set Style Tool parameter value. """ function setparam! end -setparam!(styletool::StyleTool, id::Integer, value::AbstractString) = +function setparam!( + styletool::StyleTool, + id::Integer, + value::AbstractString + )::StyleTool GDAL.ogr_st_setparamstr(styletool.ptr, id, value) + return styletool +end -setparam!(styletool::StyleTool, id::Integer, value::Integer) = +function setparam!( + styletool::StyleTool, + id::Integer, + value::Integer + )::StyleTool GDAL.ogr_st_setparamnum(styletool.ptr, id, value) + return styletool +end -setparam!(styletool::StyleTool, id::Integer, value::Float64) = +function setparam!( + styletool::StyleTool, + id::Integer, + value::Float64 + )::StyleTool GDAL.ogr_st_setparamdbl(styletool.ptr, id, value) + return styletool +end """ getstylestring(styletool::StyleTool) @@ -301,7 +335,8 @@ Get the style string for this Style Tool. ### Returns the style string for this style tool or "" if the styletool is invalid. """ -getstylestring(styletool::StyleTool) = GDAL.ogr_st_getstylestring(styletool.ptr) +getstylestring(styletool::StyleTool)::String = + GDAL.ogr_st_getstylestring(styletool.ptr) """ toRGBA(styletool::StyleTool, color::AbstractString) @@ -315,11 +350,14 @@ Return the r,g,b,a components of a color encoded in #RRGGBB[AA] format. ### Returns (R,G,B,A) tuple of Cints. """ -function toRGBA(styletool::StyleTool, color::AbstractString) - red = Ref{Cint}(0) - green = Ref{Cint}(0) - blue = Ref{Cint}(0) - alpha = Ref{Cint}(0) +function toRGBA( + styletool::StyleTool, + color::AbstractString + )::Tuple{Int32, Int32, Int32, Int32} + red = Ref{Int32}(0) + green = Ref{Int32}(0) + blue = Ref{Int32}(0) + alpha = Ref{Int32}(0) result = Bool(GDAL.ogr_st_getrgbfromstring(styletool.ptr, color, red, green, blue, alpha)) result || error("Error in getting RGBA from Styletool") @@ -334,7 +372,7 @@ OGRStyleTable factory. ### Returns an handle to the new style table object. """ -unsafe_createstyletable() = StyleTable(GDAL.ogr_stbl_create()) +unsafe_createstyletable()::StyleTable = StyleTable(GDAL.ogr_stbl_create()) """ Destroy Style Table. @@ -342,7 +380,7 @@ Destroy Style Table. ### Parameters * `styletable`: handle to the style table to destroy. """ -function destroy(st::StyleTable) +function destroy(st::StyleTable)::Nothing GDAL.ogr_stbl_destroy(st.ptr) st.ptr = C_NULL return nothing @@ -365,7 +403,7 @@ function addstyle!( styletable::StyleTable, stylename::AbstractString, stylestring::AbstractString - ) + )::Bool return Bool(GDAL.ogr_stbl_addstyle(styletable.ptr, stylename, stylestring)) end @@ -381,7 +419,7 @@ Save a style table to a file. ### Returns `true` on success, `false` on error """ -savestyletable(styletable::StyleTable, filename::AbstractString) = +savestyletable(styletable::StyleTable, filename::AbstractString)::Bool = Bool(GDAL.ogr_stbl_savestyletable(styletable.ptr, filename)) """ @@ -396,7 +434,7 @@ Load a style table from a file. ### Returns `true` on success, `false` on error """ -loadstyletable!(styletable::StyleTable, filename::AbstractString) = +loadstyletable!(styletable::StyleTable, filename::AbstractString)::Bool = Bool(GDAL.ogr_stbl_loadstyletable(styletable.ptr, filename)) """ @@ -411,7 +449,7 @@ Get a style string by name. ### Returns the style string matching the name or NULL if not found or error. """ -findstylestring(styletable::StyleTable, name::AbstractString) = +findstylestring(styletable::StyleTable, name::AbstractString)::String = GDAL.ogr_stbl_find(styletable.ptr, name) """ @@ -422,8 +460,10 @@ Reset the next style pointer to 0. ### Parameters * `styletable`: handle to the style table. """ -resetreading!(styletable::StyleTable) = +function resetreading!(styletable::StyleTable)::StyleTable GDAL.ogr_stbl_resetstylestringreading(styletable.ptr) + return styletable +end """ nextstyle(styletable::StyleTable) @@ -436,7 +476,8 @@ Get the next style string from the table. ### Returns the next style string or NULL on error. """ -nextstyle(styletable::StyleTable) = GDAL.ogr_stbl_getnextstyle(styletable.ptr) +nextstyle(styletable::StyleTable)::String = + GDAL.ogr_stbl_getnextstyle(styletable.ptr) """ laststyle(styletable::StyleTable) @@ -449,5 +490,5 @@ Get the style name of the last style string fetched with OGR_STBL_GetNextStyle. ### Returns the Name of the last style string or NULL on error. """ -laststyle(styletable::StyleTable) = +laststyle(styletable::StyleTable)::String = GDAL.ogr_stbl_getlaststylename(styletable.ptr) From 1175f1462f216f13ea6c7e82e565c34260c7116b Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 10:21:43 -0700 Subject: [PATCH 014/169] [Breaking] copywholeraster -> copywholeraster! It now returns the dataset that was copied into as the return type. --- src/dataset.jl | 12 ++++++------ test/test_dataset.jl | 24 +++++++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/dataset.jl b/src/dataset.jl index bb32240c..b20971a4 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -20,17 +20,17 @@ specific `createcopy()` functions. It implements efficient copying, in particular \"chunking\" the copy in substantial blocks and, if appropriate, performing the transfer in a pixel interleaved fashion. """ -function copywholeraster( +function copywholeraster!( source::AbstractDataset, - dest::AbstractDataset; + dest::D; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata::Any = C_NULL - ) + )::D where {D <: AbstractDataset} result = GDAL.gdaldatasetcopywholeraster(source.ptr, dest.ptr, options, @cplprogress(progressfunc), progressdata) @cplerr result "Failed to copy whole raster" - return result + return dest end """ @@ -612,10 +612,10 @@ end Fetch a band object for a dataset from its index. """ -getband(dataset::AbstractDataset, i::Integer) = +getband(dataset::AbstractDataset, i::Integer)::IRasterBand = IRasterBand(GDAL.gdalgetrasterband(dataset.ptr, i), ownedby = dataset) -unsafe_getband(dataset::AbstractDataset, i::Integer) = +unsafe_getband(dataset::AbstractDataset, i::Integer)::RasterBand = RasterBand(GDAL.gdalgetrasterband(dataset.ptr, i)) """ diff --git a/test/test_dataset.jl b/test/test_dataset.jl index 6e3132b6..0ce59360 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -11,10 +11,13 @@ import ArchGDAL; const AG = ArchGDAL @test AG.ngcp(copydataset) == 0 AG.getband(copydataset,1) do band @test AG.noverview(band) == 0 - AG.buildoverviews!(copydataset, Cint[2,4,8]) + AG.buildoverviews!(copydataset, Cint[2, 4, 8]) @test AG.noverview(band) == 3 - AG.copywholeraster(dataset, copydataset, - progressfunc=GDAL.gdaltermprogress) + AG.copywholeraster!( + dataset, + copydataset, + progressfunc = GDAL.gdaltermprogress + ) end end end @@ -22,16 +25,23 @@ import ArchGDAL; const AG = ArchGDAL copydataset = AG.copy(dataset, filename = "/vsimem/utmcopy.tif") @test AG.ngcp(copydataset) == 0 @test AG.noverview(AG.getband(copydataset,1)) == 0 - AG.buildoverviews!(copydataset, Cint[2,4,8]) + AG.buildoverviews!(copydataset, Cint[2, 4, 8]) @test AG.noverview(AG.getband(copydataset,1)) == 3 - AG.copywholeraster(dataset, copydataset, - progressfunc=GDAL.gdaltermprogress) + AG.copywholeraster!( + dataset, + copydataset, + progressfunc = GDAL.gdaltermprogress + ) end AG.copyfiles("GTiff", "/vsimem/utmcopy2.tif", "/vsimem/utmcopy.tif") AG.update("/vsimem/utmcopy2.tif") do copydataset @test AG.ngcp(copydataset) == 0 @test AG.noverview(AG.getband(copydataset,1)) == 3 - AG.copywholeraster(dataset, copydataset, options = ["COMPRESS=LZW"]) + AG.copywholeraster!( + dataset, + copydataset, + options = ["COMPRESS=LZW"] + ) end end end From 1411c7983386862f4a20fecdf9c9ca19c41d9227 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 19:36:25 -0700 Subject: [PATCH 015/169] annotate with return types --- src/raster/array.jl | 110 ++++++++++++++--------- src/raster/colortable.jl | 31 ++++--- src/raster/rasterattributetable.jl | 63 ++++++++------ src/raster/rasterband.jl | 134 ++++++++++++++++++----------- src/raster/rasterio.jl | 129 +++++++++++++++------------ 5 files changed, 285 insertions(+), 182 deletions(-) diff --git a/src/raster/array.jl b/src/raster/array.jl index d675f67e..24f25c4a 100644 --- a/src/raster/array.jl +++ b/src/raster/array.jl @@ -2,7 +2,6 @@ import DiskArrays const AllowedXY = Union{Integer,Colon,AbstractRange} const AllowedBand = Union{Integer,Colon,AbstractArray} - """ RasterDataset(dataset::AbstractDataset) @@ -22,12 +21,14 @@ us to be able to index into it like we would an array. Constructing a RasterDataset will error if the raster bands do not have all the same size and a common element data type. """ -struct RasterDataset{T,DS} <: AbstractDiskArray{T,3} +struct RasterDataset{T, DS <: AbstractDataset} <: AbstractDiskArray{T,3} ds::DS size::Tuple{Int,Int,Int} end -function RasterDataset(ds::AbstractDataset) +function RasterDataset( + ds::AbstractDataset + )::RasterDataset{_dataset_type(ds), typeof(ds)} if iszero(nraster(ds)) throw(ArgumentError("The Dataset does not contain any raster bands")) end @@ -41,16 +42,39 @@ end for f in (:getgeotransform, :nraster, :getband, :getproj, :width, :height, :destroy, :getdriver, :filelist, :listcapability, :ngcp, :copy, :write, :testcapability, :setproj!, :buildoverviews!) - eval(:($(f)(x::RasterDataset, args...; kwargs...) = $(f)(x.ds, args...; kwargs...))) + eval(:( + $(f)(x::RasterDataset, args...; kwargs...) = + $(f)(x.ds, args...; kwargs...) + )) end # Here we need to special-case, because source and dest might be rasters -copywholeraster(x::RasterDataset,y::AbstractDataset;kwargs...) = - copywholeraster(x.ds, y; kwargs...) -copywholeraster(x::RasterDataset,y::RasterDataset;kwargs...) = - copywholeraster(x.ds, y.ds; kwargs...) -copywholeraster(x::AbstractDataset,y::RasterDataset;kwargs...) = - copywholeraster(x.ds, y.ds; kwargs...) +function copywholeraster!( + source::RasterDataset, + dest::D; + kwargs... + )::D where {D <: AbstractDataset} + copywholeraster!(source.ds, dest; kwargs...) + return dest +end + +function copywholeraster!( + source::RasterDataset, + dest::RasterDataset; + kwargs... + )::RasterDataset + copywholeraster!(source.ds, dest.ds; kwargs...) + return dest +end + +function copywholeraster!( + source::AbstractDataset, + dest::RasterDataset; + kwargs... + )::RasterDataset + copywholeraster!(source.ds, dest.ds; kwargs...) + return dest +end """ _dataset_type(ds::AbstractDataset) @@ -58,7 +82,7 @@ copywholeraster(x::AbstractDataset,y::RasterDataset;kwargs...) = Tries to determine a common dataset type for all the bands in a raster dataset. """ -function _dataset_type(ds::AbstractDataset) +function _dataset_type(ds::AbstractDataset)::DataType alldatatypes = map(1:nraster(ds)) do i b = getband(ds, i) pixeltype(b) @@ -87,8 +111,8 @@ function _common_size(ds::AbstractDataset) return Int.((s[1]..., nr)) end -getband(ds::RasterDataset, i::Integer) = getband(ds.ds, i) -unsafe_readraster(args...; kwargs...) = +getband(ds::RasterDataset, i::Integer)::IRasterBand = getband(ds.ds, i) +unsafe_readraster(args...; kwargs...)::RasterDataset = RasterDataset(unsafe_read(args...; kwargs...)) """ @@ -99,19 +123,22 @@ function returns a `RasterDataset`, which is a subtype of `AbstractDiskArray{T,3}`, so that users can operate on the array using direct indexing. """ -readraster(s::String; kwargs...) = RasterDataset(read(s; kwargs...)) +readraster(s::String; kwargs...)::RasterDataset = + RasterDataset(read(s; kwargs...)) -function DiskArrays.eachchunk(ds::RasterDataset) +function DiskArrays.eachchunk(ds::RasterDataset)::DiskArrays.GridChunks subchunks = DiskArrays.eachchunk(getband(ds, 1)) return DiskArrays.GridChunks(ds,(subchunks.chunksize..., 1)) end -DiskArrays.haschunks(::RasterDataset) = DiskArrays.Chunked() -DiskArrays.haschunks(::AbstractRasterBand) = DiskArrays.Chunked() +DiskArrays.haschunks(::RasterDataset)::DiskArrays.Chunked = DiskArrays.Chunked() +DiskArrays.haschunks(::AbstractRasterBand)::DiskArrays.Chunked = + DiskArrays.Chunked() -Base.size(band::AbstractRasterBand) = (width(band), height(band)) +Base.size(band::AbstractRasterBand)::Tuple{T, T} where {T <: Integer} = + (width(band), height(band)) -function DiskArrays.eachchunk(band::AbstractRasterBand) +function DiskArrays.eachchunk(band::AbstractRasterBand)::DiskArrays.GridChunks wI = windows(band) cs = (wI.blockiter.xbsize, wI.blockiter.ybsize) return DiskArrays.GridChunks(band, cs) @@ -119,66 +146,71 @@ end function DiskArrays.readblock!( band::AbstractRasterBand, - buffer, x::AbstractUnitRange, + buffer::T, + x::AbstractUnitRange, y::AbstractUnitRange - ) - xoffset, yoffset = first(x)-1, first(y)-1 + )::T where {T <: Any} + xoffset, yoffset = first(x) - 1, first(y) - 1 xsize, ysize = length(x), length(y) - return read!(band, buffer, xoffset, yoffset, xsize, ysize) + read!(band, buffer, xoffset, yoffset, xsize, ysize) + return buffer end function DiskArrays.writeblock!( band::AbstractRasterBand, - value, + buffer::T, x::AbstractUnitRange, y::AbstractUnitRange - ) - xoffset, yoffset = first(x)-1, first(y)-1 + )::T where {T <: Any} + xoffset, yoffset = first(x) - 1, first(y) - 1 xsize, ysize = length(x), length(y) - return write!(band, value, xoffset, yoffset, xsize, ysize) + write!(band, buffer, xoffset, yoffset, xsize, ysize) + return buffer end # AbstractDataset indexing -Base.size(dataset::RasterDataset) = dataset.size +Base.size(dataset::RasterDataset)::Tuple{Int,Int,Int} = dataset.size function DiskArrays.readblock!( dataset::RasterDataset, - buffer, + buffer::T, x::AbstractUnitRange, y::AbstractUnitRange, z::AbstractUnitRange - ) + )::T where {T <: Any} buffer2 = Array(buffer) DiskArrays.readblock!(dataset::RasterDataset, buffer2, x, y, z) - return buffer .= buffer2 + buffer .= buffer2 + return buffer end function DiskArrays.readblock!( dataset::RasterDataset, - buffer::Array, + buffer::T, x::AbstractUnitRange, y::AbstractUnitRange, z::AbstractUnitRange - ) + )::T where {T <: Array} xoffset, yoffset = first.((x, y)) .- 1 - xsize, ysize= length.((x, y)) - indices = [Cint(i) for i in z] - return read!(dataset.ds, buffer, indices, xoffset, yoffset, xsize, ysize) + xsize, ysize = length.((x, y)) + read!(dataset.ds, buffer, Cint.(z), xoffset, yoffset, xsize, ysize) + return buffer end function DiskArrays.writeblock!( dataset::RasterDataset, - value, + buffer::T, x::AbstractUnitRange, y::AbstractUnitRange, bands::AbstractUnitRange - ) + )::T where {T <: Any} xoffset, yoffset = first.((x, y)) .- 1 xsize, ysize= length.((x, y)) indices = [Cint(i) for i in bands] - return write!(dataset.ds, value, indices, xoffset, yoffset, xsize, ysize) + write!(dataset.ds, buffer, indices, xoffset, yoffset, xsize, ysize) + return buffer end Base.Array(dataset::RasterDataset) = dataset[:,:,:] diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index eb87eeba..5ec879ec 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -3,11 +3,11 @@ Construct a new color table. """ -unsafe_createcolortable(palette::GDALPaletteInterp) = +unsafe_createcolortable(palette::GDALPaletteInterp)::ColorTable = ColorTable(GDAL.gdalcreatecolortable(palette)) "Destroys a color table." -function destroy(ct::ColorTable) +function destroy(ct::ColorTable)::Nothing GDAL.gdaldestroycolortable(ct.ptr) ct.ptr = C_NULL return nothing @@ -18,7 +18,8 @@ end Make a copy of a color table. """ -unsafe_clone(ct::ColorTable) = ColorTable(GDAL.gdalclonecolortable(ct.ptr)) +unsafe_clone(ct::ColorTable)::ColorTable = + ColorTable(GDAL.gdalclonecolortable(ct.ptr)) """ paletteinterp(ct::ColorTable) @@ -28,21 +29,22 @@ Fetch palette interpretation. ### Returns palette interpretation enumeration value, usually `GPI_RGB`. """ -paletteinterp(ct::ColorTable) = GDAL.gdalgetpaletteinterpretation(ct.ptr) +paletteinterp(ct::ColorTable)::GDAL.GDALPaletteInterp = + GDAL.gdalgetpaletteinterpretation(ct.ptr) """ ncolorentry(ct::ColorTable) Get number of color entries in table. """ -ncolorentry(ct::ColorTable) = GDAL.gdalgetcolorentrycount(ct.ptr) +ncolorentry(ct::ColorTable)::Integer = GDAL.gdalgetcolorentrycount(ct.ptr) """ getcolorentry(ct::ColorTable, i::Integer) Fetch a color entry from table. """ -getcolorentry(ct::ColorTable, i::Integer) = +getcolorentry(ct::ColorTable, i::Integer)::GDAL.GDALColorEntry = unsafe_load(GDAL.gdalgetcolorentry(ct.ptr, i)) """ @@ -58,9 +60,9 @@ tables. * `i` entry offset from zero to GetColorEntryCount()-1. ### Returns -`true` on success, or `false` if the conversion isn't supported. +The color entry in RGB format. """ -function getcolorentryasrgb(ct::ColorTable, i::Integer) +function getcolorentryasrgb(ct::ColorTable, i::Integer)::GDAL.GDALColorEntry colorentry = Ref{GDAL.GDALColorEntry}(GDAL.GDALColorEntry(0, 0, 0, 0)) result = Bool(GDAL.gdalgetcolorentryasrgb(ct.ptr, i, colorentry)) result || @warn("The conversion to RGB isn't supported.") @@ -82,7 +84,11 @@ The table is grown as needed to hold the supplied offset. * `i` entry offset from `0` to `ncolorentry()-1`. * `entry` value to assign to table. """ -function setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry) +function setcolorentry!( + ct::ColorTable, + i::Integer, + entry::GDAL.GDALColorEntry + )::ColorTable GDAL.gdalsetcolorentry(ct.ptr, i, Ref{GDAL.GDALColorEntry}(entry)) return ct end @@ -104,7 +110,7 @@ called several times to create multiples ramps in the same color table. * `endcolor` a color entry value to end the ramp ### Returns -total number of entries, -1 to report error +The color table with the created color ramp. """ function createcolorramp!( ct::ColorTable, @@ -112,12 +118,13 @@ function createcolorramp!( startcolor::GDAL.GDALColorEntry, endindex::Integer, endcolor::GDAL.GDALColorEntry - ) - return GDAL.gdalcreatecolorramp( + )::ColorTable + GDAL.gdalcreatecolorramp( ct.ptr, startindex, Ref{GDAL.GDALColorEntry}(startcolor), endindex, Ref{GDAL.GDALColorEntry}(endcolor) ) + return ct end diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 33ed497e..918357da 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -3,18 +3,19 @@ Construct empty table. """ -unsafe_createRAT() = RasterAttrTable(GDAL.gdalcreaterasterattributetable()) +unsafe_createRAT()::RasterAttrTable = + RasterAttrTable(GDAL.gdalcreaterasterattributetable()) """ unsafe_createRAT(ct::ColorTable) Construct table from an existing colortable. """ -unsafe_createRAT(ct::ColorTable) = +unsafe_createRAT(ct::ColorTable)::RasterAttrTable = initializeRAT!(unsafe_createRAT(), ct) "Destroys a RAT." -function destroy(rat::RasterAttrTable) +function destroy(rat::RasterAttrTable)::Nothing GDAL.gdaldestroyrasterattributetable(rat.ptr) rat.ptr = C_NULL return nothing @@ -25,7 +26,7 @@ end Fetch table column count. """ -ncolumn(rat::RasterAttrTable) = GDAL.gdalratgetcolumncount(rat.ptr) +ncolumn(rat::RasterAttrTable)::Integer = GDAL.gdalratgetcolumncount(rat.ptr) """ columnname(rat::RasterAttrTable, i::Integer) @@ -38,7 +39,7 @@ Fetch name of indicated column. ### Returns the column name or an empty string for invalid column numbers. """ -columnname(rat::RasterAttrTable, i::Integer) = +columnname(rat::RasterAttrTable, i::Integer)::String = GDAL.gdalratgetnameofcol(rat.ptr, i) """ @@ -46,7 +47,7 @@ columnname(rat::RasterAttrTable, i::Integer) = Fetch column usage value. """ -columnusage(rat::RasterAttrTable, i::Integer) = +columnusage(rat::RasterAttrTable, i::Integer)::GDAL.GDALRATFieldUsage = GDAL.gdalratgetusageofcol(rat.ptr, i) """ @@ -60,7 +61,7 @@ Fetch column type. ### Returns column type or `GFT_Integer` if the column index is illegal. """ -columntype(rat::RasterAttrTable, i::Integer) = +columntype(rat::RasterAttrTable, i::Integer)::GDAL.GDALRATFieldType = GDAL.gdalratgettypeofcol(rat.ptr, i) """ @@ -72,7 +73,7 @@ match is found. ### Parameters * `usage` usage type to search for. """ -findcolumnindex(rat::RasterAttrTable, usage::GDALRATFieldUsage) = +findcolumnindex(rat::RasterAttrTable, usage::GDALRATFieldUsage)::Integer = GDAL.gdalratgetcolofusage(rat.ptr, usage) """ @@ -80,7 +81,7 @@ findcolumnindex(rat::RasterAttrTable, usage::GDALRATFieldUsage) = Fetch row count. """ -nrow(rat::RasterAttrTable) = GDAL.gdalratgetrowcount(rat.ptr) +nrow(rat::RasterAttrTable)::Integer = GDAL.gdalratgetrowcount(rat.ptr) """ asstring(rat::RasterAttrTable, row::Integer, col::Integer) @@ -95,7 +96,7 @@ some precision may be lost. * `row` row to fetch (zero based). * `col` column to fetch (zero based). """ -asstring(rat::RasterAttrTable, row::Integer, col::Integer) = +asstring(rat::RasterAttrTable, row::Integer, col::Integer)::String = GDAL.gdalratgetvalueasstring(rat.ptr, row, col) """ @@ -110,7 +111,7 @@ Non-integer fields will be converted to int with the possibility of data loss. * `row` row to fetch (zero based). * `col` column to fetch (zero based). """ -asint(rat::RasterAttrTable, row::Integer, col::Integer) = +asint(rat::RasterAttrTable, row::Integer, col::Integer)::Integer = GDAL.gdalratgetvalueasint(rat.ptr, row, col) """ @@ -125,7 +126,7 @@ Non double fields will be converted to double with the possibility of data loss. * `row` row to fetch (zero based). * `col` column to fetch (zero based). """ -asdouble(rat::RasterAttrTable, row::Integer, col::Integer) = +asdouble(rat::RasterAttrTable, row::Integer, col::Integer)::Float64 = GDAL.gdalratgetvalueasdouble(rat.ptr, row, col) """ @@ -149,7 +150,7 @@ function setvalue!( row::Integer, col::Integer, val::AbstractString - ) + )::RasterAttrTable GDAL.gdalratsetvalueasstring(rat.ptr, row, col, val) return rat end @@ -159,7 +160,7 @@ function setvalue!( row::Integer, col::Integer, val::Integer - ) + )::RasterAttrTable GDAL.gdalratsetvalueasint(rat.ptr, row, col, val) return rat end @@ -169,7 +170,7 @@ function setvalue!( row::Integer, col::Integer, val::Float64 - ) + )::RasterAttrTable GDAL.gdalratsetvalueasdouble(rat.ptr, row, col, val) return rat end @@ -183,7 +184,7 @@ If this returns `false` then GDALRasterBand.SetDefaultRAT() should be called. Otherwise this is unnecessary since changes to this object are reflected in the dataset. """ -changesarewrittentofile(rat::RasterAttrTable) = +changesarewrittentofile(rat::RasterAttrTable)::Bool = Bool(GDAL.gdalratchangesarewrittentofile(rat.ptr)) """ @@ -209,7 +210,7 @@ function attributeio!( startrow::Integer, nrows::Integer, data::Vector{Float64} - ) + )::Vector{Float64} result = GDAL.gdalratvaluesioasdouble(rat.ptr, access, col, startrow, nrows, data) @cplerr result "Failed to $access at column $col starting at $startrow" @@ -223,7 +224,7 @@ function attributeio!( startrow::Integer, nrows::Integer, data::Vector{Cint} - ) + )::Vector{Cint} result = GDAL.gdalratvaluesioasinteger(rat.ptr, access, col, startrow, nrows, data) @cplerr result "Failed to $access at column $col starting at $startrow" @@ -237,7 +238,7 @@ function attributeio!( startrow::Integer, nrows::Integer, data::Vector{T} - ) where T <: AbstractString + )::Vector{T} where T <: AbstractString result = GDAL.gdalratvaluesioasstring(rat.ptr, access, col, startrow, nrows, data) @cplerr result "Failed to $access at column $col starting at $startrow" @@ -253,7 +254,7 @@ Resizes the table to include the indicated number of rows. Newly created rows will be initialized to their default values - \"\" for strings, and zero for numeric fields. """ -function setrowcount!(rat::RasterAttrTable, n::Integer) +function setrowcount!(rat::RasterAttrTable, n::Integer)::RasterAttrTable GDAL.gdalratsetrowcount(rat.ptr, n) return rat end @@ -274,7 +275,7 @@ function createcolumn!( name::AbstractString, fieldtype::GDALRATFieldType, fieldusage::GDALRATFieldUsage - ) + )::RasterAttrTable result = GDAL.gdalratcreatecolumn(rat.ptr, name, fieldtype, fieldusage) @cplerr result "Failed to create column $name" return rat @@ -293,7 +294,11 @@ the table. * `row0min` the lower bound (pixel value) of the first category. * `binsize` the width of each category (in pixel value units). """ -function setlinearbinning!(rat::RasterAttrTable, row0min::Real, binsize::Real) +function setlinearbinning!( + rat::RasterAttrTable, + row0min::Real, + binsize::Real + )::RasterAttrTable result = GDAL.gdalratsetlinearbinning(rat.ptr, row0min, binsize) @cplerr result "Fail to set linear binning: r0min=$row0min, width=$binsize" return rat @@ -308,7 +313,7 @@ Get linear binning information. * `row0min` the lower bound (pixel value) of the first category. * `binsize` the width of each category (in pixel value units). """ -function getlinearbinning(rat::RasterAttrTable) +function getlinearbinning(rat::RasterAttrTable)::Tuple{Cdouble, Cdouble} row0min = Ref{Cdouble}() binsize = Ref{Cdouble}() result = GDAL.gdalratgetlinearbinning(rat.ptr, row0min, binsize) @@ -331,7 +336,10 @@ The raster attribute table must be empty before calling `initializeRAT!()`. The Value fields are set based on the implicit assumption with color tables that entry 0 applies to pixel value 0, 1 to 1, etc. """ -function initializeRAT!(rat::RasterAttrTable, colortable::ColorTable) +function initializeRAT!( + rat::RasterAttrTable, + colortable::ColorTable + )::RasterAttrTable result = GDAL.gdalratinitializefromcolortable(rat.ptr, colortable.ptr) @cplerr result "Failed to initialize RAT from color table" return rat @@ -348,7 +356,7 @@ Translate to a color table. ### Returns the generated color table or `NULL` on failure. """ -toColorTable(rat::RasterAttrTable, n::Integer = -1) = +toColorTable(rat::RasterAttrTable, n::Integer = -1)::ColorTable = ColorTable(GDAL.gdalrattranslatetocolortable(rat.ptr, n)) # """ @@ -371,7 +379,8 @@ the responsibility of the caller to destroy. May fail (return `NULL`) if the attribute table is too large to clone: `(nrow() * ncolumn() > RAT_MAX_ELEM_FOR_CLONE)` """ -unsafe_clone(rat::RasterAttrTable) = RasterAttrTable(GDAL.gdalratclone(rat.ptr)) +unsafe_clone(rat::RasterAttrTable)::RasterAttrTable = + RasterAttrTable(GDAL.gdalratclone(rat.ptr)) """ serializeJSON(rat::RasterAttrTable) @@ -394,5 +403,5 @@ which row in the table applies to the pixel value. The row index is returned. ### Returns The row index or -1 if no row is appropriate. """ -findrowindex(rat::RasterAttrTable, pxvalue::Real) = +findrowindex(rat::RasterAttrTable, pxvalue::Real)::Integer = GDAL.gdalratgetrowofvalue(rat.ptr, pxvalue) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 66465f4e..fd653f2a 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -1,13 +1,13 @@ -function destroy(band::AbstractRasterBand) +function destroy(band::AbstractRasterBand)::Nothing band.ptr = GDALRasterBand(C_NULL) - return band + return nothing end -function destroy(band::IRasterBand) +function destroy(band::IRasterBand)::Nothing band.ptr = GDALRasterBand(C_NULL) band.ownedby = Dataset() - return band + return nothing end """ @@ -27,8 +27,8 @@ Note that the X and Y block sizes don't have to divide the image size evenly, meaning that right and bottom edge blocks may be incomplete. See `ReadBlock()` for an example of code dealing with these issues. """ -function blocksize(band::AbstractRasterBand) - xy = Array{Cint}(undef, 2); x = pointer(xy); y = x + sizeof(Cint) +function blocksize(band::AbstractRasterBand)::Vector{Cint} + xy = Vector{Cint}(undef, 2); x = pointer(xy); y = x + sizeof(Cint) GDAL.gdalgetblocksize(band.ptr, x, y) return xy end @@ -38,28 +38,31 @@ end Fetch the pixel data type for this band. """ -pixeltype(band::AbstractRasterBand{T}) where T = T +function pixeltype(band::AbstractRasterBand{T})::DataType where {T <: Any} + return T +end """ width(band::AbstractRasterBand) Fetch the width in pixels of this band. """ -width(band::AbstractRasterBand) = GDAL.gdalgetrasterbandxsize(band.ptr) +width(band::AbstractRasterBand)::Integer = GDAL.gdalgetrasterbandxsize(band.ptr) """ height(band::AbstractRasterBand) Fetch the height in pixels of this band. """ -height(band::AbstractRasterBand) = GDAL.gdalgetrasterbandysize(band.ptr) +height(band::AbstractRasterBand)::Integer = GDAL.gdalgetrasterbandysize(band.ptr) """ accessflag(band::AbstractRasterBand) Return the access flag (e.g. `OF_ReadOnly` or `OF_Update`) for this band. """ -accessflag(band::AbstractRasterBand) = GDAL.gdalgetrasteraccess(band.ptr) +accessflag(band::AbstractRasterBand)::GDAL.GDALAccess = + GDAL.gdalgetrasteraccess(band.ptr) """ indexof(band::AbstractRasterBand) @@ -69,7 +72,7 @@ Fetch the band number (1+) within its dataset, or 0 if unknown. This method may return a value of 0 to indicate overviews, or free-standing `GDALRasterBand` objects without a relationship to a dataset. """ -indexof(band::AbstractRasterBand) = GDAL.gdalgetbandnumber(band.ptr) +indexof(band::AbstractRasterBand)::Integer = GDAL.gdalgetbandnumber(band.ptr) """ getdataset(band::AbstractRasterBand) @@ -79,7 +82,7 @@ Fetch the handle to its dataset handle, or `NULL` if this cannot be determined. Note that some `RasterBand`s are not considered to be a part of a dataset, such as overviews or other "freestanding" bands. """ -getdataset(band::AbstractRasterBand) = +getdataset(band::AbstractRasterBand)::Dataset = Dataset(GDAL.gdalgetbanddataset(band.ptr)) # ↑ GDAL wrapper checks null by default, but it is a valid result in this case @@ -89,7 +92,8 @@ getdataset(band::AbstractRasterBand) = Return a name for the units of this raster's values. For instance, it might be "m" for an elevation model in meters, or "ft" for feet. """ -getunittype(band::AbstractRasterBand) = GDAL.gdalgetrasterunittype(band.ptr) +getunittype(band::AbstractRasterBand)::String = + GDAL.gdalgetrasterunittype(band.ptr) """ setunittype!(band::AbstractRasterBand, unitstring::AbstractString) @@ -100,7 +104,10 @@ Values should be one of \"\" (the default indicating it is unknown), \"m\" indicating meters, or \"ft\" indicating feet, though other nonstandard values are allowed. """ -function setunittype!(band::AbstractRasterBand, unitstring::AbstractString) +function setunittype!( + band::T, + unitstring::AbstractString + )::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrasterunittype(band.ptr, unitstring) @cplerr result "Failed to set unit type" return band @@ -119,14 +126,15 @@ elevations in `GUInt16` bands with a precision of 0.1, starting from -100. For file formats that don't know this intrinsically, a value of 0 is returned. """ -getoffset(band::AbstractRasterBand) = GDAL.gdalgetrasteroffset(band.ptr, C_NULL) +getoffset(band::AbstractRasterBand)::Real = + GDAL.gdalgetrasteroffset(band.ptr, C_NULL) """ setoffset!(band::AbstractRasterBand, value::Real) Set scaling offset. """ -function setoffset!(band::AbstractRasterBand, value::Real) +function setoffset!(band::T, value::Real)::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrasteroffset(band.ptr, value) @cplerr result "Failed to set scaling offset." return band @@ -146,14 +154,15 @@ and starting from -100. For file formats that don't know this intrinsically a value of one is returned. """ -getscale(band::AbstractRasterBand) = GDAL.gdalgetrasterscale(band.ptr, C_NULL) +getscale(band::AbstractRasterBand)::Real = + GDAL.gdalgetrasterscale(band.ptr, C_NULL) """ setscale!(band::AbstractRasterBand, ratio::Real) Set scaling ratio. """ -function setscale!(band::AbstractRasterBand, ratio::Real) +function setscale!(band::T, ratio::Real)::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrasterscale(band.ptr, ratio) @cplerr result "Failed to set scaling ratio" return band @@ -172,7 +181,7 @@ not be displayed, nor contribute to analysis operations. ### Returns the nodata value for this band or `nothing`. """ -function getnodatavalue(band::AbstractRasterBand) +function getnodatavalue(band::AbstractRasterBand)::Union{Cint, Nothing} # ### Parameters # * `pbSuccess` pointer to a boolean to use to indicate if a value is # actually associated with this layer. May be `NULL` (default). @@ -190,13 +199,16 @@ end Set the no data value for this band. """ -function setnodatavalue!(band::AbstractRasterBand, value::Real) +function setnodatavalue!( + band::T, + value::Real + )::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrasternodatavalue(band.ptr, value) @cplerr result "Could not set nodatavalue" return band end -function deletenodatavalue!(band::AbstractRasterBand) +function deletenodatavalue!(band::T)::T where {T <: AbstractRasterBand} result = GDAL.gdaldeleterasternodatavalue(band.ptr) @cplerr result "Could not delete nodatavalue" return band @@ -207,7 +219,7 @@ end Set the category names for this band. """ -function setcategorynames!(band::AbstractRasterBand, names) +function setcategorynames!(band::T, names)::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrastercategorynames(band.ptr, names) @cplerr result "Failed to set category names" return band @@ -218,21 +230,24 @@ end Fetch the minimum value for this band. """ -minimum(band::AbstractRasterBand) = GDAL.gdalgetrasterminimum(band.ptr, C_NULL) +minimum(band::AbstractRasterBand)::Real = + GDAL.gdalgetrasterminimum(band.ptr, C_NULL) """ maximum(band::AbstractRasterBand) Fetch the maximum value for this band. """ -maximum(band::AbstractRasterBand) = GDAL.gdalgetrastermaximum(band.ptr, C_NULL) +maximum(band::AbstractRasterBand)::Real = + GDAL.gdalgetrastermaximum(band.ptr, C_NULL) """ getdefaultRAT(band::AbstractRasterBand) Fetch default Raster Attribute Table. """ -getdefaultRAT(band::AbstractRasterBand) = GDAL.gdalgetdefaultrat(band.ptr) +getdefaultRAT(band::AbstractRasterBand)::GDAL.GDALRasterAttributeTableH = + GDAL.gdalgetdefaultrat(band.ptr) """ setdefaultRAT!(band::AbstractRasterBand, rat::RasterAttrTable) @@ -243,7 +258,10 @@ Associates a default RAT with the band. If not implemented for the format a CPLE_NotSupported error will be issued. If successful a copy of the RAT is made, the original remains owned by the caller. """ -function setdefaultRAT!(band::AbstractRasterBand, rat::RasterAttrTable) +function setdefaultRAT!( + band::T, + rat::RasterAttrTable + )::T where {T <: AbstractRasterBand} result = GDAL.gdalsetdefaultrat(band.ptr, rat.ptr) @cplerr result "Failed to set default raster attribute table" return band @@ -274,12 +292,12 @@ More options may be supported in the future. * `progressdata` callback data for progress function. """ function copywholeraster!( - source::AbstractRasterBand, + source::T, dest::AbstractRasterBand; options = StringList(C_NULL), progressdata = C_NULL, progressfunc::Function = GDAL.gdaldummyprogress - ) + )::T where {T <: AbstractRasterBand} result = GDAL.gdalrasterbandcopywholeraster(source.ptr, dest.ptr, options, @cplprogress(progressfunc), progressdata) @cplerr result "Failed to copy whole raster" @@ -291,17 +309,18 @@ end Return the number of overview layers available, zero if none. """ -noverview(band::AbstractRasterBand) = GDAL.gdalgetoverviewcount(band.ptr) +noverview(band::AbstractRasterBand)::Integer = + GDAL.gdalgetoverviewcount(band.ptr) """ getoverview(band::IRasterBand, i::Integer) Fetch overview raster band object. """ -getoverview(band::IRasterBand, i::Integer) = +getoverview(band::IRasterBand, i::Integer)::IRasterBand = IRasterBand(GDAL.gdalgetoverview(band.ptr, i), ownedby = band.ownedby) -unsafe_getoverview(band::AbstractRasterBand, i::Integer) = +unsafe_getoverview(band::AbstractRasterBand, i::Integer)::RasterBand = RasterBand(GDAL.gdalgetoverview(band.ptr, i)) """ @@ -315,14 +334,14 @@ number of desired samples to fetch the most reduced overview. The same band as was passed in will be returned if it has not overviews, or if none of the overviews have enough samples. """ -function sampleoverview(band::IRasterBand, nsamples::Integer) +function sampleoverview(band::IRasterBand, nsamples::Integer)::IRasterBand return IRasterBand( GDAL.gdalgetrastersampleoverviewex(band.ptr, UInt64(nsamples)), ownedby = band.ownedby ) end -unsafe_sampleoverview(band::AbstractRasterBand, nsamples::Integer) = +unsafe_sampleoverview(band::AbstractRasterBand, nsamples::Integer)::RasterBand = RasterBand(GDAL.gdalgetrastersampleoverviewex(band.ptr, UInt64(nsamples))) """ @@ -330,7 +349,7 @@ unsafe_sampleoverview(band::AbstractRasterBand, nsamples::Integer) = Color Interpretation value for band """ -getcolorinterp(band::AbstractRasterBand) = +getcolorinterp(band::AbstractRasterBand)::GDAL.GDALColorInterp = GDAL.gdalgetrastercolorinterpretation(band.ptr) """ @@ -338,7 +357,10 @@ getcolorinterp(band::AbstractRasterBand) = Set color interpretation of a band. """ -function setcolorinterp!(band::AbstractRasterBand, color::GDALColorInterp) +function setcolorinterp!( + band::T, + color::GDALColorInterp + )::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrastercolorinterpretation(band.ptr, color) @cplerr result "Failed to set color interpretation" return band @@ -353,7 +375,7 @@ Returns a clone of the color table associated with the band. original color table remains owned by the `GDALRasterBand`, and can't be depended on for long, nor should it ever be modified by the caller.) """ -function unsafe_getcolortable(band::AbstractRasterBand) +function unsafe_getcolortable(band::AbstractRasterBand)::ColorTable result = ColorTable(GDALColorTable(GDAL.gdalgetrastercolortable(band.ptr))) return if result.ptr == C_NULL result @@ -373,13 +395,16 @@ owned by the caller after the call. ### Parameters * `colortable` color table to apply (where supported). """ -function setcolortable!(band::AbstractRasterBand, colortable::ColorTable) +function setcolortable!( + band::T, + colortable::ColorTable + )::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrastercolortable(band.ptr, colortable.ptr) @cplwarn result "CPLError $(result): action is unsupported by the driver" return band end -function clearcolortable!(band::AbstractRasterBand) +function clearcolortable!(band::T)::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrastercolortable(band.ptr, GDALColorTable(C_NULL)) @cplwarn result "CPLError $(result): action is unsupported by the driver" return band @@ -415,12 +440,12 @@ considered as the nodata value and not each value of the triplet independantly per band. """ function regenerateoverviews!( - band::AbstractRasterBand, + band::T, overviewbands::Vector{<:AbstractRasterBand}, resampling::AbstractString = "NEAREST", # progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL - ) + )::T where {T <: AbstractRasterBand} cfunc = @cfunction(GDAL.gdaldummyprogress, Cint, (Cdouble, Cstring, Ptr{Cvoid})) result = GDAL.gdalregenerateoverviews( @@ -458,7 +483,7 @@ NULL terminated array of strings. Raster values without associated names will have an empty string in the returned list. The first entry in the list is for raster values of zero, and so on. """ -getcategorynames(band::AbstractRasterBand) = +getcategorynames(band::AbstractRasterBand)::Vector{String} = GDAL.gdalgetrastercategorynames(band.ptr) """ @@ -466,7 +491,10 @@ getcategorynames(band::AbstractRasterBand) = Set the category names for this band. """ -function setcategorynames!(band::AbstractRasterBand, names::Vector{String}) +function setcategorynames!( + band::T, + names::Vector{String} + )::T where {T <: AbstractRasterBand} result = GDAL.gdalsetrastercategorynames(band.ptr, names) @cplerr result "Failed to set category names for this band" return band @@ -500,10 +528,10 @@ allows the imaginary component of a complex constant value to be specified. * `imagvalue`: Imaginary component of fill value, defaults to zero """ function fillraster!( - band::AbstractRasterBand, + band::T, realvalue::Real, imagvalue::Real = 0 - ) + )::T where {T <: AbstractRasterBand} result = GDAL.gdalfillraster(band.ptr, realvalue, imagvalue) @cplerr result "Failed to fill raster band" return band @@ -540,10 +568,10 @@ See also: http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask ### Returns a valid mask band. """ -getmaskband(band::IRasterBand) = +getmaskband(band::IRasterBand)::IRasterBand = IRasterBand(GDAL.gdalgetmaskband(band.ptr), ownedby = band.ownedby) -unsafe_getmaskband(band::AbstractRasterBand) = +unsafe_getmaskband(band::AbstractRasterBand)::RasterBand = RasterBand(GDAL.gdalgetmaskband(band.ptr)) """ @@ -586,7 +614,7 @@ See also: http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask ### Returns a valid mask band. """ -maskflags(band::AbstractRasterBand) = GDAL.gdalgetmaskflags(band.ptr) +maskflags(band::AbstractRasterBand)::Cint = GDAL.gdalgetmaskflags(band.ptr) """ @@ -604,7 +632,12 @@ named tuple with the following fields: A named tuple with unpacked mask flags """ -function maskflaginfo(band::AbstractRasterBand) +function maskflaginfo( + band::AbstractRasterBand + )::NamedTuple{ + (:all_valid, :per_dataset, :alpha, :nodata), + NTuple{4, Bool} + } flags = maskflags(band) return ( all_valid = !iszero(flags & 0x01), @@ -632,7 +665,10 @@ invalidated by `CreateMaskBand()`. So you have to call `GetMaskBand()` again. See also: http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask """ -function createmaskband!(band::AbstractRasterBand, nflags::Integer) +function createmaskband!( + band::T, + nflags::Integer + )::T where {T <: AbstractRasterBand} result = GDAL.gdalcreatemaskband(band.ptr, nflags) @cplerr result "Failed to create mask band" return band diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 0be8ce7c..24b7cc71 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -67,13 +67,13 @@ function rasterio! end function rasterio!( dataset::AbstractDataset, - buffer::Array{<:Real, 3}, + buffer::T, bands, access::GDALRWFlag = GDAL.GF_Read, pxspace::Integer = 0, linespace::Integer = 0, bandspace::Integer = 0 - ) + )::T where {T <: Array{<:Real, 3}} rasterio!(dataset, buffer, bands, 0, 0, size(buffer, 1), size(buffer, 2), access, pxspace, linespace, bandspace) return buffer @@ -81,7 +81,7 @@ end function rasterio!( dataset::AbstractDataset, - buffer::Array{<:Real, 3}, + buffer::T, bands, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, @@ -89,7 +89,7 @@ function rasterio!( pxspace::Integer = 0, linespace::Integer = 0, bandspace::Integer = 0 - ) + )::T where {T <: Array{<:Real, 3}} xsize = cols[end] - cols[1] + 1; xsize < 0 && error("invalid window width") ysize = rows[end] - rows[1] + 1; ysize < 0 && error("invalid window height") rasterio!(dataset, buffer, bands, cols[1], rows[1], xsize, ysize, access, @@ -99,11 +99,11 @@ end function rasterio!( rasterband::AbstractRasterBand, - buffer::Matrix{<:Real}, + buffer::T, access::GDALRWFlag = GDAL.GF_Read, pxspace::Integer = 0, linespace::Integer = 0 - ) + )::T where {T <: Matrix{<:Real}} rasterio!(rasterband, buffer, 0, 0, width(rasterband), height(rasterband), access, pxspace, linespace) return buffer @@ -111,13 +111,13 @@ end function rasterio!( rasterband::AbstractRasterBand, - buffer::Matrix{<:Real}, + buffer::T, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, access::GDALRWFlag = GDAL.GF_Read, pxspace::Integer = 0, linespace::Integer = 0 - ) + )::T where {T <: Matrix{<:Real}} xsize = length(cols); xsize < 1 && error("invalid window width") ysize = length(rows); ysize < 1 && error("invalid window height") rasterio!(rasterband, buffer, cols[1]-1, rows[1]-1, xsize, ysize, access, @@ -125,27 +125,32 @@ function rasterio!( return buffer end -read!(rb::AbstractRasterBand, buffer::Matrix{<:Real}) = +function read!( + rb::AbstractRasterBand, + buffer::T + )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, GDAL.GF_Read) + return buffer +end function read!( rb::AbstractRasterBand, - buffer::Matrix{<:Real}, + buffer::T, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize) return buffer end function read!( rb::AbstractRasterBand, - buffer::Matrix{<:Real}, + buffer::T, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, rows, cols) return buffer end @@ -159,8 +164,8 @@ function read( yoffset::Integer, xsize::Integer, ysize::Integer - ) - buffer = Array{pixeltype(rb)}(undef, xsize, ysize) + )::Matrix{pixeltype(rb)} + buffer = Matrix{pixeltype(rb)}(undef, xsize, ysize) rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize) return buffer end @@ -169,54 +174,64 @@ function read( rb::AbstractRasterBand, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) - buffer = Array{pixeltype(rb)}(undef, length(cols), length(rows)) + )::Matrix{pixeltype(rb)} + buffer = Matrix{pixeltype(rb)}(undef, length(cols), length(rows)) rasterio!(rb, buffer, rows, cols) return buffer end -function write!(rb::AbstractRasterBand, buffer::Matrix{<:Real}) +function write!( + rb::AbstractRasterBand, + buffer::T + )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, GDAL.GF_Write) return buffer end function write!( rb::AbstractRasterBand, - buffer::Matrix{<:Real}, + buffer::T, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize, GDAL.GF_Write) return buffer end function write!( rb::AbstractRasterBand, - buffer::Matrix{<:Real}, + buffer::T, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, rows, cols, GDAL.GF_Write) return buffer end -function read!(dataset::AbstractDataset, buffer::Matrix{<:Real}, i::Integer) +function read!( + dataset::AbstractDataset, + buffer::T, + i::Integer + )::T where {T <: Matrix{<:Real}} read!(getband(dataset, i), buffer) return buffer end function read!( dataset::AbstractDataset, - buffer::Array{<:Real, 3}, + buffer::T, indices - ) + )::T where {T <: Array{<:Real, 3}} rasterio!(dataset, buffer, indices, GDAL.GF_Read) return buffer end -function read!(dataset::AbstractDataset, buffer::Array{<:Real, 3}) +function read!( + dataset::AbstractDataset, + buffer::T + )::T where {T <: Array{<:Real, 3}} nband = nraster(dataset) @assert size(buffer, 3) == nband rasterio!(dataset, buffer, collect(Cint, 1:nband), GDAL.GF_Read) @@ -225,48 +240,48 @@ end function read!( dataset::AbstractDataset, - buffer::Matrix{<:Real}, + buffer::T, i::Integer, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::T where {T <: Matrix{<:Real}} read!(getband(dataset, i), buffer, xoffset, yoffset, xsize, ysize) return buffer end function read!( dataset::AbstractDataset, - buffer::Array{<:Real, 3}, + buffer::T, indices, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::T where {T <: Array{<:Real, 3}} rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize) return buffer end function read!( dataset::AbstractDataset, - buffer::Matrix{<:Real}, + buffer::T, i::Integer, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::T where {T <: Matrix{<:Real}} read!(getband(dataset, i), buffer, rows, cols) return buffer end function read!( dataset::AbstractDataset, - buffer::Array{<:Real, 3}, + buffer::T, indices, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::T where {T <: Array{<:Real, 3}} rasterio!(dataset, buffer, indices, rows, cols) return buffer end @@ -276,14 +291,14 @@ read(dataset::AbstractDataset, i::Integer) = read(getband(dataset, i)) function read( dataset::AbstractDataset, indices - ) + )::Array{pixeltype(getband(dataset, indices[1]))} buffer = Array{pixeltype(getband(dataset, indices[1]))}(undef, width(dataset), height(dataset), length(indices)) rasterio!(dataset, buffer, indices) return buffer end -function read(dataset::AbstractDataset) +function read(dataset::AbstractDataset)::Array{pixeltype(getband(dataset, 1))} buffer = Array{pixeltype(getband(dataset, 1))}(undef, width(dataset), height(dataset), nraster(dataset)) read!(dataset, buffer) @@ -309,7 +324,7 @@ function read( yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::Array{pixeltype(getband(dataset, indices[1]))} buffer = Array{pixeltype(getband(dataset, indices[1]))}(undef, xsize, ysize, length(indices)) rasterio!(dataset, buffer, indices, xsize, ysize, xoffset, yoffset) @@ -331,72 +346,76 @@ function read( indices, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::Array{pixeltype(getband(dataset, indices[1]))} buffer = Array{pixeltype(getband(dataset, indices[1]))}(undef, length(cols), length(rows), length(indices)) rasterio!(dataset, buffer, indices, rows, cols) return buffer end -function write!(dataset::AbstractDataset, buffer::Matrix{<:Real}, i::Integer) +function write!( + dataset::T, + buffer::Matrix{<:Real}, + i::Integer + )::T where {T <: AbstractDataset} write!(getband(dataset, i), buffer) return dataset end function write!( - dataset::AbstractDataset, + dataset::T, buffer::Array{<:Real, 3}, indices - ) + )::T where {T <: AbstractDataset} rasterio!(dataset, buffer, indices, GDAL.GF_Write) return dataset end function write!( - dataset::AbstractDataset, + dataset::T, buffer::Matrix{<:Real}, i::Integer, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::T where {T <: AbstractDataset} write!(getband(dataset, i), buffer, xoffset, yoffset, xsize, ysize) return dataset end function write!( - dataset::AbstractDataset, + dataset::T, buffer::Array{<:Real, 3}, indices, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::T where {T <: AbstractDataset} rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize, GDAL.GF_Write) return dataset end function write!( - dataset::AbstractDataset, + dataset::T, buffer::Matrix{<:Real}, i::Integer, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::T where {T <: AbstractDataset} write!(getband(dataset, i), buffer, rows, cols) return dataset end function write!( - dataset::AbstractDataset, + dataset::T, buffer::Array{<:Real, 3}, indices, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::T where {T <: AbstractDataset} rasterio!(dataset, buffer, indices, rows, cols, GDAL.GF_Write) return dataset end @@ -416,7 +435,7 @@ for (T,GT) in _GDALTYPE linespace::Integer = 0, bandspace::Integer = 0, extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) - ) + )::Array{$T, 3} # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg # structure with additional arguments to specify resampling and # progress callback, or `NULL` for default behaviour. The @@ -478,7 +497,7 @@ for (T,GT) in _GDALTYPE pxspace::Integer = 0, linespace::Integer = 0, extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) - ) + )::Matrix{$T} # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg # structure with additional arguments to specify resampling and # progress callback, or `NULL` for default behaviour. The @@ -522,8 +541,8 @@ function readblock!( rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, - buffer - ) + buffer::T + )::T where {T <: Any} result = GDAL.gdalreadblock(rb.ptr, xoffset, yoffset, buffer) @cplerr result "Failed to read block at ($xoffset,$yoffset)" return buffer @@ -549,11 +568,11 @@ access use RasterIO(). GetRasterDataType(). """ function writeblock!( - rb::AbstractRasterBand, + rb::T, xoffset::Integer, yoffset::Integer, buffer - ) + )::T where {T <: AbstractRasterBand} result = GDAL.gdalwriteblock(rb.ptr, xoffset, yoffset, buffer) @cplerr result "Failed to write block at ($xoffset,$yoffset)" return rb From cc82bf3f988a83b1d0dbeb1e05f6ac534384b229 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 19:39:27 -0700 Subject: [PATCH 016/169] [Breaking] Deprecate serializeJSON It returns a Ptr{Void}, and feels sufficiently unsafe for people to work with. (I initially thought it might return a String.) We don't have any tests for it, and I haven't seen widespread use for it through GDAL, so it's safer to deprecate this function until I've thought through how to make it accessible to users. --- src/raster/rasterattributetable.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 918357da..63818997 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -382,12 +382,12 @@ attribute table is too large to clone: unsafe_clone(rat::RasterAttrTable)::RasterAttrTable = RasterAttrTable(GDAL.gdalratclone(rat.ptr)) -""" - serializeJSON(rat::RasterAttrTable) - -Serialize Raster Attribute Table in Json format. -""" -serializeJSON(rat::RasterAttrTable) = GDAL.gdalratserializejson(rat.ptr) +# """ +# serializeJSON(rat::RasterAttrTable) +# +# Serialize Raster Attribute Table in Json format. +# """ +# serializeJSON(rat::RasterAttrTable) = GDAL.gdalratserializejson(rat.ptr) """ findrowindex(rat::RasterAttrTable, pxvalue::Real) From 0a6755dadcd16dd42c33a5d40e5aea687906e684 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 20:07:11 -0700 Subject: [PATCH 017/169] [Breaking] _dataset_type -> pixeltype We also use it in the rasterio functions for safe behavior, rather than assuming that the bands all have the same pixeltype. --- src/dataset.jl | 106 +++++++++++++++++++++++++++-------------- src/raster/array.jl | 18 +------ src/raster/rasterio.jl | 20 ++++---- 3 files changed, 82 insertions(+), 62 deletions(-) diff --git a/src/dataset.jl b/src/dataset.jl index b20971a4..ab2a55e0 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -90,7 +90,7 @@ function unsafe_copy( options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL - ) + )::Dataset return Dataset(GDAL.gdalcreatecopy( driver.ptr, filename, @@ -147,7 +147,7 @@ function copy( options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL - ) + )::IDataset return IDataset(GDAL.gdalcreatecopy( driver.ptr, filename, @@ -164,8 +164,13 @@ end Writes the dataset to the designated filename. """ -function write(dataset::AbstractDataset, filename::AbstractString; kwargs...) - return destroy(unsafe_copy(dataset, filename = filename; kwargs...)) +function write( + dataset::AbstractDataset, + filename::AbstractString; + kwargs... + )::Nothing + destroy(unsafe_copy(dataset, filename = filename; kwargs...)) + return nothing end """ @@ -200,7 +205,7 @@ function unsafe_create( nbands::Integer = 0, dtype::DataType = Any, options = StringList(C_NULL) - ) + )::Dataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, gdaltype(dtype), options) return Dataset(result) @@ -214,7 +219,7 @@ function unsafe_create( nbands::Integer = 0, dtype::DataType = Any, options = StringList(C_NULL) - ) + )::Dataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, gdaltype(dtype), options) return Dataset(result) @@ -259,7 +264,7 @@ function create( nbands::Integer = 0, dtype::DataType = Any, options = StringList(C_NULL) - ) + )::IDataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, gdaltype(dtype), options) return IDataset(result) @@ -273,7 +278,7 @@ function create( nbands::Integer = 0, dtype::DataType = Any, options = StringList(C_NULL) - ) + )::IDataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, gdaltype(dtype), options) return IDataset(result) @@ -343,7 +348,7 @@ function unsafe_read( alloweddrivers = StringList(C_NULL), options = StringList(C_NULL), siblingfiles = StringList(C_NULL) - ) + )::Dataset result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, siblingfiles) return Dataset(result) @@ -390,13 +395,13 @@ function read( alloweddrivers = StringList(C_NULL), options = StringList(C_NULL), siblingfiles = StringList(C_NULL) - ) + )::IDataset result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, siblingfiles) return IDataset(result) end -unsafe_update(filename::AbstractString; flags = OF_Update, kwargs...) = +unsafe_update(filename::AbstractString; flags = OF_Update, kwargs...)::Dataset = unsafe_read(filename; flags = OF_Update | flags, kwargs...) """ @@ -404,35 +409,37 @@ unsafe_update(filename::AbstractString; flags = OF_Update, kwargs...) = Fetch raster width in pixels. """ -width(dataset::AbstractDataset) = GDAL.gdalgetrasterxsize(dataset.ptr) +width(dataset::AbstractDataset)::Integer = GDAL.gdalgetrasterxsize(dataset.ptr) """ height(dataset::AbstractDataset) Fetch raster height in pixels. """ -height(dataset::AbstractDataset) = GDAL.gdalgetrasterysize(dataset.ptr) +height(dataset::AbstractDataset)::Integer = GDAL.gdalgetrasterysize(dataset.ptr) """ nraster(dataset::AbstractDataset) Fetch the number of raster bands on this dataset. """ -nraster(dataset::AbstractDataset) = GDAL.gdalgetrastercount(dataset.ptr) +nraster(dataset::AbstractDataset)::Integer = + GDAL.gdalgetrastercount(dataset.ptr) """ nlayer(dataset::AbstractDataset) Fetch the number of feature layers on this dataset. """ -nlayer(dataset::AbstractDataset) = GDAL.gdaldatasetgetlayercount(dataset.ptr) +nlayer(dataset::AbstractDataset)::Integer = + GDAL.gdaldatasetgetlayercount(dataset.ptr) """ getdriver(dataset::AbstractDataset) Fetch the driver that the dataset was created with """ -getdriver(dataset::AbstractDataset) = +getdriver(dataset::AbstractDataset)::Driver = Driver(GDAL.gdalgetdatasetdriver(dataset.ptr)) """ @@ -448,7 +455,8 @@ list is owned by the caller and should be deallocated with `CSLDestroy()`. The returned filenames will normally be relative or absolute paths depending on the path used to originally open the dataset. The strings will be UTF-8 encoded """ -filelist(dataset::AbstractDataset) = GDAL.gdalgetfilelist(dataset.ptr) +filelist(dataset::AbstractDataset)::Vector{String} = + GDAL.gdalgetfilelist(dataset.ptr) """ getlayer(dataset::AbstractDataset, i::Integer) @@ -458,10 +466,10 @@ Fetch the layer at index `i` (between `0` and `nlayer(dataset)-1`) The returned layer remains owned by the GDALDataset and should not be deleted by the application. """ -getlayer(dataset::AbstractDataset, i::Integer) = +getlayer(dataset::AbstractDataset, i::Integer)::IFeatureLayer = IFeatureLayer(GDAL.gdaldatasetgetlayer(dataset.ptr, i), ownedby = dataset) -unsafe_getlayer(dataset::AbstractDataset, i::Integer) = +unsafe_getlayer(dataset::AbstractDataset, i::Integer)::FeatureLayer = FeatureLayer(GDAL.gdaldatasetgetlayer(dataset.ptr, i)) """ @@ -474,14 +482,14 @@ Table, which supports only one layer, a name is not needed. The returned layer remains owned by the GDALDataset and should not be deleted by the application. """ -function getlayer(dataset::AbstractDataset, name::AbstractString) +function getlayer(dataset::AbstractDataset, name::AbstractString)::IFeatureLayer return IFeatureLayer( GDAL.gdaldatasetgetlayerbyname(dataset.ptr, name), ownedby = dataset ) end -unsafe_getlayer(dataset::AbstractDataset, name::AbstractString) = +unsafe_getlayer(dataset::AbstractDataset, name::AbstractString)::FeatureLayer = FeatureLayer(GDAL.gdaldatasetgetlayerbyname(dataset.ptr, name)) """ @@ -493,7 +501,7 @@ Delete the indicated layer (at index i; between `0` to `nlayer()-1`) `OGRERR_NONE` on success, or `OGRERR_UNSUPPORTED_OPERATION` if deleting layers is not supported for this dataset. """ -function deletelayer!(dataset::AbstractDataset, i::Integer) +function deletelayer!(dataset::T, i::Integer)::T where {T <: AbstractDataset} result = GDAL.gdaldatasetdeletelayer(dataset.ptr, i) @ogrerr result "Failed to delete layer" return dataset @@ -525,7 +533,7 @@ the strings themselves to avoid misspelling. * `dataset`: the dataset handle. * `capability`: the capability to test. """ -testcapability(dataset::AbstractDataset, capability::AbstractString) = +testcapability(dataset::AbstractDataset, capability::AbstractString)::Bool = Bool(GDAL.gdaldatasettestcapability(dataset.ptr, capability)) function listcapability( @@ -536,7 +544,7 @@ function listcapability( GDAL.ODsCCurveGeometries, GDAL.ODsCTransactions, GDAL.ODsCEmulatedTransactions) - ) + )::Dict{String, Bool} return Dict{String, Bool}( c => testcapability(dataset, c) for c in capabilities ) @@ -578,7 +586,7 @@ function unsafe_executesql( query::AbstractString; dialect::AbstractString = "", spatialfilter::Geometry = Geometry(GDALGeometry(C_NULL)) - ) + )::FeatureLayer return FeatureLayer(GDALFeatureLayer(GDAL.gdaldatasetexecutesql( dataset.ptr, query, @@ -600,7 +608,10 @@ before destroying the GDALDataset may cause errors. * `dataset`: the dataset handle. * `layer`: the result of a previous ExecuteSQL() call. """ -function releaseresultset(dataset::AbstractDataset, layer::FeatureLayer) +function releaseresultset( + dataset::AbstractDataset, + layer::FeatureLayer + )::Nothing GDAL.gdaldatasetreleaseresultset(dataset.ptr, layer.ptr) destroy(layer) return nothing @@ -645,22 +656,28 @@ transformation to projection coordinates. ### Returns `CE_None` on success, or `CE_Failure` if no transform can be fetched. """ -function getgeotransform!(dataset::AbstractDataset, transform::Vector{Cdouble}) +function getgeotransform!( + dataset::AbstractDataset, + transform::Vector{Cdouble} + )::Vector{Cdouble} @assert length(transform) == 6 result = GDAL.gdalgetgeotransform(dataset.ptr, pointer(transform)) @cplerr result "Failed to get geotransform" return transform end -getgeotransform(dataset::AbstractDataset) = - getgeotransform!(dataset, Array{Cdouble}(undef, 6)) +getgeotransform(dataset::AbstractDataset)::Vector{Cdouble} = + getgeotransform!(dataset, Vector{Cdouble}(undef, 6)) """ setgeotransform!(dataset::AbstractDataset, transform::Vector{Cdouble}) Set the affine transformation coefficients. """ -function setgeotransform!(dataset::AbstractDataset, transform::Vector{Cdouble}) +function setgeotransform!( + dataset::T, + transform::Vector{Cdouble} + )::T where {T <: AbstractDataset} @assert length(transform) == 6 result = GDAL.gdalsetgeotransform(dataset.ptr, pointer(transform)) @cplerr result "Failed to transform raster dataset" @@ -672,7 +689,7 @@ end Get number of GCPs for this dataset. Zero if there are none. """ -ngcp(dataset::AbstractDataset) = GDAL.gdalgetgcpcount(dataset.ptr) +ngcp(dataset::AbstractDataset)::Integer = GDAL.gdalgetgcpcount(dataset.ptr) """ getproj(dataset::AbstractDataset) @@ -683,14 +700,18 @@ It should be suitable for use with the OGRSpatialReference class. When a projection definition is not available an empty (but not `NULL`) string is returned. """ -getproj(dataset::AbstractDataset) = GDAL.gdalgetprojectionref(dataset.ptr) +getproj(dataset::AbstractDataset)::String = + GDAL.gdalgetprojectionref(dataset.ptr) """ setproj!(dataset::AbstractDataset, projstring::AbstractString) Set the projection reference string for this dataset. """ -function setproj!(dataset::AbstractDataset, projstring::AbstractString) +function setproj!( + dataset::T, + projstring::AbstractString + )::T where {T <: AbstractDataset} result = GDAL.gdalsetprojection(dataset.ptr, projstring) @cplerr result "Could not set projection" return dataset @@ -717,13 +738,13 @@ returned, and CPLGetLastErrorNo() will return CPLE_NotSupported. * `progressdata` application data to pass to the progress function. """ function buildoverviews!( - dataset::AbstractDataset, + dataset::T, overviewlist::Vector{Cint}; bandlist::Vector{Cint} = Cint[], resampling::AbstractString = "NEAREST", progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL - ) + )::T where {T <: AbstractDataset} result = GDAL.gdalbuildoverviews( dataset.ptr, resampling, @@ -738,8 +759,21 @@ function buildoverviews!( return dataset end -function destroy(dataset::AbstractDataset) +function destroy(dataset::AbstractDataset)::Nothing GDAL.gdalclose(dataset.ptr) dataset.ptr = C_NULL return nothing end + +""" + pixeltype(ds::AbstractDataset) + +Tries to determine a common dataset type for all the bands +in a raster dataset. +""" +function pixeltype(ds::AbstractDataset)::DataType + alldatatypes = map(1:nraster(ds)) do i + pixeltype(getband(ds, i)) + end + return reduce(promote_type, alldatatypes) +end diff --git a/src/raster/array.jl b/src/raster/array.jl index 24f25c4a..487fbd87 100644 --- a/src/raster/array.jl +++ b/src/raster/array.jl @@ -28,12 +28,12 @@ end function RasterDataset( ds::AbstractDataset - )::RasterDataset{_dataset_type(ds), typeof(ds)} + )::RasterDataset{pixeltype(ds), typeof(ds)} if iszero(nraster(ds)) throw(ArgumentError("The Dataset does not contain any raster bands")) end s = _common_size(ds) - return RasterDataset{_dataset_type(ds), typeof(ds)}(ds, s) + return RasterDataset{pixeltype(ds), typeof(ds)}(ds, s) end # Forward a few functions @@ -76,20 +76,6 @@ function copywholeraster!( return dest end -""" - _dataset_type(ds::AbstractDataset) - -Tries to determine a common dataset type for all the bands -in a raster dataset. -""" -function _dataset_type(ds::AbstractDataset)::DataType - alldatatypes = map(1:nraster(ds)) do i - b = getband(ds, i) - pixeltype(b) - end - return reduce(promote_type, alldatatypes) -end - """ _common_size(ds::AbstractDataset) diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 24b7cc71..5da41a2d 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -291,15 +291,15 @@ read(dataset::AbstractDataset, i::Integer) = read(getband(dataset, i)) function read( dataset::AbstractDataset, indices - )::Array{pixeltype(getband(dataset, indices[1]))} - buffer = Array{pixeltype(getband(dataset, indices[1]))}(undef, + )::Array{pixeltype(dataset), 3} + buffer = Array{pixeltype(dataset)}(undef, width(dataset), height(dataset), length(indices)) rasterio!(dataset, buffer, indices) return buffer end -function read(dataset::AbstractDataset)::Array{pixeltype(getband(dataset, 1))} - buffer = Array{pixeltype(getband(dataset, 1))}(undef, width(dataset), +function read(dataset::AbstractDataset)::Array{pixeltype(dataset), 3} + buffer = Array{pixeltype(dataset)}(undef, width(dataset), height(dataset), nraster(dataset)) read!(dataset, buffer) return buffer @@ -312,7 +312,7 @@ function read( yoffset::Integer, xsize::Integer, ysize::Integer - ) + )::Matrix{pixeltype(dataset)} buffer = read(getband(dataset, i), xoffset, yoffset, xsize, ysize) return buffer end @@ -324,8 +324,8 @@ function read( yoffset::Integer, xsize::Integer, ysize::Integer - )::Array{pixeltype(getband(dataset, indices[1]))} - buffer = Array{pixeltype(getband(dataset, indices[1]))}(undef, + )::Array{pixeltype(dataset), 3} + buffer = Array{pixeltype(dataset)}(undef, xsize, ysize, length(indices)) rasterio!(dataset, buffer, indices, xsize, ysize, xoffset, yoffset) return buffer @@ -336,7 +336,7 @@ function read( i::Integer, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - ) + )::Matrix{pixeltype(dataset)} buffer = read(getband(dataset, i), rows, cols) return buffer end @@ -346,8 +346,8 @@ function read( indices, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - )::Array{pixeltype(getband(dataset, indices[1]))} - buffer = Array{pixeltype(getband(dataset, indices[1]))}(undef, + )::Array{pixeltype(dataset), 3} + buffer = Array{pixeltype(dataset), 3}(undef, length(cols), length(rows), length(indices)) rasterio!(dataset, buffer, indices, rows, cols) return buffer From 8e7c37dde71a3fa2d640f9c805af2376858ef8f0 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 22:10:54 -0700 Subject: [PATCH 018/169] Annotate with return types --- src/context.jl | 8 +- src/driver.jl | 60 ++++++++++----- src/gcp.jl | 21 ++++-- src/geointerface.jl | 5 +- src/spatialref.jl | 174 ++++++++++++++++++++++++++++++-------------- src/types.jl | 15 ++-- 6 files changed, 188 insertions(+), 95 deletions(-) diff --git a/src/context.jl b/src/context.jl index 8e39923b..e0dc76a9 100644 --- a/src/context.jl +++ b/src/context.jl @@ -100,14 +100,14 @@ to the layer. format driver. """ function addfielddefn!( - layer::AbstractFeatureLayer, + layer::T, name::AbstractString, etype::OGRFieldType; nwidth::Integer = 0, nprecision::Integer = 0, justify::OGRJustification = GDAL.OJUndefined, approx::Bool = false - ) + )::T where {T <: AbstractFeatureLayer} fielddefn = unsafe_createfielddefn(name, etype) setparams!(fielddefn, name, etype, nwidth = nwidth, nprecision = nprecision, justify = justify) @@ -166,11 +166,11 @@ to the layer. slightly different form depending on the limitations of the driver. """ function writegeomdefn!( - layer::AbstractFeatureLayer, + layer::T, name::AbstractString, etype::WKBGeometryType; approx::Bool = false - ) + )::T where {T <: AbstractFeatureLayer} geomdefn = unsafe_creategeomdefn(name, etype) addgeomdefn!(layer, geomdefn) destroy(geomdefn) diff --git a/src/driver.jl b/src/driver.jl index 1f39071e..c167aaaf 100644 --- a/src/driver.jl +++ b/src/driver.jl @@ -3,14 +3,14 @@ Fetch driver by index. """ -getdriver(i::Integer) = Driver(GDAL.gdalgetdriver(i)) +getdriver(i::Integer)::Driver = Driver(GDAL.gdalgetdriver(i)) """ getdriver(name::AbstractString) Fetch a driver based on the short name (such as `GTiff`). """ -getdriver(name::AbstractString) = Driver(GDAL.gdalgetdriverbyname(name)) +getdriver(name::AbstractString)::Driver = Driver(GDAL.gdalgetdriverbyname(name)) """ destroy(drv::Driver) @@ -21,7 +21,7 @@ This is roughly equivalent to deleting the driver, but is guaranteed to take place in the GDAL heap. It is important this that function not be called on a driver that is registered with the `GDALDriverManager`. """ -function destroy(drv::Driver) +function destroy(drv::Driver)::Nothing GDAL.gdaldestroydriver(drv.ptr) drv.ptr = C_NULL return nothing @@ -32,51 +32,57 @@ end Register a driver for use. """ -register(drv::Driver) = GDAL.gdalregisterdriver(drv.ptr) +function register(drv::Driver)::Nothing + GDAL.gdalregisterdriver(drv.ptr) + return nothing +end """ deregister(drv::Driver) Deregister the passed driver. """ -deregister(drv::Driver) = GDAL.gdalderegisterdriver(drv.ptr) +function deregister(drv::Driver)::Nothing + GDAL.gdalderegisterdriver(drv.ptr) + return nothing +end """ options(drv::Driver) Return the list of creation options of the driver [an XML string]. """ -options(drv::Driver) = GDAL.gdalgetdrivercreationoptionlist(drv.ptr) +options(drv::Driver)::String = GDAL.gdalgetdrivercreationoptionlist(drv.ptr) -driveroptions(name::AbstractString) = options(getdriver(name)) +driveroptions(name::AbstractString)::String = options(getdriver(name)) """ shortname(drv::Driver) Return the short name of a driver (e.g. `GTiff`). """ -shortname(drv::Driver) = GDAL.gdalgetdrivershortname(drv.ptr) +shortname(drv::Driver)::String = GDAL.gdalgetdrivershortname(drv.ptr) """ longname(drv::Driver) Return the long name of a driver (e.g. `GeoTIFF`), or empty string. """ -longname(drv::Driver) = GDAL.gdalgetdriverlongname(drv.ptr) +longname(drv::Driver)::String = GDAL.gdalgetdriverlongname(drv.ptr) """ ndriver() Fetch the number of registered drivers. """ -ndriver() = GDAL.gdalgetdrivercount() +ndriver()::Integer = GDAL.gdalgetdrivercount() """ listdrivers() Returns a listing of all registered drivers. """ -listdrivers() = Dict{String,String}([ +listdrivers()::Dict{String,String} = Dict{String,String}([ shortname(getdriver(i)) => longname(getdriver(i)) for i in 0:(ndriver()-1) ]) @@ -90,7 +96,7 @@ by invoking the Identify method of each registered `GDALDriver` in turn. The first driver that successful identifies the file name will be returned. If all drivers fail then `NULL` is returned. """ -identifydriver(filename::AbstractString) = +identifydriver(filename::AbstractString)::Driver = Driver(GDAL.gdalidentifydriver(filename, C_NULL)) """ @@ -121,8 +127,12 @@ in the list of creation options are compatible with the capabilities declared by the `GDAL_DMD_CREATIONOPTIONLIST` metadata item. In case of incompatibility a (non fatal) warning will be emited and ``false`` will be returned. """ -validate(drv::Driver, options::Vector{T}) where {T <: AbstractString} = - Bool(GDAL.gdalvalidatecreationoptions(drv.ptr, options)) +function validate( + drv::Driver, + options::Vector{T} + )::Bool where {T <: AbstractString} + return Bool(GDAL.gdalvalidatecreationoptions(drv.ptr, options)) +end """ copyfiles(drv::Driver, new::AbstractString, old::AbstractString) @@ -132,14 +142,24 @@ Copy all the files associated with a dataset. """ function copyfiles end -function copyfiles(drv::Driver, new::AbstractString, old::AbstractString) +function copyfiles( + drv::Driver, + new::AbstractString, + old::AbstractString + )::Nothing result = GDAL.gdalcopydatasetfiles(drv.ptr, new, old) @cplerr result "Failed to copy dataset files" - return result + return nothing end -copyfiles(drvname::AbstractString, new::AbstractString, old::AbstractString) = +function copyfiles( + drvname::AbstractString, + new::AbstractString, + old::AbstractString + )::Nothing copyfiles(getdriver(drvname), new, old) + return nothing +end """ extensions() @@ -147,8 +167,8 @@ copyfiles(drvname::AbstractString, new::AbstractString, old::AbstractString) = Returns a `Dict{String,String}` of all of the file extensions that can be read by GDAL, with their respective drivers' `shortname`s. """ -function extensions() - extdict = Dict{String,String}() +function extensions()::Dict{String, String} + extdict = Dict{String, String}() for i in 1:ndriver() driver = getdriver(i) if !(driver.ptr == C_NULL) @@ -168,7 +188,7 @@ Returns a driver shortname that matches the filename extension. So `extensiondriver("/my/file.tif") == "GTiff"`. """ -function extensiondriver(filename::AbstractString) +function extensiondriver(filename::AbstractString)::String split = splitext(filename) extensiondict = extensions() ext = split[2] == "" ? split[1] : split[2] diff --git a/src/gcp.jl b/src/gcp.jl index 6fbe11b4..e72e1618 100644 --- a/src/gcp.jl +++ b/src/gcp.jl @@ -13,13 +13,16 @@ converts the equation from being pixel to geo to being geo to pixel. ### Returns `gt_out` """ -function invgeotransform!(gt_in::Vector{Cdouble}, gt_out::Vector{Cdouble}) +function invgeotransform!( + gt_in::Vector{Cdouble}, + gt_out::Vector{Cdouble} + )::Vector{Cdouble} result = Bool(GDAL.gdalinvgeotransform(pointer(gt_in), pointer(gt_out))) result || error("Geotransform coefficients is uninvertable") return gt_out end -invgeotransform(gt_in::Vector{Cdouble}) = +invgeotransform(gt_in::Vector{Cdouble})::Vector{Cdouble} = invgeotransform!(gt_in, Array{Cdouble}(undef, 6)) """ @@ -43,8 +46,8 @@ function applygeotransform( geotransform::Vector{Cdouble}, pixel::Cdouble, line::Cdouble - ) - geo_xy = Array{Cdouble}(undef, 2) + )::Vector{Cdouble} + geo_xy = Vector{Cdouble}(undef, 2) geo_x = pointer(geo_xy) geo_y = geo_x + sizeof(Cdouble) GDAL.gdalapplygeotransform(pointer(geotransform), pixel, line, geo_x, geo_y) @@ -70,10 +73,14 @@ function composegeotransform!( gt1::Vector{Cdouble}, gt2::Vector{Cdouble}, gtout::Vector{Cdouble} - ) + )::Vector{Cdouble} GDAL.gdalcomposegeotransform(pointer(gt1), pointer(gt2), pointer(gtout)) return gtout end -composegeotransform(gt1::Vector{Cdouble}, gt2::Vector{Cdouble}) = - composegeotransform!(gt1, gt2, Array{Cdouble}(undef, 6)) +function composegeotransform( + gt1::Vector{Cdouble}, + gt2::Vector{Cdouble} + )::Vector{Cdouble} + return composegeotransform!(gt1, gt2, Vector{Cdouble}(undef, 6)) +end diff --git a/src/geointerface.jl b/src/geointerface.jl index da4845b4..c0d63aae 100644 --- a/src/geointerface.jl +++ b/src/geointerface.jl @@ -11,7 +11,7 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), collectiontypes = (wkbGeometryCollection, wkbGeometryCollection25D, wkbGeometryCollectionM, wkbGeometryCollectionZM) - function GeoInterface.geotype(g::AbstractGeometry) + function GeoInterface.geotype(g::AbstractGeometry)::Symbol gtype = getgeomtype(g) return if gtype in pointtypes :Point @@ -66,5 +66,4 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), ] end end - -end \ No newline at end of file +end diff --git a/src/spatialref.jl b/src/spatialref.jl index 5889505e..028e0229 100644 --- a/src/spatialref.jl +++ b/src/spatialref.jl @@ -9,10 +9,10 @@ returning an `ArchGDAL.AbstractSpatialRef`. axis ordering in any actions done with the crs. `:compliant` (the default) will use axis ordering compliant with the relevant CRS authority. """ -importCRS(x::GFT.GeoFormat; kwargs...) = +importCRS(x::GFT.GeoFormat; kwargs...)::ISpatialRef = importCRS!(newspatialref(; kwargs...), x) -unsafe_importCRS(x::GFT.GeoFormat; kwargs...) = +unsafe_importCRS(x::GFT.GeoFormat; kwargs...)::SpatialRef = importCRS!(unsafe_newspatialref(; kwargs...), x) """ @@ -22,18 +22,44 @@ Import a coordinate reference system from a `GeoFormat` into the spatial ref. """ function importCRS! end -importCRS!(spref::AbstractSpatialRef, x::GFT.EPSG) = +function importCRS!(spref::T, x::GFT.EPSG)::T where {T <: AbstractSpatialRef} importEPSG!(spref, GFT.val(x)) -importCRS!(spref::AbstractSpatialRef, x::GFT.AbstractWellKnownText) = + return spref +end + +function importCRS!( + spref::T, + x::GFT.AbstractWellKnownText + )::T where {T <: AbstractSpatialRef} importWKT!(spref, GFT.val(x)) -importCRS!(spref::AbstractSpatialRef, x::GFT.ESRIWellKnownText) = + return spref +end + +function importCRS!( + spref::T, + x::GFT.ESRIWellKnownText + )::T where {T <: AbstractSpatialRef} importESRI!(spref, GFT.val(x)) -importCRS!(spref::AbstractSpatialRef, x::GFT.ProjString) = + return spref +end + +function importCRS!( + spref::T, + x::GFT.ProjString + )::T where {T <: AbstractSpatialRef} importPROJ4!(spref, GFT.val(x)) -importCRS!(spref::AbstractSpatialRef, x::GFT.GML) = + return spref +end + +function importCRS!(spref::T, x::GFT.GML)::T where {T <: AbstractSpatialRef} importXML!(spref, GFT.val(x)) -importCRS!(spref::AbstractSpatialRef, x::GFT.KML) = + return spref +end + +function importCRS!(spref::T, x::GFT.KML)::T where {T <: AbstractSpatialRef} importCRS!(spref, GFT.EPSG(4326)) + return spref +end """ reproject(points, sourceproj::GeoFormat, destproj::GeoFormat; @@ -66,8 +92,14 @@ julia> ArchGDAL.reproject( [-2.663928675953517e6, 1.56208905951487e7] ``` """ -reproject(coord, sourcecrs::GFT.GeoFormat, targetcrs::Nothing; kwargs...) = - coord +function reproject( + coord::T, + sourcecrs::GFT.GeoFormat, + targetcrs::Nothing; + kwargs... + )::T where {T <: Any} + return coord +end # These should be better integrated with geometry packages or follow a standard const ReprojectCoord = Union{ @@ -181,20 +213,27 @@ newspatialref(wkt::AbstractString = ""; order=:compliant) = unsafe_newspatialref(wkt::AbstractString = ""; order=:compliant) = maybesetaxisorder!(SpatialRef(GDAL.osrnewspatialreference(wkt)), order) -function maybesetaxisorder!(sr::AbstractSpatialRef, order) +function maybesetaxisorder!( + spref::T, + order::Symbol + )::T where {T <: AbstractSpatialRef} if order == :trad - GDAL.osrsetaxismappingstrategy(sr.ptr, GDAL.OAMS_TRADITIONAL_GIS_ORDER) + GDAL.osrsetaxismappingstrategy( + spref.ptr, + GDAL.OAMS_TRADITIONAL_GIS_ORDER + ) elseif order != :compliant throw(ArgumentError( "order $order is not supported. Use :trad or :compliant" )) end - return sr + return spref end -function destroy(spref::AbstractSpatialRef) +function destroy(spref::AbstractSpatialRef)::Nothing GDAL.osrdestroyspatialreference(spref.ptr) spref.ptr = C_NULL + return nothing end """ @@ -202,7 +241,7 @@ end Makes a clone of the Spatial Reference System. May return NULL. """ -function clone(spref::AbstractSpatialRef) +function clone(spref::AbstractSpatialRef)::ISpatialRef return if spref.ptr == C_NULL ISpatialRef() else @@ -210,7 +249,7 @@ function clone(spref::AbstractSpatialRef) end end -function unsafe_clone(spref::AbstractSpatialRef) +function unsafe_clone(spref::AbstractSpatialRef)::SpatialRef return if spref.ptr == C_NULL SpatialRef() else @@ -243,7 +282,7 @@ These support files are normally searched for in /usr/local/share/gdal or in the directory identified by the GDAL_DATA configuration option. See CPLFindFile() for details. """ -function importEPSG!(spref::AbstractSpatialRef, code::Integer) +function importEPSG!(spref::T, code::Integer)::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromepsg(spref.ptr, code) @ogrerr result "Failed to initialize SRS based on EPSG" return spref @@ -259,10 +298,10 @@ Construct a Spatial Reference System from its EPSG GCS or PCS code. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importEPSG(code::Integer; kwargs...) = +importEPSG(code::Integer; kwargs...)::ISpatialRef = importEPSG!(newspatialref(; kwargs...), code) -unsafe_importEPSG(code::Integer; kwargs...) = +unsafe_importEPSG(code::Integer; kwargs...)::SpatialRef = importEPSG!(unsafe_newspatialref(; kwargs...), code) """ @@ -277,7 +316,10 @@ are also a few projected coordinate systems that use northing/easting order contrary to typical GIS use). See `importFromEPSG()` for more details on operation of this method. """ -function importEPSGA!(spref::AbstractSpatialRef, code::Integer) +function importEPSGA!( + spref::T, + code::Integer + )::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromepsga(spref.ptr, code) @ogrerr result "Failed to initializ SRS based on EPSGA" return spref @@ -300,10 +342,10 @@ details on operation of this method. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importEPSGA(code::Integer; kwargs...) = +importEPSGA(code::Integer; kwargs...)::ISpatialRef = importEPSGA!(newspatialref(; kwargs...), code) -unsafe_importEPSGA(code::Integer; kwargs...) = +unsafe_importEPSGA(code::Integer; kwargs...)::SpatialRef = importEPSGA!(unsafe_newspatialref(; kwargs...), code) """ @@ -316,7 +358,10 @@ contents of the passed WKT string. Only as much of the input string as needed to construct this SRS is consumed from the input string, and the input string pointer is then updated to point to the remaining (unused) input. """ -function importWKT!(spref::AbstractSpatialRef, wktstr::AbstractString) +function importWKT!( + spref::T, + wktstr::AbstractString + )::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromwkt(spref.ptr, [wktstr]) @ogrerr result "Failed to initialize SRS based on WKT string" return spref @@ -332,10 +377,10 @@ Create SRS from its WKT string. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importWKT(wktstr::AbstractString; kwargs...) = +importWKT(wktstr::AbstractString; kwargs...)::ISpatialRef = newspatialref(wktstr; kwargs...) -unsafe_importWKT(wktstr::AbstractString; kwargs...) = +unsafe_importWKT(wktstr::AbstractString; kwargs...)::SpatialRef = unsafe_newspatialref(wktstr; kwargs...) """ @@ -360,7 +405,10 @@ back to PROJ.4 format\". For example: `\"+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext\"` """ -function importPROJ4!(spref::AbstractSpatialRef, projstr::AbstractString) +function importPROJ4!( + spref::T, + projstr::AbstractString + )::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromproj4(spref.ptr, projstr) @ogrerr result "Failed to initialize SRS based on PROJ4 string" return spref @@ -376,10 +424,10 @@ Create SRS from its PROJ.4 string. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importPROJ4(projstr::AbstractString; kwargs...) = +importPROJ4(projstr::AbstractString; kwargs...)::ISpatialRef = importPROJ4!(newspatialref(; kwargs...), projstr) -unsafe_importPROJ4(projstr::AbstractString; kwargs...) = +unsafe_importPROJ4(projstr::AbstractString; kwargs...)::SpatialRef = importPROJ4!(unsafe_newspatialref(; kwargs...), projstr) """ @@ -404,7 +452,10 @@ At this time there is no equivalent `exportToESRI()` method. Writing old style and `exportToWkt()` methods can be used to generate output suitable to write to new style (Arc 8) .prj files. """ -function importESRI!(spref::AbstractSpatialRef, esristr::AbstractString) +function importESRI!( + spref::T, + esristr::AbstractString + )::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromesri(spref.ptr, [esristr]) @ogrerr result "Failed to initialize SRS based on ESRI string" return spref @@ -418,10 +469,10 @@ Create SRS from its ESRI .prj format(s). Passing the keyword argument `order=:compliant` or `order=:trad` will set the mapping strategy to return compliant axis order or traditional lon/lat order. """ -importESRI(esristr::AbstractString; kwargs...) = +importESRI(esristr::AbstractString; kwargs...)::ISpatialRef = importESRI!(newspatialref(; kwargs...), esristr) -unsafe_importESRI(esristr::AbstractString; kwargs...) = +unsafe_importESRI(esristr::AbstractString; kwargs...)::SpatialRef = importESRI!(unsafe_newspatialref(; kwargs...), esristr) """ @@ -429,7 +480,10 @@ unsafe_importESRI(esristr::AbstractString; kwargs...) = Import SRS from XML format (GML only currently). """ -function importXML!(spref::AbstractSpatialRef, xmlstr::AbstractString) +function importXML!( + spref::T, + xmlstr::AbstractString + )::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromxml(spref.ptr, xmlstr) @ogrerr result "Failed to initialize SRS based on XML string" return spref @@ -448,10 +502,10 @@ mapping strategy to return compliant axis order or traditional lon/lat order. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importXML(xmlstr::AbstractString; kwargs...) = +importXML(xmlstr::AbstractString; kwargs...)::ISpatialRef = importXML!(newspatialref(; kwargs...), xmlstr) -unsafe_importXML(xmlstr::AbstractString; kwargs...) = +unsafe_importXML(xmlstr::AbstractString; kwargs...)::SpatialRef = importXML!(unsafe_newspatialref(; kwargs...), xmlstr) """ @@ -462,7 +516,10 @@ Set spatial reference from a URL. This method will download the spatial reference at a given URL and feed it into SetFromUserInput for you. """ -function importURL!(spref::AbstractSpatialRef, url::AbstractString) +function importURL!( + spref::T, + url::AbstractString + )::T where {T <: AbstractSpatialRef} result = GDAL.osrimportfromurl(spref.ptr, url) @ogrerr result "Failed to initialize SRS from URL" return spref @@ -481,10 +538,10 @@ SetFromUserInput for you. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importURL(url::AbstractString; kwargs...) = +importURL(url::AbstractString; kwargs...)::ISpatialRef = importURL!(newspatialref(; kwargs...), url) -unsafe_importURL(url::AbstractString; kwargs...) = +unsafe_importURL(url::AbstractString; kwargs...)::SpatialRef = importURL!(unsafe_newspatialref(; kwargs...), url) """ @@ -492,7 +549,7 @@ unsafe_importURL(url::AbstractString; kwargs...) = Convert this SRS into WKT format. """ -function toWKT(spref::AbstractSpatialRef) +function toWKT(spref::AbstractSpatialRef)::String wktptr = Ref{Cstring}() result = GDAL.osrexporttowkt(spref.ptr, wktptr) @ogrerr result "Failed to convert this SRS into WKT format" @@ -509,7 +566,7 @@ Convert this SRS into a nicely formatted WKT string for display to a person. * `simplify`: `true` if the `AXIS`, `AUTHORITY` and `EXTENSION` nodes should be stripped off. """ -function toWKT(spref::AbstractSpatialRef, simplify::Bool) +function toWKT(spref::AbstractSpatialRef, simplify::Bool)::String wktptr = Ref{Cstring}() result = GDAL.osrexporttoprettywkt(spref.ptr, wktptr, simplify) @ogrerr result "Failed to convert this SRS into pretty WKT" @@ -521,7 +578,7 @@ end Export coordinate system in PROJ.4 format. """ -function toPROJ4(spref::AbstractSpatialRef) +function toPROJ4(spref::AbstractSpatialRef)::String projptr = Ref{Cstring}() result = GDAL.osrexporttoproj4(spref.ptr, projptr) @ogrerr result "Failed to export this SRS to PROJ.4 format" @@ -537,7 +594,7 @@ Converts the loaded coordinate reference system into XML format to the extent possible. LOCAL_CS coordinate systems are not translatable. An empty string will be returned along with OGRERR_NONE. """ -function toXML(spref::AbstractSpatialRef) +function toXML(spref::AbstractSpatialRef)::String xmlptr = Ref{Cstring}() result = GDAL.osrexporttoxml(spref.ptr, xmlptr, C_NULL) @ogrerr result "Failed to convert this SRS into XML" @@ -549,7 +606,7 @@ end Export coordinate system in Mapinfo style CoordSys format. """ -function toMICoordSys(spref::AbstractSpatialRef) +function toMICoordSys(spref::AbstractSpatialRef)::String ptr = Ref{Cstring}() result = GDAL.osrexporttomicoordsys(spref.ptr, ptr) @ogrerr result "Failed to convert this SRS into XML" @@ -566,7 +623,7 @@ closely map onto the ESRI concept of WKT format. This includes renaming a variety of projections and arguments, and stripping out nodes note recognised by ESRI (like AUTHORITY and AXIS). """ -function morphtoESRI!(spref::AbstractSpatialRef) +function morphtoESRI!(spref::T)::T where {T <: AbstractSpatialRef} result = GDAL.osrmorphtoesri(spref.ptr) @ogrerr result "Failed to convert in place to ESRI WKT format" return spref @@ -600,7 +657,7 @@ of the following (`TOWGS84` recommended for proper datum shift calculations) `importFromEPSG(n)`, using `EPSG` code `n` corresponding to the existing `GEOGCS`. Does not impact `PROJCS` values. """ -function morphfromESRI!(spref::AbstractSpatialRef) +function morphfromESRI!(spref::T)::T where {T <: AbstractSpatialRef} result = GDAL.osrmorphfromesri(spref.ptr) @ogrerr result "Failed to convert in place from ESRI WKT format" return spref @@ -622,16 +679,19 @@ the value otherwise the zeroth child will be assigned the value. out if you just want to force creation of the intermediate path. """ function setattrvalue!( - spref::AbstractSpatialRef, + spref::T, path::AbstractString, value::AbstractString - ) + )::T where {T <: AbstractSpatialRef} result = GDAL.osrsetattrvalue(spref.ptr, path, value) @ogrerr result "Failed to set attribute path to value" return spref end -function setattrvalue!(spref::AbstractSpatialRef, path::AbstractString) +function setattrvalue!( + spref::T, + path::AbstractString + )::T where {T <: AbstractSpatialRef} result = GDAL.osrsetattrvalue(spref.ptr, path, C_NULL) @ogrerr result "Failed to set attribute path" return spref @@ -652,10 +712,15 @@ Parameters `i` the child of the node to fetch (zero based). Returns -the requested value, or NULL if it fails for any reason. +the requested value, or `nothing` if it fails for any reason. """ -getattrvalue(spref::AbstractSpatialRef, name::AbstractString, i::Integer) = - GDAL.osrgetattrvalue(spref.ptr, name, i) +function getattrvalue( + spref::AbstractSpatialRef, + name::AbstractString, + i::Integer + )::Union{String, Nothing} + return GDAL.osrgetattrvalue(spref.ptr, name, i) +end """ unsafe_createcoordtrans(source::AbstractSpatialRef, @@ -673,15 +738,16 @@ NULL on failure or a ready to use transformation object. function unsafe_createcoordtrans( source::AbstractSpatialRef, target::AbstractSpatialRef - ) + )::CoordTransform return CoordTransform(GDAL.octnewcoordinatetransformation(source.ptr, target.ptr)) end "OGRCoordinateTransformation destructor." -function destroy(obj::CoordTransform) +function destroy(obj::CoordTransform)::Nothing GDAL.octdestroycoordinatetransformation(obj.ptr) - return obj.ptr = C_NULL + obj.ptr = C_NULL + return nothing end """ @@ -702,7 +768,7 @@ function transform!( yvertices::Vector{Cdouble}, zvertices::Vector{Cdouble}, obj::CoordTransform - ) + )::Bool # The method TransformEx() allows extended success information to be # captured indicating which points failed to transform. n = length(xvertices) diff --git a/src/types.jl b/src/types.jl index abfb15de..1bf3e63a 100644 --- a/src/types.jl +++ b/src/types.jl @@ -207,17 +207,17 @@ mutable struct ColorTable end "return the corresponding `DataType` in julia" -datatype(gt::GDALDataType) = get(_JLTYPE, gt) do +datatype(gt::GDALDataType)::DataType = get(_JLTYPE, gt) do error("Unknown GDALDataType: $gt") end "return the corresponding `GDAL.GDALDataType`" -gdaltype(dt::DataType) = get(_GDALTYPE, dt) do +gdaltype(dt::DataType)::GDAL.GDALDataType = get(_GDALTYPE, dt) do error("Unknown DataType: $dt") end "return the corresponding `DataType` in julia" -datatype(ft::OGRFieldType) = get(_FIELDTYPE, ft) do +datatype(ft::OGRFieldType)::DataType = get(_FIELDTYPE, ft) do error("Unknown OGRFieldType: $ft") end @@ -321,23 +321,24 @@ import Base.| """ typesize(dt::GDALDataType) -Get data type size in bits. +Get the number of bits or zero if it is not recognised. """ -typesize(dt::GDALDataType) = GDAL.gdalgetdatatypesize(dt) +typesize(dt::GDALDataType)::Integer = GDAL.gdalgetdatatypesize(dt) """ typename(dt::GDALDataType) name (string) corresponding to GDAL data type. """ -typename(dt::GDALDataType) = GDAL.gdalgetdatatypename(dt) +typename(dt::GDALDataType)::String = GDAL.gdalgetdatatypename(dt) """ gettype(name::AbstractString) Returns GDAL data type by symbolic name. """ -gettype(name::AbstractString) = GDAL.gdalgetdatatypebyname(name) +gettype(name::AbstractString)::GDAL.GDALDataType = + GDAL.gdalgetdatatypebyname(name) """ typeunion(dt1::GDALDataType, dt2::GDALDataType) From f96f2c286ee662649fb6fcdc276db933da459469 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 22:16:23 -0700 Subject: [PATCH 019/169] Fix the implementation of src/tables.jl We should be using the interface based on https://tables.juliadata.org/stable/#Tables.AbstractRow-1, rather than overriding base methods. Along the way, I realize that the methods for getfield(feature, name) and getgeom(feature, name) do not handle the case when the name is invalid, so I've added implementations where they are missing, and return nothing/C_NULL for existing implementations. I'll use coverage results later to see where to augment with tests. --- src/ogr/feature.jl | 44 ++++++++++++++++++--- src/tables.jl | 79 ++++++++++++++++++++++---------------- test/test_ospy_examples.jl | 12 +++--- test/test_tables.jl | 34 ++-------------- 4 files changed, 95 insertions(+), 74 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 1fa7c9dd..7584eed1 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -391,8 +391,14 @@ function getfield(feature::Feature, i::Integer) end end -getfield(feature::Feature, name::Union{AbstractString, Symbol}) = - getfield(feature, findfieldindex(feature, name)) +function getfield(feature::Feature, name::Union{AbstractString, Symbol}) + i = findfieldindex(feature, name) + return if i == -1 + nothing + else + getfield(feature, i) + end +end """ setfield!(feature::Feature, i::Integer, value) @@ -532,7 +538,7 @@ function getgeomdefn(feature::Feature, i::Integer)::IGeomFieldDefnView end """ - findgeomindex(feature::Feature, name::AbstractString="") + findgeomindex(feature::Feature, name::Union{AbstractString, Symbol} = "") Fetch the geometry field index given geometry field name. @@ -546,8 +552,12 @@ the geometry field index, or -1 if no matching geometry field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetGeomFieldIndex()` method. """ -findgeomindex(feature::Feature, name::AbstractString = "")::Integer = - GDAL.ogr_f_getgeomfieldindex(feature.ptr, name) +function findgeomindex( + feature::Feature, + name::Union{AbstractString, Symbol} = "" + )::Integer + return GDAL.ogr_f_getgeomfieldindex(feature.ptr, name) +end """ getgeom(feature::Feature, i::Integer) @@ -576,6 +586,30 @@ function unsafe_getgeom(feature::Feature, i::Integer)::Geometry end end +function getgeom( + feature::Feature, + name::Union{AbstractString, Symbol} = "" + )::IGeometry + i = findgeomindex(feature, name) + return if i == -1 + IGeometry() + else + getgeom(feature, i) + end +end + +function unsafe_getgeom( + feature::Feature, + name::Union{AbstractString, Symbol} = "" + )::Geometry + i = findgeomindex(feature, name) + return if i == -1 + Geometry() + else + unsafe_getgeom(feature, i) + end +end + """ setgeom!(feature::Feature, i::Integer, geom::AbstractGeometry) diff --git a/src/tables.jl b/src/tables.jl index 2dfed7eb..58dde05b 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -1,60 +1,71 @@ """ -Constructs `Table` out of `FeatureLayer`, where every row is a `Feature` consisting of Geometry and attributes. -``` -ArchGDAL.Table(T::Union{IFeatureLayer, FeatureLayer}) -``` +A tabular representation of a `FeatureLayer` + +Every row is a `Feature` consisting of Geometry and attributes. """ -struct Table{T<:Union{IFeatureLayer, FeatureLayer}} +struct Table{T <: AbstractFeatureLayer} layer::T end -getlayer(t::Table) = Base.getfield(t, :layer) - -function Tables.schema(layer::AbstractFeatureLayer) +function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema field_names, geom_names, featuredefn, fielddefns = schema_names(layer) ngeom = ArchGDAL.ngeom(featuredefn) geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) field_types = (datatype(gettype(fielddefn)) for fielddefn in fielddefns) geom_types = (IGeometry for i in 1:ngeom) - Tables.Schema((field_names..., geom_names...), (field_types..., geom_types...)) + Tables.Schema( + (field_names..., geom_names...), + (field_types..., geom_types...) + ) end -Tables.istable(::Type{<:Table}) = true -Tables.rowaccess(::Type{<:Table}) = true -Tables.rows(t::Table) = t +Tables.istable(::Type{<:Table})::Bool = true +Tables.rowaccess(::Type{<:Table})::Bool = true + +function Tables.rows(t::Table{T})::T where {T <: AbstractFeatureLayer} + return t.layer +end -function Base.iterate(t::Table, st = 0) - layer = getlayer(t) - st >= nfeature(layer) && return nothing - if iszero(st) - resetreading!(layer) +function Tables.getcolumn(row::Feature, i::Int) + if i > nfield(row) + return getgeom(row, i - nfield(row) - 1) + elseif i > 0 + return getfield(row, i - 1) + else + return nothing end - return nextnamedtuple(layer), st + 1 end -function Base.getindex(t::Table, idx::Integer) - layer = getlayer(t) - setnextbyindex!(layer, idx-1) - return nextnamedtuple(layer) +function Tables.getcolumn(row::Feature, name::Symbol) + field = getfield(row, name) + if !isnothing(field) + return field + end + geom = getgeom(row, name) + if geom.ptr != C_NULL + return geom + end + return nothing end -Base.IteratorSize(::Type{<:Table}) = Base.HasLength() -Base.size(t::Table) = nfeature(getlayer(t)) -Base.length(t::Table) = size(t) -Base.IteratorEltype(::Type{<:Table}) = Base.HasEltype() -Base.propertynames(t::Table) = Tables.schema(getlayer(t)).names -Base.getproperty(t::Table, s::Symbol) = [getproperty(row, s) for row in t] +function Tables.columnnames( + row::Feature + )::NTuple{nfield(row) + ngeom(row), String} + field_names, geom_names = schema_names(layer) + return (field_names..., geom_names...) +end """ Returns the feature row of a layer as a `NamedTuple` -Calling it iteratively will work similar to `nextfeature` i.e. give the consecutive feature as `NamedTuple` +Calling it iteratively will work similar to `nextfeature` i.e. give the +consecutive feature as `NamedTuple`. """ -function nextnamedtuple(layer::IFeatureLayer) +function nextnamedtuple(layer::IFeatureLayer)::NamedTuple field_names, geom_names = schema_names(layer) return nextfeature(layer) do feature prop = (getfield(feature, name) for name in field_names) - geom = (getgeom(feature, idx-1) for idx in 1:length(geom_names)) + geom = (getgeom(feature, i - 1) for i in 1:length(geom_names)) NamedTuple{(field_names..., geom_names...)}((prop..., geom...)) end end @@ -63,11 +74,13 @@ function schema_names(layer::AbstractFeatureLayer) featuredefn = layerdefn(layer) fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(layer)-1) field_names = (Symbol(getname(fielddefn)) for fielddefn in fielddefns) - geom_names = (Symbol(getname(getgeomdefn(featuredefn, i-1))) for i in 1:ngeom(layer)) + geom_names = ( + Symbol(getname(getgeomdefn(featuredefn, i - 1))) for i in 1:ngeom(layer) + ) return (field_names, geom_names, featuredefn, fielddefns) end function Base.show(io::IO, t::Table) - println(io, "Table with $(nfeature(getlayer(t))) features") + println(io, "Table with $(nfeature(t.layer)) features") end Base.show(io::IO, ::MIME"text/plain", t::Table) = show(io, t) diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index 8c6c8feb..f14c5dc7 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -23,7 +23,7 @@ function copyfields(fromlayer, tolayer) # to too larger number with respect to field width fwidth = AG.getwidth(fd) if fwidth != 0 - AG.setwidth!(fd, fwidth+1) + AG.setwidth!(fd, fwidth + 1) end end AG.createfield!(tolayer, fd) end @@ -80,7 +80,7 @@ end @testset "Homework 1" begin AG.read("ospy/data1/sites.shp") do input #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw1a.py - for (i,feature) in enumerate(AG.getlayer(input, 0)) + for (i, feature) in enumerate(AG.getlayer(input, 0)) id = AG.getfield(feature, 0); cover = AG.getfield(feature, 1) (x,y) = AG.getpoint(AG.getgeom(feature, 0), 0) @test id == i @@ -122,13 +122,13 @@ AG.read("ospy/data1/sites.shp") do input # version 2 AG.create(AG.getdriver("MEMORY")) do output - AG.executesql(input, """SELECT * FROM sites + AG.executesql(input, """SELECT id, cover FROM sites WHERE cover = 'trees' """) do results @test sprint(print, results) == """ Layer: sites - Geometry 0 (_ogr_geometry_): [wkbPoint], POINT (449959.840851...), ... - Field 0 (ID): [OFTInteger], 2, 6, 9, 14, 19, 20, 22, 26, 34, 36, 41 - Field 1 (COVER): [OFTString], trees, trees, trees, trees, trees, trees, ... + Geometry 0 (): [wkbPoint], POINT (449959.840851...), ... + Field 0 (id): [OFTInteger], 2, 6, 9, 14, 19, 20, 22, 26, 34, 36, 41 + Field 1 (cover): [OFTString], trees, trees, trees, trees, trees, trees, ... """ AG.copy(results, name = "hw1b", dataset = output) end diff --git a/test/test_tables.jl b/test/test_tables.jl index 512d61d1..38a40f44 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -19,46 +19,20 @@ using Tables gt2 = AG.Table(layer2) @testset "read layer to table" begin - @test AG.getlayer(gt) === layer - @test AG.getlayer(gt1) === layer1 - @test AG.getlayer(gt2) === layer2 @test sprint(print, gt) == "Table with 4 features\n" @test sprint(print, gt1) == "Table with 2 features\n" @test sprint(print, gt2) == "Table with 9 features\n" end @testset "Tables methods" begin - @test Tables.schema(layer).names == propertynames(gt) - @test Tables.schema(layer1).names == propertynames(gt1) - @test Tables.schema(layer2).names == propertynames(gt2) + @test Tables.schema(layer1) == Tables.Schema( + (:id, :zoom, :location, :point, :linestring), + (String, String, String, AG.IGeometry, AG.IGeometry) + ) @test Tables.istable(AG.Table) == true - @test Tables.rows(gt) == AG.Table(layer) - @test Tables.rows(gt1) == AG.Table(layer1) - @test Tables.rows(gt2) == AG.Table(layer2) end @testset "Misc. methods" begin - @test Base.size(gt) == 4 - @test Base.size(gt1) == 2 - @test Base.size(gt2) == 9 - @test Base.length(gt) == 4 - @test Base.length(gt1) == 2 - @test Base.length(gt2) == 9 - @test Base.IteratorSize(typeof(gt)) == Base.HasLength() - @test Base.IteratorEltype(typeof(gt1)) == Base.HasEltype() - @test propertynames(gt) == (:FID, :pointname, Symbol("")) - @test propertynames(gt1) == (:id, :zoom, :location, :point, :linestring) - @test propertynames(gt2) == (:id, :zoom, :location, :point, :linestring) - @test getproperty(gt, :FID) == [iterate(gt, i)[1].FID for i in 0:size(gt)-1] - @test getproperty(gt1, :zoom) == [iterate(gt1, i)[1].zoom for i in 0:size(gt1)-1] - @test sprint(print, gt2[5].linestring) == sprint(print, gt2[3].point) - @test sprint(print, gt2[9].linestring) == sprint(print, gt2[7].point) - @test collect(findall(x->x=="missing", getproperty(gt2, i)) for i in [:id, :zoom, :location]) == [[6], [4, 8], [3, 7, 8]] - @test iterate(gt, 5) === nothing - @test iterate(gt1, 3) === nothing - @test typeof([getindex(gt, i) for i in 1:size(gt)]) == typeof([iterate(gt, i)[1] for i in 0:size(gt)-1]) - @test typeof([getindex(gt1, i) for i in 1:size(gt1)]) == typeof([iterate(gt1, i)[1] for i in 0:size(gt1)-1]) - AG.resetreading!(layer) AG.resetreading!(layer1) From cea217fc6df551764d192543128cad345cbbcf3f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 22:26:38 -0700 Subject: [PATCH 020/169] Annotate with return types --- src/types.jl | 25 +++++++++++++++---------- src/utilities.jl | 18 +++++++++--------- src/utils.jl | 32 +++++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/types.jl b/src/types.jl index 1bf3e63a..e5149c30 100644 --- a/src/types.jl +++ b/src/types.jl @@ -345,68 +345,73 @@ gettype(name::AbstractString)::GDAL.GDALDataType = Return the smallest data type that can fully express both input data types. """ -typeunion(dt1::GDALDataType, dt2::GDALDataType) = GDAL.gdaldatatypeunion(dt1, dt2) +typeunion(dt1::GDALDataType, dt2::GDALDataType)::GDAL.GDALDataType = + GDAL.gdaldatatypeunion(dt1, dt2) """ iscomplex(dtype::GDALDataType) `true` if `dtype` is one of `GDT_{CInt16|CInt32|CFloat32|CFloat64}.` """ -iscomplex(dtype::GDALDataType) = Bool(GDAL.gdaldatatypeiscomplex(dtype)) +iscomplex(dtype::GDALDataType)::Bool = Bool(GDAL.gdaldatatypeiscomplex(dtype)) """ getname(dtype::GDALAsyncStatusType) Get name of AsyncStatus data type. """ -getname(dtype::GDALAsyncStatusType) = GDAL.gdalgetasyncstatustypename(dtype) +getname(dtype::GDALAsyncStatusType)::String = + GDAL.gdalgetasyncstatustypename(dtype) """ asyncstatustype(name::AbstractString) Get AsyncStatusType by symbolic name. """ -asyncstatustype(name::AbstractString) = GDAL.gdalgetasyncstatustypebyname(name) +asyncstatustype(name::AbstractString)::GDAL.GDALAsyncStatusType = + GDAL.gdalgetasyncstatustypebyname(name) """ getname(obj::GDALColorInterp) Return name (string) corresponding to color interpretation. """ -getname(obj::GDALColorInterp) = GDAL.gdalgetcolorinterpretationname(obj) +getname(obj::GDALColorInterp)::String = GDAL.gdalgetcolorinterpretationname(obj) """ colorinterp(name::AbstractString) Get color interpretation corresponding to the given symbolic name. """ -colorinterp(name::AbstractString) = GDAL.gdalgetcolorinterpretationbyname(name) +colorinterp(name::AbstractString)::GDAL.GDALColorInterp = + GDAL.gdalgetcolorinterpretationbyname(name) """ getname(obj::GDALPaletteInterp) Get name of palette interpretation. """ -getname(obj::GDALPaletteInterp) = GDAL.gdalgetpaletteinterpretationname(obj) +getname(obj::GDALPaletteInterp)::String = + GDAL.gdalgetpaletteinterpretationname(obj) """ getname(obj::OGRFieldType) Fetch human readable name for a field type. """ -getname(obj::OGRFieldType) = GDAL.ogr_getfieldtypename(obj) +getname(obj::OGRFieldType)::String = GDAL.ogr_getfieldtypename(obj) """ getname(obj::OGRFieldSubType) Fetch human readable name for a field subtype. """ -getname(obj::OGRFieldSubType) = GDAL.ogr_getfieldsubtypename(obj) +getname(obj::OGRFieldSubType)::String = GDAL.ogr_getfieldsubtypename(obj) """ arecompatible(dtype::OGRFieldType, subtype::OGRFieldSubType) Return if type and subtype are compatible. """ -arecompatible(dtype::OGRFieldType, subtype::OGRFieldSubType) = +arecompatible(dtype::OGRFieldType, subtype::OGRFieldSubType)::Bool = Bool(GDAL.ogr_aretypesubtypecompatible(dtype, subtype)) diff --git a/src/utilities.jl b/src/utilities.jl index 01240b6e..210c0f8c 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -11,7 +11,7 @@ List various information about a GDAL supported raster dataset. ### Returns String corresponding to the information about the raster dataset. """ -function gdalinfo(dataset::Dataset, options = String[]) +function gdalinfo(dataset::Dataset, options = String[])::String options = GDAL.gdalinfooptionsnew(options, C_NULL) result = GDAL.gdalinfo(dataset.ptr, options) GDAL.gdalinfooptionsfree(options) @@ -35,7 +35,7 @@ function unsafe_gdaltranslate( dataset::Dataset, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdaltranslateoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdaltranslate(dest, dataset.ptr, options, usage_error) @@ -60,7 +60,7 @@ function unsafe_gdalwarp( datasets::Vector{Dataset}, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdalwarpappoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalwarp(dest, C_NULL, @@ -86,7 +86,7 @@ function unsafe_gdalvectortranslate( datasets::Vector{Dataset}, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdalvectortranslateoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalvectortranslate(dest, C_NULL, length(datasets), @@ -120,7 +120,7 @@ function unsafe_gdaldem( options = String[]; dest = "/vsimem/tmp", colorfile = C_NULL - ) + )::Dataset if processing == "color-relief" @assert colorfile != C_NULL end @@ -149,7 +149,7 @@ function unsafe_gdalnearblack( dataset::Dataset, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdalnearblackoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalnearblack(dest, C_NULL, dataset.ptr, options, usage_error) @@ -174,7 +174,7 @@ function unsafe_gdalgrid( dataset::Dataset, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdalgridoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalgrid(dest, dataset.ptr, options, usage_error) @@ -199,7 +199,7 @@ function unsafe_gdalrasterize( dataset::Dataset, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdalrasterizeoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalrasterize(dest, C_NULL, dataset.ptr, options, usage_error) @@ -224,7 +224,7 @@ function unsafe_gdalbuildvrt( datasets::Vector{Dataset}, options = String[]; dest = "/vsimem/tmp" - ) + )::Dataset options = GDAL.gdalbuildvrtoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalbuildvrt(dest, length(datasets), diff --git a/src/utils.jl b/src/utils.jl index ef90a17f..65652254 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -89,14 +89,15 @@ end Fetch list of (non-empty) metadata domains. """ -metadatadomainlist(obj) = GDAL.gdalgetmetadatadomainlist(obj.ptr) +metadatadomainlist(obj)::Vector{String} = + GDAL.gdalgetmetadatadomainlist(obj.ptr) """ metadata(obj; domain::AbstractString = "") Fetch metadata. Note that relatively few formats return any metadata. """ -metadata(obj; domain::AbstractString = "") = +metadata(obj; domain::AbstractString = "")::Vector{String} = GDAL.gdalgetmetadata(obj.ptr, domain) """ @@ -111,7 +112,11 @@ Fetch single metadata item. ### Returns The metadata item on success, or an empty string on failure. """ -function metadataitem(obj, name::AbstractString; domain::AbstractString = "") +function metadataitem( + obj, + name::AbstractString; + domain::AbstractString = "" + )::String item = GDAL.gdalgetmetadataitem(obj.ptr, name, domain) return item === nothing ? "" : item end @@ -135,8 +140,10 @@ defined in the environment. If `setconfigoption()` is called several times with the same key, the value provided during the last call will be used. """ -setconfigoption(option::AbstractString, value) = +function setconfigoption(option::AbstractString, value)::Nothing GDAL.cplsetconfigoption(option, value) + return nothing +end """ clearconfigoption(option::AbstractString) @@ -146,7 +153,10 @@ This function can be used to clear a setting. Note: it will not unset an existing environment variable; it will just unset a value previously set by `setconfigoption()`. """ -clearconfigoption(option::AbstractString) = setconfigoption(option, C_NULL) +function clearconfigoption(option::AbstractString)::Nothing + setconfigoption(option, C_NULL) + return nothing +end """ getconfigoption(option::AbstractString, default = C_NULL) @@ -164,7 +174,7 @@ it in environment variables. ### Returns the value associated to the key, or the default value if not found. """ -function getconfigoption(option::AbstractString, default = C_NULL) +function getconfigoption(option::AbstractString, default = C_NULL)::String result = @gdal(CPLGetConfigOption::Cstring, option::Cstring, default::Cstring @@ -188,8 +198,10 @@ This function sets the configuration option that only applies in the current thread, as opposed to `setconfigoption()` which sets an option that applies on all threads. """ -setthreadconfigoption(option::AbstractString, value) = +function setthreadconfigoption(option::AbstractString, value)::Nothing GDAL.cplsetthreadlocalconfigoption(option, value) + return nothing +end """ clearthreadconfigoption(option::AbstractString) @@ -199,15 +211,17 @@ This function can be used to clear a setting. Note: it will not unset an existing environment variable; it will just unset a value previously set by `setthreadconfigoption()`. """ -clearthreadconfigoption(option::AbstractString) = +function clearthreadconfigoption(option::AbstractString)::Nothing setthreadconfigoption(option, C_NULL) + return nothing +end """ getthreadconfigoption(option::AbstractString, default = C_NULL) Same as `getconfigoption()` but with settings from `setthreadconfigoption()`. """ -function getthreadconfigoption(option::AbstractString, default = C_NULL) +function getthreadconfigoption(option::AbstractString, default = C_NULL)::String result = @gdal(CPLGetThreadLocalConfigOption::Cstring, option::Cstring, default::Cstring From 7a785d4afa8c6810a890ee9100b7108c70ede6e8 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 23:11:22 -0700 Subject: [PATCH 021/169] tighten the return type --- src/base/iterators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/iterators.jl b/src/base/iterators.jl index 1fa2871d..af846f60 100644 --- a/src/base/iterators.jl +++ b/src/base/iterators.jl @@ -94,7 +94,7 @@ windows(raster::AbstractRasterBand)::WindowIterator{Int64} = function Base.iterate( obj::WindowIterator{T}, iter::T = 0 - )::Union{Nothing, Tuple{Tuple{UnitRange{T}, UnitRange{T}}, T}} where T + )::Union{Nothing, Tuple{NTuple{2, UnitRange{T}}, T}} where T <: Integer handle = obj.blockiter next = Base.iterate(handle, iter) next == nothing && return nothing From 62ccf75a92e4b69a4d1578a0ec1d96beb9675c5f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 23:12:24 -0700 Subject: [PATCH 022/169] white spacing --- src/base/iterators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/iterators.jl b/src/base/iterators.jl index af846f60..57e31117 100644 --- a/src/base/iterators.jl +++ b/src/base/iterators.jl @@ -9,7 +9,7 @@ function Base.iterate( resetreading!(layer) nothing else - (Feature(ptr), state+1) + (Feature(ptr), state + 1) end end From ec757bfe2901c8cd01b37557c573791d8ec27de2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 23:18:08 -0700 Subject: [PATCH 023/169] use isnothing() --- src/utils.jl | 2 +- test/test_rasterband.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 65652254..e3189630 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -118,7 +118,7 @@ function metadataitem( domain::AbstractString = "" )::String item = GDAL.gdalgetmetadataitem(obj.ptr, name, domain) - return item === nothing ? "" : item + return isnothing(item) ? "" : item end """ diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 1e5f03a4..2dc94d9b 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -43,11 +43,11 @@ import ArchGDAL; const AG = ArchGDAL AG.setscale!(rb, 1) @test AG.getscale(rb) ≈ 1 - @test AG.getnodatavalue(rb) === nothing + @test isnothing(AG.getnodatavalue(rb)) AG.setnodatavalue!(rb, -100) @test AG.getnodatavalue(rb) ≈ -100 AG.deletenodatavalue!(rb) - @test AG.getnodatavalue(rb) === nothing + @test isnothing(AG.getnodatavalue(rb)) AG.copy(dataset) do dest destband = AG.getband(dest, 1) From d5c1512e3a2ddb8bbd88db588887f2ea3edea661 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 23:34:52 -0700 Subject: [PATCH 024/169] whitespacing --- src/base/display.jl | 42 +++++++++++++++++++++--------------------- src/ogr/featuredefn.jl | 3 ++- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index e0724e80..d2dbf0ba 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -38,14 +38,14 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO println(io, "\nNumber of feature layers: $nlayers") ndisplay = min(nlayers, 5) # display up to 5 layers for i in 1:ndisplay - layer = getlayer(dataset, i-1) + layer = getlayer(dataset, i - 1) layergeomtype = getgeomtype(layer) - println(io, " Layer $(i-1): $(getname(layer)) ($layergeomtype)") + println(io, " Layer $(i - 1): $(getname(layer)) ($layergeomtype)") end if nlayers > 5 print(io, " Remaining layers: ") for i in 6:nlayers - print(io, "$(getname(getlayer(dataset, i-1))) ") + print(io, "$(getname(getlayer(dataset, i - 1))) ") # display up to 5 layer names per line if i % 5 == 0 println() end end @@ -98,8 +98,8 @@ function Base.show( println(io, "units: $(sc)px + $ofs$ut") print(io, " overviews: ") for i in 1:norvw - ovr_band = getoverview(rasterband, i-1) - print(io, "($(i-1)) $(width(ovr_band))x$(height(ovr_band)) ") + ovr_band = getoverview(rasterband, i - 1) + print(io, "($(i - 1)) $(width(ovr_band))x$(height(ovr_band)) ") i % 3 == 0 && print(io, "\n ") end return io @@ -119,8 +119,8 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO n = ngeom(featuredefn) ngeomdisplay = min(n, 3) for i in 1:ngeomdisplay - gfd = getgeomdefn(featuredefn, i-1) - display = " Geometry $(i-1) ($(getname(gfd))): [$(gettype(gfd))]" + gfd = getgeomdefn(featuredefn, i - 1) + display = " Geometry $(i - 1) ($(getname(gfd))): [$(gettype(gfd))]" if length(display) > 75 println(io, "$display[1:70]...") continue @@ -147,14 +147,14 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO n = nfield(featuredefn) nfielddisplay = min(n, 5) for i in 1:nfielddisplay - fd = getfielddefn(featuredefn, i-1) - display = " Field $(i-1) ($(getname(fd))): [$(gettype(fd))]" + fd = getfielddefn(featuredefn, i - 1) + display = " Field $(i - 1) ($(getname(fd))): [$(gettype(fd))]" if length(display) > 75 println(io, "$display[1:70]...") continue end for f in layer - field = string(getfield(f, i-1)) + field = string(getfield(f, i - 1)) length(field) > 25 && (field = "$(field[1:20])...") newdisplay = "$display, $field" if length(newdisplay) > 75 @@ -179,16 +179,16 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO n = ngeom(featuredefn) ngeomdisplay = min(n, 3) for i in 1:ngeomdisplay - gfd = getgeomdefn(featuredefn, i-1) - println(io, " Geometry (index $(i-1)): $gfd") + gfd = getgeomdefn(featuredefn, i - 1) + println(io, " Geometry (index $(i - 1)): $gfd") end n > 3 && println(io, " ...\n Number of Geometries: $n") n = nfield(featuredefn) nfielddisplay = min(n, 5) for i in 1:nfielddisplay - fd = getfielddefn(featuredefn, i-1) - println(io, " Field (index $(i-1)): $fd") + fd = getfielddefn(featuredefn, i - 1) + println(io, " Field (index $(i - 1)): $fd") end n > 5 && print(io, "...\n Number of Fields: $n") return io @@ -220,15 +220,15 @@ function Base.show(io::IO, feature::Feature)::IO println(io, "Feature") n = ngeom(feature) for i in 1:min(n, 3) - displayname = geomname(getgeom(feature, i-1)) - println(io, " (index $(i-1)) geom => $displayname") + displayname = geomname(getgeom(feature, i - 1)) + println(io, " (index $(i - 1)) geom => $displayname") end n > 3 && println(io, "...\n Number of geometries: $n") n = nfield(feature) for i in 1:min(n, 10) - displayname = getname(getfielddefn(feature, i-1)) - print(io, " (index $(i-1)) $displayname => ") - println(io, "$(getfield(feature, i-1))") + displayname = getname(getfielddefn(feature, i - 1)) + print(io, " (index $(i - 1)) $displayname => ") + println(io, "$(getfield(feature, i - 1))") end n > 10 && print(io, "...\n Number of Fields: $n") return io @@ -242,7 +242,7 @@ function Base.show(io::IO, spref::AbstractSpatialRef)::IO projstr = toPROJ4(spref) if length(projstr) > 45 projstart = projstr[1:35] - projend = projstr[end-4:end] + projend = projstr[(end - 4):end] print(io, "Spatial Reference System: $projstart ... $projend") else print(io, "Spatial Reference System: $projstr") @@ -261,7 +261,7 @@ function Base.show(io::IO, geom::AbstractGeometry)::IO print(io, "Geometry: ") geomwkt = toWKT(geom) if length(geomwkt) > 60 - print(io, "$(geomwkt[1:50]) ... $(geomwkt[end-4:end])") + print(io, "$(geomwkt[1:50]) ... $(geomwkt[(end - 4):end])") else print(io, "$geomwkt") end diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index da51c57e..f049b8ff 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -66,7 +66,8 @@ end Get name of the OGRFeatureDefn passed as an argument. """ -getname(featuredefn::AbstractFeatureDefn)::String = GDAL.ogr_fd_getname(featuredefn.ptr) +getname(featuredefn::AbstractFeatureDefn)::String = + GDAL.ogr_fd_getname(featuredefn.ptr) """ nfield(featuredefn::AbstractFeatureDefn) From cf950a2d5b19d094cef24d76ec7166c0f1021a83 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 23:35:23 -0700 Subject: [PATCH 025/169] Array -> Vector --- src/ogr/feature.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 7584eed1..02d8799e 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -226,7 +226,7 @@ pointer may be NULL or non-NULL. function asintlist(feature::Feature, i::Integer)::Vector{Int32} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasintegerlist(feature.ptr, i, n) - return (n.x == 0) ? Int32[] : unsafe_wrap(Array{Int32}, ptr, n.x) + return (n.x == 0) ? Int32[] : unsafe_wrap(Vector{Int32}, ptr, n.x) end """ @@ -247,7 +247,7 @@ pointer may be NULL or non-NULL. function asint64list(feature::Feature, i::Integer)::Vector{Int64} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasinteger64list(feature.ptr, i, n) - return (n.x == 0) ? Int64[] : unsafe_wrap(Array{Int64}, ptr, n.x) + return (n.x == 0) ? Int64[] : unsafe_wrap(Vector{Int64}, ptr, n.x) end """ @@ -268,7 +268,7 @@ pointer may be NULL or non-NULL. function asdoublelist(feature::Feature, i::Integer)::Vector{Float64} n = Ref{Cint}() ptr = GDAL.ogr_f_getfieldasdoublelist(feature.ptr, i, n) - return (n.x == 0) ? Float64[] : unsafe_wrap(Array{Float64}, ptr, n.x) + return (n.x == 0) ? Float64[] : unsafe_wrap(Vector{Float64}, ptr, n.x) end """ From 2811f95300564159924a7fa79e6fffc68c337068 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 24 Apr 2021 23:51:43 -0700 Subject: [PATCH 026/169] Introduce enums for WKBByteOrder --- src/constants.jl | 6 +++++- src/ogr/geometry.jl | 8 ++++---- src/types.jl | 5 +++++ test/test_geometry.jl | 8 ++++---- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index 52f749d1..8dbff988 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -34,7 +34,6 @@ GDALTileOrganization = GDAL.GDALTileOrganization GDALGridAlgorithm = GDAL.GDALGridAlgorithm OGRwkbGeometryType = GDAL.OGRwkbGeometryType OGRwkbVariant = GDAL.OGRwkbVariant -OGRwkbByteOrder = GDAL.OGRwkbByteOrder OGRFieldSubType = GDAL.OGRFieldSubType OGRJustification = GDAL.OGRJustification OGRSTClassId = GDAL.OGRSTClassId @@ -181,6 +180,11 @@ const _FIELDTYPE = Dict{OGRFieldType, DataType}( wkbGeometryCollection25D = 70, ) +@enum(WKBByteOrder, + wkbXDR = 0, + wkbNDR = 1, +) + @enum(GDALOpenFlag, OF_ReadOnly = GDAL.GDAL_OF_READONLY, # 0x00 OF_Update = GDAL.GDAL_OF_UPDATE, # 0x01 diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 2b899da5..28cd6588 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -232,7 +232,7 @@ function boundingbox(geom::AbstractGeometry)::IGeometry end """ - toWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = GDAL.wkbNDR) + toWKB(geom::AbstractGeometry, order::WKBByteOrder = wkbNDR) Convert a geometry well known binary format. @@ -242,7 +242,7 @@ Convert a geometry well known binary format. """ function toWKB( geom::AbstractGeometry, - order::OGRwkbByteOrder = GDAL.wkbNDR + order::WKBByteOrder = wkbNDR )::Vector{Cuchar} buffer = Vector{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttowkb(geom.ptr, order, buffer) @@ -251,7 +251,7 @@ function toWKB( end """ - toISOWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = GDAL.wkbNDR) + toISOWKB(geom::AbstractGeometry, order::WKBByteOrder = wkbNDR) Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. @@ -261,7 +261,7 @@ Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. """ function toISOWKB( geom::AbstractGeometry, - order::OGRwkbByteOrder = GDAL.wkbNDR + order::WKBByteOrder = wkbNDR )::Vector{Cuchar} buffer = Array{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttoisowkb(geom.ptr, order, buffer) diff --git a/src/types.jl b/src/types.jl index e5149c30..8403c0a9 100644 --- a/src/types.jl +++ b/src/types.jl @@ -312,6 +312,11 @@ eval(@gdalenum(WKBGeometryType::GDAL.OGRwkbGeometryType, wkbGeometryCollection25D::GDAL.wkbGeometryCollection25D, )) +eval(@gdalenum(WKBByteOrder::GDAL.OGRwkbByteOrder, + wkbXDR::GDAL.wkbXDR, + wkbNDR::GDAL.wkbNDR, +)) + import Base.| |(x::GDALOpenFlag,y::UInt8) = UInt8(x) | y diff --git a/test/test_geometry.jl b/test/test_geometry.jl index bc5f4dc6..32706df9 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -31,10 +31,10 @@ end @test sprint(print, AG.envelope(point)) == "GDAL.OGREnvelope(100.0, 100.0, 70.0, 70.0)" @test sprint(print, AG.envelope3d(point)) == "GDAL.OGREnvelope3D(100.0, 100.0, 70.0, 70.0, 0.0, 0.0)" - @test AG.toISOWKB(point, GDAL.wkbNDR) == UInt8[0x01,0xe9,0x03,0x00,0x00, + @test AG.toISOWKB(point, AG.wkbNDR) == UInt8[0x01,0xe9,0x03,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x40,0x00,0x00,0x00,0x00,0x00,0x80, 0x51,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] - @test AG.toISOWKB(point, GDAL.wkbXDR) == UInt8[0x00,0x00,0x00,0x03,0xe9, + @test AG.toISOWKB(point, AG.wkbXDR) == UInt8[0x00,0x00,0x00,0x03,0xe9, 0x40,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x51,0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] @test AG.toKML(point, "relativeToGround") == "relativeToGround100,70,0" @@ -76,10 +76,10 @@ end @test AG.getz(point, 0) == 0 @test sprint(print, AG.envelope(point)) == "GDAL.OGREnvelope(100.0, 100.0, 70.0, 70.0)" @test sprint(print, AG.envelope3d(point)) == "GDAL.OGREnvelope3D(100.0, 100.0, 70.0, 70.0, 0.0, 0.0)" - @test AG.toISOWKB(point, GDAL.wkbNDR) == UInt8[0x01,0xe9,0x03,0x00,0x00, + @test AG.toISOWKB(point, AG.wkbNDR) == UInt8[0x01,0xe9,0x03,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x40,0x00,0x00,0x00,0x00,0x00,0x80, 0x51,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] - @test AG.toISOWKB(point, GDAL.wkbXDR) == UInt8[0x00,0x00,0x00,0x03,0xe9, + @test AG.toISOWKB(point, AG.wkbXDR) == UInt8[0x00,0x00,0x00,0x03,0xe9, 0x40,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x51,0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] @test AG.toKML(point, "relativeToGround") == "relativeToGround100,70,0" From fca9536fb47700b85ca075b346ec35230623a447 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 00:32:22 -0700 Subject: [PATCH 027/169] remove pointer definitions in constants.jl They were useful in a period of time when all GDAL objects are just Ptr{Void} and hence there was no way to distinguish between the type of GDAL object if we did not wrap the pointer in one of those constants. Ever since then, we have introduced corresponding mutable structs in types.jl that have obviated the need for using pointers directly. --- docs/src/memory.md | 10 +-- src/constants.jl | 19 ----- src/dataset.jl | 22 +++--- src/driver.jl | 4 +- src/ogr/featuredefn.jl | 2 +- src/ogr/featurelayer.jl | 18 ++--- src/ogr/fielddefn.jl | 2 +- src/ogr/geometry.jl | 24 +++---- src/ogr/styletable.jl | 9 ++- src/raster/rasterattributetable.jl | 2 +- src/raster/rasterband.jl | 20 +++--- src/raster/rasterio.jl | 14 ++-- src/types.jl | 107 +++++++++++++++-------------- 13 files changed, 121 insertions(+), 132 deletions(-) diff --git a/docs/src/memory.md b/docs/src/memory.md index e3709f57..d3c6e9eb 100644 --- a/docs/src/memory.md +++ b/docs/src/memory.md @@ -41,14 +41,14 @@ end under the hood (see `src/context.jl`). Therefore, the objects themselves do not have a finalizer registered: ```julia mutable struct RasterBand <: AbstractRasterBand - ptr::GDALRasterBand + ptr::GDAL.GDALRasterBandH end unsafe_getband(dataset::AbstractDataset, i::Integer) = RasterBand(GDAL.getrasterband(dataset.ptr, i)) function destroy(rb::AbstractRasterBand) - rb.ptr = GDALRasterBand(C_NULL) + rb.ptr = C_NULL end ``` @@ -65,11 +65,11 @@ rasterband = ArchGDAL.getband(dataset, i) returns an interactive rasterband that has `destroy()` registered with its finalizer. ```julia mutable struct IRasterBand <: AbstractRasterBand - ptr::GDALRasterBand + ptr::GDAL.GDALRasterBandH ownedby::AbstractDataset function IRasterBand( - ptr::GDALRasterBand = GDALRasterBand(C_NULL); + ptr::GDAL.GDALRasterBandH = C_NULL; ownedby::AbstractDataset = Dataset() ) rasterband = new(ptr, ownedby) @@ -82,7 +82,7 @@ getband(dataset::AbstractDataset, i::Integer) = IRasterBand(GDAL.getrasterband(dataset.ptr, i), ownedby = dataset) function destroy(rasterband::IRasterBand) - rasterband.ptr = GDALRasterBand(C_NULL) + rasterband.ptr = C_NULL rasterband.ownedby = Dataset() return rasterband end diff --git a/src/constants.jl b/src/constants.jl index 8dbff988..84f43207 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -1,22 +1,3 @@ -const GDALColorTable = GDAL.GDALColorTableH -const GDALCoordTransform = GDAL.OGRCoordinateTransformationH -const GDALDataset = GDAL.GDALDatasetH -const GDALDriver = GDAL.GDALDriverH -const GDALFeature = GDAL.OGRFeatureH -const GDALFeatureDefn = GDAL.OGRFeatureDefnH -const GDALFeatureLayer = GDAL.OGRLayerH -const GDALField = GDAL.OGRField -const GDALFieldDefn = GDAL.OGRFieldDefnH -const GDALGeometry = GDAL.OGRGeometryH -const GDALGeomFieldDefn = GDAL.OGRGeomFieldDefnH -const GDALProgressFunc = GDAL.GDALProgressFunc -const GDALRasterAttrTable = GDAL.GDALRasterAttributeTableH -const GDALRasterBand = GDAL.GDALRasterBandH -const GDALSpatialRef = GDAL.OGRSpatialReferenceH -const GDALStyleManager = GDAL.OGRStyleMgrH -const GDALStyleTable = GDAL.OGRStyleTableH -const GDALStyleTool = GDAL.OGRStyleToolH - const StringList = Ptr{Cstring} CPLErr = GDAL.CPLErr diff --git a/src/dataset.jl b/src/dataset.jl index ab2a55e0..8173f4d5 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -288,10 +288,10 @@ end unsafe_read(filename; flags=OF_ReadOnly, alloweddrivers, options, siblingfiles) -Open a raster file as a GDALDataset. +Open a raster file as a `Dataset`. This function will try to open the passed file, or virtual dataset name by -invoking the Open method of each registered `GDALDriver` in turn. The first +invoking the Open method of each registered `Driver` in turn. The first successful open will result in a returned dataset. If all drivers fail then `NULL` is returned and an error is issued. @@ -306,9 +306,9 @@ driver on how to access a dataset. It should be in UTF-8 encoding. drivers. If none of the value is specified, both are implied. - Access mode: `OF_ReadOnly` (exclusive) or `OF_Update`. - Shared mode: `GDAL_OF_SHARED`. If set, it allows the sharing of - GDALDataset handles for a dataset with other callers that + `Dataset` handles for a dataset with other callers that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will - consult its list of currently open and shared GDALDataset's, + consult its list of currently open and shared `Dataset`'s, and if the GetDescription() name for one exactly matches the pszFilename passed to GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called from the same thread. @@ -463,7 +463,7 @@ filelist(dataset::AbstractDataset)::Vector{String} = Fetch the layer at index `i` (between `0` and `nlayer(dataset)-1`) -The returned layer remains owned by the GDALDataset and should not be deleted by +The returned layer remains owned by the `Dataset` and should not be deleted by the application. """ getlayer(dataset::AbstractDataset, i::Integer)::IFeatureLayer = @@ -479,7 +479,7 @@ unsafe_getlayer(dataset::AbstractDataset, i::Integer)::FeatureLayer = Fetch the feature layer corresponding to the given name. If it is called on a Table, which supports only one layer, a name is not needed. -The returned layer remains owned by the GDALDataset and should not be deleted by +The returned layer remains owned by the `Dataset` and should not be deleted by the application. """ function getlayer(dataset::AbstractDataset, name::AbstractString)::IFeatureLayer @@ -585,14 +585,14 @@ function unsafe_executesql( dataset::AbstractDataset, query::AbstractString; dialect::AbstractString = "", - spatialfilter::Geometry = Geometry(GDALGeometry(C_NULL)) + spatialfilter::Geometry = Geometry(C_NULL) )::FeatureLayer - return FeatureLayer(GDALFeatureLayer(GDAL.gdaldatasetexecutesql( + return FeatureLayer(GDAL.gdaldatasetexecutesql( dataset.ptr, query, spatialfilter.ptr, dialect - ))) + )) end """ @@ -601,8 +601,8 @@ end Release results of ExecuteSQL(). This function should only be used to deallocate OGRLayers resulting from an -ExecuteSQL() call on the same GDALDataset. Failure to deallocate a results set -before destroying the GDALDataset may cause errors. +ExecuteSQL() call on the same `Dataset`. Failure to deallocate a results set +before destroying the `Dataset` may cause errors. ### Parameters * `dataset`: the dataset handle. diff --git a/src/driver.jl b/src/driver.jl index c167aaaf..8564c6f3 100644 --- a/src/driver.jl +++ b/src/driver.jl @@ -15,7 +15,7 @@ getdriver(name::AbstractString)::Driver = Driver(GDAL.gdalgetdriverbyname(name)) """ destroy(drv::Driver) -Destroy a `GDALDriver`. +Destroy a `Driver`. This is roughly equivalent to deleting the driver, but is guaranteed to take place in the GDAL heap. It is important this that function not be called on a @@ -92,7 +92,7 @@ listdrivers()::Dict{String,String} = Dict{String,String}([ Identify the driver that can open a raster file. This function will try to identify the driver that can open the passed filename -by invoking the Identify method of each registered `GDALDriver` in turn. The +by invoking the Identify method of each registered `Driver` in turn. The first driver that successful identifies the file name will be returned. If all drivers fail then `NULL` is returned. """ diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index f049b8ff..55666146 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -361,7 +361,7 @@ OGRFeatures that depend on it is likely to result in a crash. Starting with GDAL 2.1, returns NULL in case out of memory situation. """ function unsafe_createfeature(featuredefn::AbstractFeatureDefn)::Feature - return Feature(GDALFeature(GDAL.ogr_f_create(featuredefn.ptr))) + return Feature(GDAL.ogr_f_create(featuredefn.ptr)) end """ diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index bbe1628a..5c7fa2e4 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -1,11 +1,11 @@ function destroy(layer::AbstractFeatureLayer)::Nothing - layer.ptr = GDALFeatureLayer(C_NULL) + layer.ptr = C_NULL return nothing end function destroy(layer::IFeatureLayer)::Nothing - layer.ptr = GDALFeatureLayer(C_NULL) + layer.ptr = C_NULL layer.ownedby = Dataset() layer.spatialref = SpatialRef() return nothing @@ -111,13 +111,13 @@ getgeomtype(layer::AbstractFeatureLayer)::WKBGeometryType = Returns the current spatial filter for this layer. """ function getspatialfilter(layer::AbstractFeatureLayer)::IGeometry - result = GDALGeometry(GDAL.ogr_l_getspatialfilter(Ptr{Cvoid}(layer.ptr))) + result = GDAL.ogr_l_getspatialfilter(Ptr{Cvoid}(layer.ptr)) return if result == C_NULL IGeometry(result) else # NOTE(yeesian): we make a clone here so that the geometry does not # depend on the FeatureLayer. - IGeometry(GDALGeometry(GDAL.ogr_g_clone(result))) + IGeometry(GDAL.ogr_g_clone(result)) end end @@ -190,7 +190,7 @@ end function clearspatialfilter!( layer::L )::L where {L <: AbstractFeatureLayer} - GDAL.ogr_l_setspatialfilter(layer.ptr, GDALGeometry(C_NULL)) + GDAL.ogr_l_setspatialfilter(layer.ptr, C_NULL) return layer end @@ -264,7 +264,7 @@ function clearspatialfilter!( layer::L, i::Integer )::L where {L <: AbstractFeatureLayer} - GDAL.ogr_l_setspatialfilterex(layer.ptr, i, GDALGeometry(C_NULL)) + GDAL.ogr_l_setspatialfilterex(layer.ptr, i, C_NULL) return layer end @@ -375,7 +375,7 @@ reading may or may not be valid after that operation and a call to `resetreading!()` might be needed. """ function unsafe_nextfeature(layer::AbstractFeatureLayer)::Feature - return Feature(GDALFeature(GDAL.ogr_l_getnextfeature(layer.ptr))) + return Feature(GDAL.ogr_l_getnextfeature(layer.ptr)) end """ @@ -440,7 +440,7 @@ The returned feature is now owned by the caller, and should be freed with `destroy()`. """ unsafe_getfeature(layer::AbstractFeatureLayer, i::Integer)::Feature = - Feature(GDALFeature(GDAL.ogr_l_getfeature(layer.ptr, i))) + Feature(GDAL.ogr_l_getfeature(layer.ptr, i)) """ setfeature!(layer::AbstractFeatureLayer, feature::Feature) @@ -1075,7 +1075,7 @@ nreference(layer::AbstractFeatureLayer)::Integer = # function synctodisk!(layer::AbstractFeatureLayer) # result = GDAL.ogr_l_synctodisk(layer.ptr) # @ogrerr result "Failed to flush pending changes to disk" -# layer.ptr = GDALFeatureLayer(C_NULL) +# layer.ptr = C_NULL # end # """ diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index 7d7e7412..588226c8 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -222,7 +222,7 @@ end Get default field value """ function getdefault(fielddefn::AbstractFieldDefn)::String - result = @gdal(OGR_Fld_GetDefault::Cstring, fielddefn.ptr::GDALFieldDefn) + result = @gdal(OGR_Fld_GetDefault::Cstring, fielddefn.ptr::GDAL.OGRFieldDefnH) return if result == C_NULL "" else diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 28cd6588..a54ca9d7 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -9,11 +9,11 @@ binary (WKB) representation. * `data`: pointer to the input BLOB data. """ function fromWKB(data)::IGeometry - geom = Ref{GDALGeometry}() + geom = Ref{GDAL.OGRGeometryH}() result = @gdal(OGR_G_CreateFromWkb::GDAL.OGRErr, data::Ptr{Cuchar}, - C_NULL::GDALSpatialRef, - geom::Ptr{GDALGeometry}, + C_NULL::GDAL.OGRSpatialReferenceH, + geom::Ptr{GDAL.OGRGeometryH}, sizeof(data)::Cint ) @ogrerr result "Failed to create geometry from WKB" @@ -21,11 +21,11 @@ function fromWKB(data)::IGeometry end function unsafe_fromWKB(data)::Geometry - geom = Ref{GDALGeometry}() + geom = Ref{GDAL.OGRGeometryH}() result = @gdal(OGR_G_CreateFromWkb::GDAL.OGRErr, data::Ptr{Cuchar}, - C_NULL::GDALSpatialRef, - geom::Ptr{GDALGeometry}, + C_NULL::GDAL.OGRSpatialReferenceH, + geom::Ptr{GDAL.OGRGeometryH}, sizeof(data)::Cint ) @ogrerr result "Failed to create geometry from WKB" @@ -44,22 +44,22 @@ Create a geometry object of the appropriate type from its well known text last character consumed. """ function fromWKT(data::Vector{String})::IGeometry - geom = Ref{GDALGeometry}() + geom = Ref{GDAL.OGRGeometryH}() result = @gdal(OGR_G_CreateFromWkt::GDAL.OGRErr, data::StringList, - C_NULL::GDALSpatialRef, - geom::Ptr{GDALGeometry} + C_NULL::GDAL.OGRSpatialReferenceH, + geom::Ptr{GDAL.OGRGeometryH} ) @ogrerr result "Failed to create geometry from WKT" return IGeometry(geom[]) end function unsafe_fromWKT(data::Vector{String})::Geometry - geom = Ref{GDALGeometry}() + geom = Ref{GDAL.OGRGeometryH}() result = @gdal(OGR_G_CreateFromWkt::GDAL.OGRErr, data::StringList, - C_NULL::GDALSpatialRef, - geom::Ptr{GDALGeometry} + C_NULL::GDAL.OGRSpatialReferenceH, + geom::Ptr{GDAL.OGRGeometryH} ) @ogrerr result "Failed to create geometry from WKT" return Geometry(geom[]) diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index 504ba0f5..3210f8f4 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -1,5 +1,5 @@ """ - unsafe_createstylemanager(styletable = GDALStyleTable(C_NULL)) + unsafe_createstylemanager(styletable = C_NULL) OGRStyleMgr factory. @@ -9,8 +9,11 @@ OGRStyleMgr factory. ### Returns an handle to the new style manager object. """ -unsafe_createstylemanager(styletable = GDALStyleTable(C_NULL))::StyleManager = - StyleManager(GDAL.ogr_sm_create(styletable)) +function unsafe_createstylemanager( + styletable::GDAL.OGRStyleTableH = C_NULL + )::StyleManager + return StyleManager(GDAL.ogr_sm_create(styletable)) +end """ Destroy Style Manager. diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 63818997..9f081e0e 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -180,7 +180,7 @@ end Determine whether changes made to this RAT are reflected directly in the dataset -If this returns `false` then GDALRasterBand.SetDefaultRAT() should be called. +If this returns `false` then RasterBand.SetDefaultRAT() should be called. Otherwise this is unnecessary since changes to this object are reflected in the dataset. """ diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index fd653f2a..06cb0ff2 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -1,11 +1,11 @@ function destroy(band::AbstractRasterBand)::Nothing - band.ptr = GDALRasterBand(C_NULL) + band.ptr = C_NULL return nothing end function destroy(band::IRasterBand)::Nothing - band.ptr = GDALRasterBand(C_NULL) + band.ptr = C_NULL band.ownedby = Dataset() return nothing end @@ -70,7 +70,7 @@ accessflag(band::AbstractRasterBand)::GDAL.GDALAccess = Fetch the band number (1+) within its dataset, or 0 if unknown. This method may return a value of 0 to indicate overviews, or free-standing -`GDALRasterBand` objects without a relationship to a dataset. +`RasterBand` objects without a relationship to a dataset. """ indexof(band::AbstractRasterBand)::Integer = GDAL.gdalgetbandnumber(band.ptr) @@ -372,11 +372,11 @@ end Returns a clone of the color table associated with the band. (If there is no associated color table, the original result is `NULL`. The -original color table remains owned by the `GDALRasterBand`, and can't be +original color table remains owned by the `RasterBand`, and can't be depended on for long, nor should it ever be modified by the caller.) """ function unsafe_getcolortable(band::AbstractRasterBand)::ColorTable - result = ColorTable(GDALColorTable(GDAL.gdalgetrastercolortable(band.ptr))) + result = ColorTable(GDAL.gdalgetrastercolortable(band.ptr)) return if result.ptr == C_NULL result else @@ -405,7 +405,7 @@ function setcolortable!( end function clearcolortable!(band::T)::T where {T <: AbstractRasterBand} - result = GDAL.gdalsetrastercolortable(band.ptr, GDALColorTable(C_NULL)) + result = GDAL.gdalsetrastercolortable(band.ptr, C_NULL) @cplwarn result "CPLError $(result): action is unsupported by the driver" return band end @@ -451,7 +451,7 @@ function regenerateoverviews!( result = GDAL.gdalregenerateoverviews( band.ptr, length(overviewbands), - GDALRasterBand[band.ptr for band in overviewbands], + [band.ptr for band in overviewbands], resampling, cfunc, progressdata @@ -542,7 +542,7 @@ end Return the mask band associated with the band. -The `GDALRasterBand` class includes a default implementation of `GetMaskBand()` +The `RasterBand` class includes a default implementation of `GetMaskBand()` that returns one of four default implementations: - If a corresponding .msk file exists it will be used for the mask band. @@ -560,7 +560,7 @@ apply to this band (specific rules yet to be determined) and that is of type `GDALAllValidRasterBand` class will be returned that has 255 values for all pixels. The null flags will return `GMF_ALL_VALID`. -Note that the `GetMaskBand()` should always return a `GDALRasterBand` mask, +Note that the `GetMaskBand()` should always return a `RasterBand` mask, even if it is only an all 255 mask with the flags indicating `GMF_ALL_VALID`. See also: http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask @@ -591,7 +591,7 @@ have values other than 0 and 255. - `GMF_NODATA` (`0x08`): Indicates the mask is actually being generated from nodata values. (mutually exclusive of `GMF_ALPHA`) -The `GDALRasterBand` class includes a default implementation of `GetMaskBand()` +The `RasterBand` class includes a default implementation of `GetMaskBand()` that returns one of four default implementations: - If a corresponding .msk file exists it will be used for the mask band. diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 5da41a2d..56895567 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -16,7 +16,7 @@ This method allows reading a region of one or more `RasterBand`s from this dataset into a buffer, or writing data from a buffer into a region of the `RasterBand`s. It automatically takes care of data type translation if the element type (`<:Real`) of the buffer is different than that of the -`GDALRasterBand`. The method also takes care of image decimation / replication +`RasterBand`. The method also takes care of image decimation / replication if the buffer size (`xsz × ysz`) is different than the size of the region being accessed (`xsize × ysize`). @@ -449,7 +449,7 @@ for (T,GT) in _GDALTYPE @assert nband == zbsize result = ccall((:GDALDatasetRasterIOEx,GDAL.libgdal), GDAL.CPLErr, # return type - (GDALDataset, + (GDAL.GDALDatasetH, GDAL.GDALRWFlag, # access Cint, # xoffset Cint, # yoffset @@ -507,11 +507,11 @@ for (T,GT) in _GDALTYPE (rasterband == C_NULL) && error("Can't read invalid rasterband") xbsize, ybsize = size(buffer) result = ccall((:GDALRasterIOEx,GDAL.libgdal),GDAL.CPLErr, - (GDALRasterBand,GDAL.GDALRWFlag,Cint,Cint,Cint,Cint,Ptr{Cvoid}, - Cint,Cint,GDAL.GDALDataType,GDAL.GSpacing, GDAL.GSpacing, - Ptr{GDAL.GDALRasterIOExtraArg}),rasterband.ptr,access,xoffset, - yoffset,xsize,ysize,pointer(buffer),xbsize,ybsize,$GT,pxspace, - linespace,extraargs) + (GDAL.GDALRasterBandH,GDAL.GDALRWFlag,Cint,Cint,Cint,Cint, + Ptr{Cvoid},Cint,Cint,GDAL.GDALDataType,GDAL.GSpacing, + GDAL.GSpacing,Ptr{GDAL.GDALRasterIOExtraArg}),rasterband.ptr, + access,xoffset,yoffset,xsize,ysize,pointer(buffer),xbsize, + ybsize,$GT,pxspace,linespace,extraargs) @cplerr result "Access in RasterIO failed." return buffer end diff --git a/src/types.jl b/src/types.jl index 8403c0a9..d8539f11 100644 --- a/src/types.jl +++ b/src/types.jl @@ -2,43 +2,43 @@ import DiskArrays: AbstractDiskArray import Base.convert abstract type AbstractGeometry <: GeoInterface.AbstractGeometry end - # needs to have a `ptr::GDALGeometry` attribute + # needs to have a `ptr::GDAL.OGRGeometryH` attribute abstract type AbstractSpatialRef end - # needs to have a `ptr::GDALSpatialRef` attribute + # needs to have a `ptr::GDAL.OGRSpatialReferenceH` attribute abstract type AbstractDataset end - # needs to have a `ptr::GDALDataset` attribute + # needs to have a `ptr::GDAL.GDALDatasetH` attribute abstract type AbstractFeatureDefn end - # needs to have a `ptr::GDALFeatureDefn` attribute + # needs to have a `ptr::GDAL.OGRFeatureDefnH` attribute abstract type AbstractFeatureLayer end - # needs to have a `ptr::GDALDataset` attribute + # needs to have a `ptr::GDAL.OGRLayerH` attribute abstract type AbstractFieldDefn end - # needs to have a `ptr::GDALFieldDefn` attribute + # needs to have a `ptr::GDAL.OGRFieldDefnH` attribute abstract type AbstractGeomFieldDefn end - # needs to have a `ptr::GDALGeomFieldDefn` attribute + # needs to have a `ptr::GDAL.OGRGeomFieldDefnH` attribute abstract type AbstractRasterBand{T} <: AbstractDiskArray{T,2} end - # needs to have a `ptr::GDALDataset` attribute + # needs to have a `ptr::GDAL.GDALRasterBandH` attribute mutable struct CoordTransform - ptr::GDALCoordTransform + ptr::GDAL.OGRCoordinateTransformationH end mutable struct Dataset <: AbstractDataset - ptr::GDALDataset + ptr::GDAL.GDALDatasetH - Dataset(ptr::GDALDataset = C_NULL) = new(ptr) + Dataset(ptr::GDAL.GDALDatasetH = C_NULL) = new(ptr) end mutable struct IDataset <: AbstractDataset - ptr::GDALDataset + ptr::GDAL.GDALDatasetH - function IDataset(ptr::GDALDataset = C_NULL) + function IDataset(ptr::GDAL.GDALDatasetH = C_NULL) dataset = new(ptr) finalizer(destroy, dataset) return dataset @@ -46,21 +46,21 @@ mutable struct IDataset <: AbstractDataset end mutable struct Driver - ptr::GDALDriver + ptr::GDAL.GDALDriverH end mutable struct Field - ptr::GDALField + ptr::GDAL.OGRField end mutable struct FieldDefn <: AbstractFieldDefn - ptr::GDALFieldDefn + ptr::GDAL.OGRFieldDefnH end mutable struct IFieldDefnView <: AbstractFieldDefn - ptr::GDALFieldDefn + ptr::GDAL.OGRFieldDefnH - function IFieldDefnView(ptr::GDALFieldDefn = C_NULL) + function IFieldDefnView(ptr::GDAL.OGRFieldDefnH = C_NULL) fielddefn = new(ptr) finalizer(destroy, fielddefn) return fielddefn @@ -68,11 +68,11 @@ mutable struct IFieldDefnView <: AbstractFieldDefn end mutable struct GeomFieldDefn <: AbstractGeomFieldDefn - ptr::GDALGeomFieldDefn + ptr::GDAL.OGRGeomFieldDefnH spatialref::AbstractSpatialRef function GeomFieldDefn( - ptr::GDALGeomFieldDefn = C_NULL; + ptr::GDAL.OGRGeomFieldDefnH = C_NULL; spatialref::AbstractSpatialRef = SpatialRef() ) return new(ptr, spatialref) @@ -80,9 +80,9 @@ mutable struct GeomFieldDefn <: AbstractGeomFieldDefn end mutable struct IGeomFieldDefnView <: AbstractGeomFieldDefn - ptr::GDALGeomFieldDefn + ptr::GDAL.OGRGeomFieldDefnH - function IGeomFieldDefnView(ptr::GDALGeomFieldDefn = C_NULL) + function IGeomFieldDefnView(ptr::GDAL.OGRGeomFieldDefnH = C_NULL) geomdefn = new(ptr) finalizer(destroy, geomdefn) return geomdefn @@ -90,32 +90,32 @@ mutable struct IGeomFieldDefnView <: AbstractGeomFieldDefn end mutable struct RasterAttrTable - ptr::GDALRasterAttrTable + ptr::GDAL.GDALRasterAttributeTableH end mutable struct StyleManager - ptr::GDALStyleManager + ptr::GDAL.OGRStyleMgrH end mutable struct StyleTable - ptr::GDALStyleTable + ptr::GDAL.OGRStyleTableH end mutable struct StyleTool - ptr::GDALStyleTool + ptr::GDAL.OGRStyleToolH end mutable struct FeatureLayer <: AbstractFeatureLayer - ptr::GDALFeatureLayer + ptr::GDAL.OGRLayerH end mutable struct IFeatureLayer <: AbstractFeatureLayer - ptr::GDALFeatureLayer + ptr::GDAL.OGRLayerH ownedby::AbstractDataset spatialref::AbstractSpatialRef function IFeatureLayer( - ptr::GDALFeatureLayer = C_NULL; + ptr::GDAL.OGRLayerH = C_NULL; ownedby::AbstractDataset = Dataset(), spatialref::AbstractSpatialRef = SpatialRef() ) @@ -126,17 +126,17 @@ mutable struct IFeatureLayer <: AbstractFeatureLayer end mutable struct Feature - ptr::GDALFeature + ptr::GDAL.OGRFeatureH end mutable struct FeatureDefn <: AbstractFeatureDefn - ptr::GDALFeatureDefn + ptr::GDAL.OGRFeatureDefnH end mutable struct IFeatureDefnView <: AbstractFeatureDefn - ptr::GDALFeatureDefn + ptr::GDAL.OGRFeatureDefnH - function IFeatureDefnView(ptr::GDALFeatureDefn = C_NULL) + function IFeatureDefnView(ptr::GDAL.OGRFeatureDefnH = C_NULL) featuredefn = new(ptr) finalizer(destroy, featuredefn) return featuredefn @@ -144,19 +144,21 @@ mutable struct IFeatureDefnView <: AbstractFeatureDefn end mutable struct RasterBand{T} <: AbstractRasterBand{T} - ptr::GDALRasterBand + ptr::GDAL.GDALRasterBandH end -function RasterBand(ptr::GDALRasterBand) - t = datatype(GDAL.gdalgetrasterdatatype(ptr)) - RasterBand{t}(ptr) + +function RasterBand( + ptr::GDAL.GDALRasterBandH + )::RasterBand{datatype(GDAL.gdalgetrasterdatatype(ptr))} + return RasterBand{datatype(GDAL.gdalgetrasterdatatype(ptr))}(ptr) end mutable struct IRasterBand{T} <: AbstractRasterBand{T} - ptr::GDALRasterBand + ptr::GDAL.GDALRasterBandH ownedby::AbstractDataset function IRasterBand{T}( - ptr::GDALRasterBand = C_NULL; + ptr::GDAL.GDALRasterBandH = C_NULL; ownedby::AbstractDataset = Dataset() ) where T rasterband = new(ptr, ownedby) @@ -165,21 +167,24 @@ mutable struct IRasterBand{T} <: AbstractRasterBand{T} end end -function IRasterBand(ptr::GDALRasterBand; ownedby = Dataset()) - t = datatype(GDAL.gdalgetrasterdatatype(ptr)) - IRasterBand{t}(ptr, ownedby=ownedby) +function IRasterBand( + ptr::GDAL.GDALRasterBandH; + ownedby = Dataset() + )::IRasterBand{datatype(GDAL.gdalgetrasterdatatype(ptr))} + T = datatype(GDAL.gdalgetrasterdatatype(ptr)) + return IRasterBand{T}(ptr, ownedby = ownedby) end mutable struct SpatialRef <: AbstractSpatialRef - ptr::GDALSpatialRef + ptr::GDAL.OGRSpatialReferenceH - SpatialRef(ptr::GDALSpatialRef = C_NULL) = new(ptr) + SpatialRef(ptr::GDAL.OGRSpatialReferenceH = C_NULL) = new(ptr) end mutable struct ISpatialRef <: AbstractSpatialRef - ptr::GDALSpatialRef + ptr::GDAL.OGRSpatialReferenceH - function ISpatialRef(ptr::GDALSpatialRef = C_NULL) + function ISpatialRef(ptr::GDAL.OGRSpatialReferenceH = C_NULL) spref = new(ptr) finalizer(destroy, spref) return spref @@ -187,15 +192,15 @@ mutable struct ISpatialRef <: AbstractSpatialRef end mutable struct Geometry <: AbstractGeometry - ptr::GDALGeometry + ptr::GDAL.OGRGeometryH - Geometry(ptr::GDALGeometry = C_NULL) = new(ptr) + Geometry(ptr::GDAL.OGRGeometryH = C_NULL) = new(ptr) end mutable struct IGeometry <: AbstractGeometry - ptr::GDALGeometry + ptr::GDAL.OGRGeometryH - function IGeometry(ptr::GDALGeometry = C_NULL) + function IGeometry(ptr::GDAL.OGRGeometryH = C_NULL) geom = new(ptr) finalizer(destroy, geom) return geom @@ -203,7 +208,7 @@ mutable struct IGeometry <: AbstractGeometry end mutable struct ColorTable - ptr::GDALColorTable + ptr::GDAL.GDALColorTableH end "return the corresponding `DataType` in julia" From cb4a13a98554696417ba4bdc9ecf6206127c2d00 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 11:39:21 -0700 Subject: [PATCH 028/169] [Breaking] Provide proper support for all GDAL enums This uses the enum macro in Base to define each of the GDAL enums. * I decided to maintain names with GDAL for the most part to maintain searchability for the same names. (This is a breaking change for some of the existing names, e.g. for GDALOpenFlag.) * I decided not to go with cenum because I didn't want to support having different enum values evaluate to the same UInt8. * We no longer expose internal dicts of mappings between data types. Now everything should go through base conversion. * I verified (by a search on `::GDAL.` that the only remaining GDAL.jl types in the API for this package are GDAL.GDALColorEntry, GDAL.OGREnvelope, and GDAL.OGREnvelope3D. As they are well-defined structs, I see no compelling reason to wrap them yet. * [Breaking] We now use Base conversion for mapping between the different data types, rather than having gdaltype(), datatype(), etc. * Cleaned up the implementation of rasterio!() to use GDAL.jl's functions rather than doings its own ccall. --- src/constants.jl | 238 ++++++++++++++++++----------- src/context.jl | 10 +- src/dataset.jl | 28 ++-- src/ogr/feature.jl | 39 +++-- src/ogr/featuredefn.jl | 8 +- src/ogr/featurelayer.jl | 8 +- src/ogr/fielddefn.jl | 23 +-- src/ogr/geometry.jl | 24 +-- src/ogr/styletable.jl | 10 +- src/raster/colortable.jl | 2 +- src/raster/rasterattributetable.jl | 4 +- src/raster/rasterband.jl | 6 +- src/raster/rasterio.jl | 207 ++++++++++--------------- src/tables.jl | 4 +- src/types.jl | 215 ++++++++++++++++++++++---- src/utils.jl | 3 +- test/test_array.jl | 4 +- test/test_feature.jl | 10 +- test/test_fielddefn.jl | 26 ++-- test/test_gdal_tutorials.jl | 4 +- test/test_rasterattrtable.jl | 34 ++--- test/test_rasterband.jl | 8 +- test/test_styletable.jl | 10 +- test/test_types.jl | 64 ++++---- 24 files changed, 582 insertions(+), 407 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index 84f43207..e73b196a 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -1,53 +1,19 @@ -const StringList = Ptr{Cstring} - -CPLErr = GDAL.CPLErr -CPLXMLNodeType = GDAL.CPLXMLNodeType -GDALDataType = GDAL.GDALDataType -GDALAsyncStatusType = GDAL.GDALAsyncStatusType -GDALAccess = GDAL.GDALAccess -GDALRWFlag = GDAL.GDALRWFlag -GDALRIOResampleAlg = GDAL.GDALRIOResampleAlg -GDALColorInterp = GDAL.GDALColorInterp -GDALPaletteInterp = GDAL.GDALPaletteInterp -GDALRATFieldType = GDAL.GDALRATFieldType -GDALRATFieldUsage = GDAL.GDALRATFieldUsage -GDALTileOrganization = GDAL.GDALTileOrganization -GDALGridAlgorithm = GDAL.GDALGridAlgorithm -OGRwkbGeometryType = GDAL.OGRwkbGeometryType -OGRwkbVariant = GDAL.OGRwkbVariant -OGRFieldSubType = GDAL.OGRFieldSubType -OGRJustification = GDAL.OGRJustification -OGRSTClassId = GDAL.OGRSTClassId -OGRSTUnitId = GDAL.OGRSTUnitId -OGRSTPenParam = GDAL.OGRSTPenParam -OGRSTBrushParam = GDAL.OGRSTBrushParam -OGRSTSymbolParam = GDAL.OGRSTSymbolParam -OGRSTLabelParam = GDAL.OGRSTLabelParam -GDALResampleAlg = GDAL.GDALResampleAlg -GWKAverageOrModeAlg = GDAL.GWKAverageOrModeAlg -OGRAxisOrientation = GDAL.OGRAxisOrientation - -"return the corresponding `DataType` in julia" -const _JLTYPE = Dict{GDALDataType, DataType}( - GDAL.GDT_Unknown => Any, - GDAL.GDT_Byte => UInt8, - GDAL.GDT_UInt16 => UInt16, - GDAL.GDT_Int16 => Int16, - GDAL.GDT_UInt32 => UInt32, - GDAL.GDT_Int32 => Int32, - GDAL.GDT_Float32 => Float32, - GDAL.GDT_Float64 => Float64, -) - -const _GDALTYPE = Dict{DataType,GDALDataType}( - Any => GDAL.GDT_Unknown, - UInt8 => GDAL.GDT_Byte, - UInt16 => GDAL.GDT_UInt16, - Int16 => GDAL.GDT_Int16, - UInt32 => GDAL.GDT_UInt32, - Int32 => GDAL.GDT_Int32, - Float32 => GDAL.GDT_Float32, - Float64 => GDAL.GDT_Float64, +const StringList = Ptr{Cstring} + +@enum(GDALDataType, + GDT_Unknown = 0, + GDT_Byte = 1, + GDT_UInt16 = 2, + GDT_Int16 = 3, + GDT_UInt32 = 4, + GDT_Int32 = 5, + GDT_Float32 = 6, + GDT_Float64 = 7, + GDT_CInt16 = 8, + GDT_CInt32 = 9, + GDT_CFloat32 = 10, + GDT_CFloat64 = 11, + GDT_TypeCount = 12, ) @enum(OGRFieldType, @@ -65,29 +31,117 @@ const _GDALTYPE = Dict{DataType,GDALDataType}( OFTDateTime = 11, OFTInteger64 = 12, OFTInteger64List = 13, - OFTMaxType = 14, -) - -"return the corresponding `DataType` in julia" -const _FIELDTYPE = Dict{OGRFieldType, DataType}( - OFTInteger => Int32, - OFTIntegerList => Vector{Int32}, - OFTReal => Float64, - OFTRealList => Vector{Float64}, - OFTString => String, - OFTStringList => Vector{String}, - OFTWideString => Nothing, # deprecated - OFTWideStringList => Nothing, # deprecated - OFTBinary => Vector{UInt8}, - OFTDate => Dates.Date, - OFTTime => Dates.Time, - OFTDateTime => Dates.DateTime, - OFTInteger64 => Int64, - OFTInteger64List => Vector{Int64}, - # OFTMaxType => Nothing # unsupported -) - -@enum(WKBGeometryType, + OFTMaxType = 14, # 13 +) + +@enum(OGRFieldSubType, + OFSTNone = 0, + OFSTBoolean = 1, + OFSTInt16 = 2, + OFSTFloat32 = 3, + OFSTJSON = 4, + OFSTMaxSubType = 5, # 4 +) + +@enum(OGRJustification, + OJUndefined = 0, + OJLeft = 1, + OJRight = 2, +) + +@enum(GDALRATFieldType, + GFT_Integer = 0, + GFT_Real = 1, + GFT_String = 2, +) + +@enum(GDALRATFieldUsage, + GFU_Generic = 0, + GFU_PixelCount = 1, + GFU_Name = 2, + GFU_Min = 3, + GFU_Max = 4, + GFU_MinMax = 5, + GFU_Red = 6, + GFU_Green = 7, + GFU_Blue = 8, + GFU_Alpha = 9, + GFU_RedMin = 10, + GFU_GreenMin = 11, + GFU_BlueMin = 12, + GFU_AlphaMin = 13, + GFU_RedMax = 14, + GFU_GreenMax = 15, + GFU_BlueMax = 16, + GFU_AlphaMax = 17, + GFU_MaxCount = 18, +) + +@enum(GDALAccess, + GA_ReadOnly = 0, + GA_Update = 1, +) + +@enum(GDALRWFlag, + GF_Read = 0, + GF_Write = 1, +) + +@enum(GDALPaletteInterp, + GPI_Gray = 0, + GPI_RGB = 1, + GPI_CMYK = 2, + GPI_HLS = 3, +) + +@enum(GDALColorInterp, + GCI_Undefined = 0, + GCI_GrayIndex = 1, + GCI_PaletteIndex = 2, + GCI_RedBand = 3, + GCI_GreenBand = 4, + GCI_BlueBand = 5, + GCI_AlphaBand = 6, + GCI_HueBand = 7, + GCI_SaturationBand = 8, + GCI_LightnessBand = 9, + GCI_CyanBand = 10, + GCI_MagentaBand = 11, + GCI_YellowBand = 12, + GCI_BlackBand = 13, + GCI_YCbCr_YBand = 14, + GCI_YCbCr_CbBand = 15, + GCI_YCbCr_CrBand = 16, + GCI_Max = 17, # 16 +) + +@enum(GDALAsyncStatusType, + GARIO_PENDING = 0, + GARIO_UPDATE = 1, + GARIO_ERROR = 2, + GARIO_COMPLETE = 3, + GARIO_TypeCount = 4, +) + +@enum(OGRSTClassId, + OGRSTCNone = 0, + OGRSTCPen = 1, + OGRSTCBrush = 2, + OGRSTCSymbol = 3, + OGRSTCLabel = 4, + OGRSTCVector = 5, +) + +@enum(OGRSTUnitId, + OGRSTUGround = 0, + OGRSTUPixel = 1, + OGRSTUPoints = 2, + OGRSTUMM = 3, + OGRSTUCM = 4, + OGRSTUInches = 5, +) + +@enum(OGRwkbGeometryType, wkbUnknown = 0, wkbPoint = 1, wkbLineString = 2, @@ -161,25 +215,33 @@ const _FIELDTYPE = Dict{OGRFieldType, DataType}( wkbGeometryCollection25D = 70, ) -@enum(WKBByteOrder, +@enum(OGRwkbByteOrder, wkbXDR = 0, wkbNDR = 1, ) @enum(GDALOpenFlag, - OF_ReadOnly = GDAL.GDAL_OF_READONLY, # 0x00 - OF_Update = GDAL.GDAL_OF_UPDATE, # 0x01 - # OF_All = GDAL.GDAL_OF_ALL, # 0x00 - OF_Raster = GDAL.GDAL_OF_RASTER, # 0x02 - OF_Vector = GDAL.GDAL_OF_VECTOR, # 0x04 + OF_READONLY = GDAL.GDAL_OF_READONLY, # 0x00 + OF_UPDATE = GDAL.GDAL_OF_UPDATE, # 0x01 + # OF_All = GDAL.GDAL_OF_ALL, # 0x00 + OF_RASTER = GDAL.GDAL_OF_RASTER, # 0x02 + OF_VECTOR = GDAL.GDAL_OF_VECTOR, # 0x04 OF_GNM = GDAL.GDAL_OF_GNM, # 0x08 - OF_Kind_Mask = GDAL.GDAL_OF_KIND_MASK, # 0x1e - OF_Shared = GDAL.GDAL_OF_SHARED, # 0x20 - OF_Verbose_Error = GDAL.GDAL_OF_VERBOSE_ERROR, # 0x40 - OF_Internal = GDAL.GDAL_OF_INTERNAL, # 0x80 - # OF_DEFAULT_BLOCK_ACCESS = GDAL.GDAL_OF_DEFAULT_BLOCK_ACCESS, # 0 - OF_Array_Block_Access = GDAL.GDAL_OF_ARRAY_BLOCK_ACCESS, # 0x0100 - OF_Hashset_Block_Access = GDAL.GDAL_OF_HASHSET_BLOCK_ACCESS, # 0x0200 - # OF_RESERVED_1 = GDAL.GDAL_OF_RESERVED_1, # 0x0300 - OF_Block_Access_Mask = GDAL.GDAL_OF_BLOCK_ACCESS_MASK, # 0x0300 + OF_KIND_MASK = GDAL.GDAL_OF_KIND_MASK, # 0x1e + OF_SHARED = GDAL.GDAL_OF_SHARED, # 0x20 + OF_VERBOSE_ERROR = GDAL.GDAL_OF_VERBOSE_ERROR, # 0x40 + OF_INTERNAL = GDAL.GDAL_OF_INTERNAL, # 0x80 + # OF_DEFAULT_BLOCK_ACCESS = GDAL.GDAL_OF_DEFAULT_BLOCK_ACCESS, # 0 + OF_ARRAY_BLOCK_ACCESS = GDAL.GDAL_OF_ARRAY_BLOCK_ACCESS, # 0x0100 + OF_HASHSET_BLOCK_ACCESS = GDAL.GDAL_OF_HASHSET_BLOCK_ACCESS, # 0x0200 + # OF_RESERVED_1 = GDAL.GDAL_OF_RESERVED_1, # 0x0300 + OF_BLOCK_ACCESS_MASK = GDAL.GDAL_OF_BLOCK_ACCESS_MASK, # 0x0300 +) + +@enum(FieldValidation, + F_VAL_NULL = GDAL.OGR_F_VAL_NULL, # 0x0001 + F_VAL_GEOM_TYPE = GDAL.OGR_F_VAL_GEOM_TYPE, # 0x0002 + F_VAL_WIDTH = GDAL.OGR_F_VAL_WIDTH, # 0x0004 + F_VAL_ALLOW_NULL_WHEN_DEFAULT = GDAL.OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, # 0x0008 + F_VAL_ALLOW_DIFFERENT_GEOM_DIM = GDAL.OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, # 0x0010 ) diff --git a/src/context.jl b/src/context.jl index e0dc76a9..33bb8b90 100644 --- a/src/context.jl +++ b/src/context.jl @@ -105,7 +105,7 @@ function addfielddefn!( etype::OGRFieldType; nwidth::Integer = 0, nprecision::Integer = 0, - justify::OGRJustification = GDAL.OJUndefined, + justify::OGRJustification = OJUndefined, approx::Bool = false )::T where {T <: AbstractFeatureLayer} fielddefn = unsafe_createfielddefn(name, etype) @@ -123,7 +123,7 @@ function addfielddefn( etype::OGRFieldType; nwidth::Integer = 0, nprecision::Integer = 0, - justify::OGRJustification = GDAL.OJUndefined, + justify::OGRJustification = OJUndefined, approx::Bool = false ) fielddefn = unsafe_createfielddefn(name, etype) @@ -138,7 +138,7 @@ function addfielddefn( end """ - writegeomdefn!(layer::AbstractFeatureLayer, name, etype::WKBGeometryType, + writegeomdefn!(layer::AbstractFeatureLayer, name, etype::OGRwkbGeometryType, approx=false) Write a new geometry field on a layer. @@ -168,7 +168,7 @@ to the layer. function writegeomdefn!( layer::T, name::AbstractString, - etype::WKBGeometryType; + etype::OGRwkbGeometryType; approx::Bool = false )::T where {T <: AbstractFeatureLayer} geomdefn = unsafe_creategeomdefn(name, etype) @@ -181,7 +181,7 @@ function writegeomdefn( f::Function, layer::AbstractFeatureLayer, name::AbstractString, - etype::WKBGeometryType; + etype::OGRwkbGeometryType; approx::Bool = false ) geomdefn = unsafe_creategeomdefn(name, etype) diff --git a/src/dataset.jl b/src/dataset.jl index 8173f4d5..ff0998cc 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -207,7 +207,7 @@ function unsafe_create( options = StringList(C_NULL) )::Dataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - gdaltype(dtype), options) + convert(GDALDataType, dtype), options) return Dataset(result) end @@ -221,7 +221,7 @@ function unsafe_create( options = StringList(C_NULL) )::Dataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - gdaltype(dtype), options) + convert(GDALDataType, dtype), options) return Dataset(result) end @@ -266,7 +266,7 @@ function create( options = StringList(C_NULL) )::IDataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - gdaltype(dtype), options) + convert(GDALDataType, dtype), options) return IDataset(result) end @@ -280,12 +280,12 @@ function create( options = StringList(C_NULL) )::IDataset result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - gdaltype(dtype), options) + convert(GDALDataType, dtype), options) return IDataset(result) end """ - unsafe_read(filename; flags=OF_ReadOnly, alloweddrivers, options, + unsafe_read(filename; flags=OF_READONLY, alloweddrivers, options, siblingfiles) Open a raster file as a `Dataset`. @@ -304,7 +304,7 @@ driver on how to access a dataset. It should be in UTF-8 encoding. - Driver kind: GDAL_OF_RASTER for raster drivers, GDAL_OF_VECTOR for vector drivers. If none of the value is specified, both are implied. - - Access mode: `OF_ReadOnly` (exclusive) or `OF_Update`. + - Access mode: `OF_READONLY` (exclusive) or `OF_UPDATE`. - Shared mode: `GDAL_OF_SHARED`. If set, it allows the sharing of `Dataset` handles for a dataset with other callers that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will @@ -344,7 +344,7 @@ archive (see `VSIInstallTarFileHandler()`), or a HTTP / FTP server """ function unsafe_read( filename::AbstractString; - flags = OF_ReadOnly, + flags = OF_READONLY, alloweddrivers = StringList(C_NULL), options = StringList(C_NULL), siblingfiles = StringList(C_NULL) @@ -355,7 +355,7 @@ function unsafe_read( end """ - read(filename; flags=OF_ReadOnly, alloweddrivers, options, siblingfiles) + read(filename; flags=OF_READONLY, alloweddrivers, options, siblingfiles) Open a raster file @@ -364,13 +364,13 @@ Open a raster file ### Keyword Arguments * `flags`: a combination of `OF_*` flags (listed below) that may be - combined through the logical `|` operator. It defaults to `OF_ReadOnly`. + combined through the logical `|` operator. It defaults to `OF_READONLY`. - Driver kind: `OF_Raster` for raster drivers, `OF_Vector` for vector drivers. If none of the value is specified, both are implied. - - Access mode: `OF_ReadOnly` (exclusive) or `OF_Update`. + - Access mode: `OF_READONLY` (exclusive) or `OF_UPDATE`. - Shared mode: `OF_Shared`. If set, it allows the sharing of handles for a dataset with other callers that have set `OF_Shared`. - - Verbose error: `OF_Verbose_Error`. If set, a failed attempt to open the + - Verbose error: `OF_VERBOSE_ERROR`. If set, a failed attempt to open the file will lead to an error message to be reported. * `options`: additional format dependent options. @@ -391,7 +391,7 @@ The corresponding dataset. """ function read( filename::AbstractString; - flags = OF_ReadOnly | OF_Verbose_Error, + flags = OF_READONLY | OF_VERBOSE_ERROR, alloweddrivers = StringList(C_NULL), options = StringList(C_NULL), siblingfiles = StringList(C_NULL) @@ -401,8 +401,8 @@ function read( return IDataset(result) end -unsafe_update(filename::AbstractString; flags = OF_Update, kwargs...)::Dataset = - unsafe_read(filename; flags = OF_Update | flags, kwargs...) +unsafe_update(filename::AbstractString; flags = OF_UPDATE, kwargs...)::Dataset = + unsafe_read(filename; flags = OF_UPDATE | flags, kwargs...) """ width(dataset::AbstractDataset) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 02d8799e..f6655207 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -364,24 +364,23 @@ function getdefault(feature::Feature, i::Integer)::String return getdefault(getfielddefn(feature, i)) end -const _FETCHFIELD = Dict{OGRFieldType, Function}( - OFTInteger => asint, #0 - OFTIntegerList => asintlist, #1 - OFTReal => asdouble, #2 - OFTRealList => asdoublelist, #3 - OFTString => asstring, #4 - OFTStringList => asstringlist, #5 - # const OFTWideString = (UInt32)(6) - # const OFTWideStringList = (UInt32)(7) - OFTBinary => asbinary, #8 - OFTDate => asdatetime, #9 - OFTTime => asdatetime, #10 - OFTDateTime => asdatetime, #11 - OFTInteger64 => asint64, #12 - OFTInteger64List => asint64list #13 - ) - function getfield(feature::Feature, i::Integer) + _FETCHFIELD = Dict{OGRFieldType, Function}( + OFTInteger => asint, #0 + OFTIntegerList => asintlist, #1 + OFTReal => asdouble, #2 + OFTRealList => asdoublelist, #3 + OFTString => asstring, #4 + OFTStringList => asstringlist, #5 + # const OFTWideString = (UInt32)(6) + # const OFTWideStringList = (UInt32)(7) + OFTBinary => asbinary, #8 + OFTDate => asdatetime, #9 + OFTTime => asdatetime, #10 + OFTDateTime => asdatetime, #11 + OFTInteger64 => asint64, #12 + OFTInteger64List => asint64list, #13 + ) return if isfieldset(feature, i) _fieldtype = gettype(getfielddefn(feature, i)) _fetchfield = get(_FETCHFIELD, _fieldtype, getdefault) @@ -588,7 +587,7 @@ end function getgeom( feature::Feature, - name::Union{AbstractString, Symbol} = "" + name::Union{AbstractString, Symbol} )::IGeometry i = findgeomindex(feature, name) return if i == -1 @@ -600,7 +599,7 @@ end function unsafe_getgeom( feature::Feature, - name::Union{AbstractString, Symbol} = "" + name::Union{AbstractString, Symbol} )::Geometry i = findgeomindex(feature, name) return if i == -1 @@ -852,5 +851,5 @@ fails, then it will fail for all interpretations). ### Returns `true` if all enabled validation tests pass. """ -validate(feature::Feature, flags::Integer, emiterror::Bool)::Bool = +validate(feature::Feature, flags::FieldValidation, emiterror::Bool)::Bool = Bool(GDAL.ogr_f_validate(feature.ptr, flags, emiterror)) diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index 55666146..a2a3aad7 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -195,11 +195,11 @@ For layers with multiple geometry fields, this method only returns the geometry type of the first geometry column. For other columns, use `OGR_GFld_GetType(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer), i))`. """ -getgeomtype(featuredefn::AbstractFeatureDefn)::WKBGeometryType = - gdaltype(GDAL.ogr_fd_getgeomtype(featuredefn.ptr)) +getgeomtype(featuredefn::AbstractFeatureDefn)::OGRwkbGeometryType = + GDAL.ogr_fd_getgeomtype(featuredefn.ptr) """ - setgeomtype!(featuredefn::FeatureDefn, etype::WKBGeometryType) + setgeomtype!(featuredefn::FeatureDefn, etype::OGRwkbGeometryType) Assign the base geometry type for the passed layer (same as the fd). @@ -210,7 +210,7 @@ have been created against this definition. """ function setgeomtype!( featuredefn::FeatureDefn, - etype::WKBGeometryType + etype::OGRwkbGeometryType )::FeatureDefn GDAL.ogr_fd_setgeomtype(featuredefn.ptr, etype) return featuredefn diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index 5c7fa2e4..c75d4dd0 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -29,7 +29,7 @@ This function attempts to create a new layer on the dataset with the indicated function createlayer(; name::AbstractString = "", dataset::AbstractDataset = create(getdriver("Memory")), - geom::WKBGeometryType = wkbUnknown, + geom::OGRwkbGeometryType = wkbUnknown, spatialref::AbstractSpatialRef = SpatialRef(), options = StringList(C_NULL) )::IFeatureLayer @@ -44,7 +44,7 @@ end function unsafe_createlayer(; name::AbstractString = "", dataset::AbstractDataset = create(getdriver("Memory")), - geom::WKBGeometryType = wkbUnknown, + geom::OGRwkbGeometryType = wkbUnknown, spatialref::AbstractSpatialRef = SpatialRef(), options = StringList(C_NULL) )::FeatureLayer @@ -102,8 +102,8 @@ getname(layer::AbstractFeatureLayer)::String = GDAL.ogr_l_getname(layer.ptr) Return the layer geometry type. """ -getgeomtype(layer::AbstractFeatureLayer)::WKBGeometryType = - gdaltype(GDAL.ogr_l_getgeomtype(layer.ptr)) +getgeomtype(layer::AbstractFeatureLayer)::OGRwkbGeometryType = + GDAL.ogr_l_getgeomtype(layer.ptr) """ getspatialfilter(layer::AbstractFeatureLayer) diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index 588226c8..08edd413 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -32,7 +32,7 @@ getname(fielddefn::AbstractFieldDefn)::String = "Fetch the type of this field." gettype(fielddefn::AbstractFieldDefn)::OGRFieldType = - gdaltype(GDAL.ogr_fld_gettype(fielddefn.ptr)) + GDAL.ogr_fld_gettype(fielddefn.ptr) "Set the type of this field." function settype!(fielddefn::FieldDefn, etype::OGRFieldType)::FieldDefn @@ -51,7 +51,7 @@ Fetch subtype of this field. ### Returns field subtype. """ -getsubtype(fielddefn::AbstractFieldDefn)::GDAL.OGRFieldSubType = +getsubtype(fielddefn::AbstractFieldDefn)::OGRFieldSubType = GDAL.ogr_fld_getsubtype(fielddefn.ptr) """ @@ -66,7 +66,10 @@ OGRFeatureDefn. * `fielddefn`: handle to the field definition to set type to. * `subtype`: the new field subtype. """ -function setsubtype!(fielddefn::FieldDefn, subtype::OGRFieldSubType)::FieldDefn +function setsubtype!( + fielddefn::FieldDefn, + subtype::OGRFieldSubType + )::FieldDefn GDAL.ogr_fld_setsubtype(fielddefn.ptr, subtype) return fielddefn end @@ -78,7 +81,7 @@ Get the justification for this field. Note: no driver is know to use the concept of field justification. """ -getjustify(fielddefn::AbstractFieldDefn)::GDAL.OGRJustification = +getjustify(fielddefn::AbstractFieldDefn)::OGRJustification = GDAL.ogr_fld_getjustify(fielddefn.ptr) """ @@ -161,7 +164,7 @@ function setparams!( etype::OGRFieldType; nwidth::Integer = 0, nprecision::Integer = 0, - justify::OGRJustification = GDAL.OJUndefined + justify::OGRJustification = OJUndefined )::FieldDefn GDAL.ogr_fld_set(fielddefn.ptr, name, etype, nwidth, nprecision, justify) return fielddefn @@ -270,13 +273,13 @@ isdefaultdriverspecific(fielddefn::AbstractFieldDefn)::Bool = Bool(GDAL.ogr_fld_isdefaultdriverspecific(fielddefn.ptr)) """ - unsafe_creategeomdefn(name::AbstractString, etype::WKBGeometryType) + unsafe_creategeomdefn(name::AbstractString, etype::OGRwkbGeometryType) Create a new field geometry definition. """ function unsafe_creategeomdefn( name::AbstractString, - etype::WKBGeometryType + etype::OGRwkbGeometryType )::GeomFieldDefn return GeomFieldDefn(GDAL.ogr_gfld_create(name, etype)) end @@ -306,13 +309,13 @@ getname(geomdefn::AbstractGeomFieldDefn)::String = GDAL.ogr_gfld_getnameref(geomdefn.ptr) "Fetch geometry type of this field." -gettype(geomdefn::AbstractGeomFieldDefn)::WKBGeometryType = - gdaltype(GDAL.ogr_gfld_gettype(geomdefn.ptr)) +gettype(geomdefn::AbstractGeomFieldDefn)::OGRwkbGeometryType = + GDAL.ogr_gfld_gettype(geomdefn.ptr) "Set the geometry type of this field." function settype!( geomdefn::GeomFieldDefn, - etype::WKBGeometryType + etype::OGRwkbGeometryType )::GeomFieldDefn GDAL.ogr_gfld_settype(geomdefn.ptr, etype) return geomdefn diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index a54ca9d7..33f78768 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -104,21 +104,21 @@ function unsafe_clone(geom::AbstractGeometry)::Geometry end """ - creategeom(geomtype::WKBGeometryType) + creategeom(geomtype::OGRwkbGeometryType) Create an empty geometry of desired type. This is equivalent to allocating the desired geometry with new, but the allocation is guaranteed to take place in the context of the GDAL/OGR heap. """ -creategeom(geomtype::WKBGeometryType)::IGeometry = +creategeom(geomtype::OGRwkbGeometryType)::IGeometry = IGeometry(GDAL.ogr_g_creategeometry(geomtype)) -unsafe_creategeom(geomtype::WKBGeometryType)::Geometry = +unsafe_creategeom(geomtype::OGRwkbGeometryType)::Geometry = Geometry(GDAL.ogr_g_creategeometry(geomtype)) """ - forceto(geom::AbstractGeometry, targettype::WKBGeometryType, [options]) + forceto(geom::AbstractGeometry, targettype::OGRwkbGeometryType, [options]) Tries to force the provided geometry to the specified geometry type. @@ -139,7 +139,7 @@ The passed in geometry is cloned and a new one returned. """ function forceto( geom::AbstractGeometry, - targettype::WKBGeometryType, + targettype::OGRwkbGeometryType, options = StringList(C_NULL) )::IGeometry return IGeometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, @@ -148,7 +148,7 @@ end function unsafe_forceto( geom::AbstractGeometry, - targettype::WKBGeometryType, + targettype::OGRwkbGeometryType, options = StringList(C_NULL) )::Geometry return Geometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, @@ -232,7 +232,7 @@ function boundingbox(geom::AbstractGeometry)::IGeometry end """ - toWKB(geom::AbstractGeometry, order::WKBByteOrder = wkbNDR) + toWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = wkbNDR) Convert a geometry well known binary format. @@ -242,7 +242,7 @@ Convert a geometry well known binary format. """ function toWKB( geom::AbstractGeometry, - order::WKBByteOrder = wkbNDR + order::OGRwkbByteOrder = wkbNDR )::Vector{Cuchar} buffer = Vector{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttowkb(geom.ptr, order, buffer) @@ -251,7 +251,7 @@ function toWKB( end """ - toISOWKB(geom::AbstractGeometry, order::WKBByteOrder = wkbNDR) + toISOWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = wkbNDR) Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. @@ -261,7 +261,7 @@ Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. """ function toISOWKB( geom::AbstractGeometry, - order::WKBByteOrder = wkbNDR + order::OGRwkbByteOrder = wkbNDR )::Vector{Cuchar} buffer = Array{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttoisowkb(geom.ptr, order, buffer) @@ -309,8 +309,8 @@ end Fetch geometry type code """ -getgeomtype(geom::AbstractGeometry)::WKBGeometryType = - gdaltype(GDAL.ogr_g_getgeometrytype(geom.ptr)) +getgeomtype(geom::AbstractGeometry)::OGRwkbGeometryType = + GDAL.ogr_g_getgeometrytype(geom.ptr) """ geomname(geom::AbstractGeometry) diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index 3210f8f4..7bbd7f04 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -10,9 +10,9 @@ OGRStyleMgr factory. an handle to the new style manager object. """ function unsafe_createstylemanager( - styletable::GDAL.OGRStyleTableH = C_NULL + styletable::StyleTable = StyleTable() )::StyleManager - return StyleManager(GDAL.ogr_sm_create(styletable)) + return StyleManager(GDAL.ogr_sm_create(styletable.ptr)) end """ @@ -181,7 +181,8 @@ Determine type of Style Tool. the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2), OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the OGRStyleToolH is invalid. """ -gettype(styletool::StyleTool)::GDAL.OGRSTClassId = GDAL.ogr_st_gettype(styletool.ptr) +gettype(styletool::StyleTool)::OGRSTClassId = + GDAL.ogr_st_gettype(styletool.ptr) """ getunit(styletool::StyleTool) @@ -194,7 +195,8 @@ Get Style Tool units. ### Returns the style tool units. """ -getunit(styletool::StyleTool)::GDAL.OGRSTUnitId = GDAL.ogr_st_getunit(styletool.ptr) +getunit(styletool::StyleTool)::OGRSTUnitId = + GDAL.ogr_st_getunit(styletool.ptr) """ setunit!(styletool::StyleTool, newunit::OGRSTUnitId, scale::Real) diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index 5ec879ec..8bfb211b 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -29,7 +29,7 @@ Fetch palette interpretation. ### Returns palette interpretation enumeration value, usually `GPI_RGB`. """ -paletteinterp(ct::ColorTable)::GDAL.GDALPaletteInterp = +paletteinterp(ct::ColorTable)::GDALPaletteInterp = GDAL.gdalgetpaletteinterpretation(ct.ptr) """ diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 9f081e0e..81f0520f 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -47,7 +47,7 @@ columnname(rat::RasterAttrTable, i::Integer)::String = Fetch column usage value. """ -columnusage(rat::RasterAttrTable, i::Integer)::GDAL.GDALRATFieldUsage = +columnusage(rat::RasterAttrTable, i::Integer)::GDALRATFieldUsage = GDAL.gdalratgetusageofcol(rat.ptr, i) """ @@ -61,7 +61,7 @@ Fetch column type. ### Returns column type or `GFT_Integer` if the column index is illegal. """ -columntype(rat::RasterAttrTable, i::Integer)::GDAL.GDALRATFieldType = +columntype(rat::RasterAttrTable, i::Integer)::GDALRATFieldType = GDAL.gdalratgettypeofcol(rat.ptr, i) """ diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 06cb0ff2..1e39305d 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -59,9 +59,9 @@ height(band::AbstractRasterBand)::Integer = GDAL.gdalgetrasterbandysize(band.ptr """ accessflag(band::AbstractRasterBand) -Return the access flag (e.g. `OF_ReadOnly` or `OF_Update`) for this band. +Return the access flag (e.g. `OF_READONLY` or `OF_UPDATE`) for this band. """ -accessflag(band::AbstractRasterBand)::GDAL.GDALAccess = +accessflag(band::AbstractRasterBand)::GDALAccess = GDAL.gdalgetrasteraccess(band.ptr) """ @@ -349,7 +349,7 @@ unsafe_sampleoverview(band::AbstractRasterBand, nsamples::Integer)::RasterBand = Color Interpretation value for band """ -getcolorinterp(band::AbstractRasterBand)::GDAL.GDALColorInterp = +getcolorinterp(band::AbstractRasterBand)::GDALColorInterp = GDAL.gdalgetrastercolorinterpretation(band.ptr) """ diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 56895567..eec4712f 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -32,8 +32,8 @@ boundaries\" as returned by `blocksize()`, or use the `readblock!()` and `UnitRange{<:Integer}`, such as 2:9. * `cols` A continuous range of columns expressed as a `UnitRange{<:Integer}`, such as 2:9. -* `access` Either `GDAL.GF_Read` to read a region of data, or - `GDAL.GF_Write` to write a region of data. +* `access` Either `GF_Read` to read a region of data, or + `GF_Write` to write a region of data. * `xoffset` The pixel offset to the top left corner of the region to be accessed. It will be `0` (default) to start from the left. * `yoffset` The line offset to the top left corner of the region to be @@ -69,10 +69,10 @@ function rasterio!( dataset::AbstractDataset, buffer::T, bands, - access::GDALRWFlag = GDAL.GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0 )::T where {T <: Array{<:Real, 3}} rasterio!(dataset, buffer, bands, 0, 0, size(buffer, 1), size(buffer, 2), access, pxspace, linespace, bandspace) @@ -85,10 +85,10 @@ function rasterio!( bands, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, - access::GDALRWFlag = GDAL.GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0 )::T where {T <: Array{<:Real, 3}} xsize = cols[end] - cols[1] + 1; xsize < 0 && error("invalid window width") ysize = rows[end] - rows[1] + 1; ysize < 0 && error("invalid window height") @@ -97,12 +97,44 @@ function rasterio!( return buffer end +function rasterio!( + dataset::AbstractDataset, + buffer::Array{T, 3}, + bands, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, + extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) + )::Array{T, 3} where {T <: Any} + # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg + # structure with additional arguments to specify resampling and + # progress callback, or `NULL` for default behaviour. The + # `GDAL_RASTERIO_RESAMPLING` configuration option can also be + # defined to override the default resampling to one of `BILINEAR`, + # `CUBIC`, `CUBICSPLINE`, `LANCZOS`, `AVERAGE` or `MODE`. + (dataset == C_NULL) && error("Can't read NULL dataset") + xbsize, ybsize, zbsize = size(buffer) + nband = length(bands) + bands = isa(bands, Vector{Cint}) ? bands : Cint.(collect(bands)) + @assert nband == zbsize + result = GDAL.gdaldatasetrasterioex(dataset.ptr, access, xoffset, yoffset, + xsize, ysize, pointer(buffer), xbsize, ybsize, convert(GDALDataType, T), + nband, pointer(bands), pxspace, linespace, bandspace, extraargs) + @cplerr result "Access in DatasetRasterIO failed." + return buffer +end + function rasterio!( rasterband::AbstractRasterBand, buffer::T, - access::GDALRWFlag = GDAL.GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0 )::T where {T <: Matrix{<:Real}} rasterio!(rasterband, buffer, 0, 0, width(rasterband), height(rasterband), access, pxspace, linespace) @@ -114,9 +146,9 @@ function rasterio!( buffer::T, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, - access::GDALRWFlag = GDAL.GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0 )::T where {T <: Matrix{<:Real}} xsize = length(cols); xsize < 1 && error("invalid window width") ysize = length(rows); ysize < 1 && error("invalid window height") @@ -125,11 +157,38 @@ function rasterio!( return buffer end +function rasterio!( + rasterband::AbstractRasterBand, + buffer::Matrix{T}, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) + )::Matrix{T} where {T <: Any} + # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg + # structure with additional arguments to specify resampling and + # progress callback, or `NULL` for default behaviour. The + # `GDAL_RASTERIO_RESAMPLING` configuration option can also be + # defined to override the default resampling to one of `BILINEAR`, + # `CUBIC`, `CUBICSPLINE`, `LANCZOS`, `AVERAGE` or `MODE`. + (rasterband == C_NULL) && error("Can't read NULL rasterband") + xbsize, ybsize = size(buffer) + result = GDAL.gdalrasterioex(rasterband.ptr, access, xoffset, yoffset, + xsize, ysize, pointer(buffer), xbsize, ybsize, convert(GDALDataType, T), + pxspace, linespace, extraargs) + @cplerr result "Access in RasterIO failed." + return buffer +end + function read!( rb::AbstractRasterBand, buffer::T )::T where {T <: Matrix{<:Real}} - rasterio!(rb, buffer, GDAL.GF_Read) + rasterio!(rb, buffer, GF_Read) return buffer end @@ -184,7 +243,7 @@ function write!( rb::AbstractRasterBand, buffer::T )::T where {T <: Matrix{<:Real}} - rasterio!(rb, buffer, GDAL.GF_Write) + rasterio!(rb, buffer, GF_Write) return buffer end @@ -196,7 +255,7 @@ function write!( xsize::Integer, ysize::Integer )::T where {T <: Matrix{<:Real}} - rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize, GDAL.GF_Write) + rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize, GF_Write) return buffer end @@ -206,7 +265,7 @@ function write!( rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} )::T where {T <: Matrix{<:Real}} - rasterio!(rb, buffer, rows, cols, GDAL.GF_Write) + rasterio!(rb, buffer, rows, cols, GF_Write) return buffer end @@ -224,7 +283,7 @@ function read!( buffer::T, indices )::T where {T <: Array{<:Real, 3}} - rasterio!(dataset, buffer, indices, GDAL.GF_Read) + rasterio!(dataset, buffer, indices, GF_Read) return buffer end @@ -234,7 +293,7 @@ function read!( )::T where {T <: Array{<:Real, 3}} nband = nraster(dataset) @assert size(buffer, 3) == nband - rasterio!(dataset, buffer, collect(Cint, 1:nband), GDAL.GF_Read) + rasterio!(dataset, buffer, collect(Cint, 1:nband), GF_Read) return buffer end @@ -367,7 +426,7 @@ function write!( buffer::Array{<:Real, 3}, indices )::T where {T <: AbstractDataset} - rasterio!(dataset, buffer, indices, GDAL.GF_Write) + rasterio!(dataset, buffer, indices, GF_Write) return dataset end @@ -394,7 +453,7 @@ function write!( ysize::Integer )::T where {T <: AbstractDataset} rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize, - GDAL.GF_Write) + GF_Write) return dataset end @@ -416,108 +475,10 @@ function write!( rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} )::T where {T <: AbstractDataset} - rasterio!(dataset, buffer, indices, rows, cols, GDAL.GF_Write) + rasterio!(dataset, buffer, indices, rows, cols, GF_Write) return dataset end -for (T,GT) in _GDALTYPE - eval(quote - function rasterio!( - dataset::AbstractDataset, - buffer::Array{$T, 3}, - bands, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, - access::GDALRWFlag = GDAL.GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0, - extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) - )::Array{$T, 3} - # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg - # structure with additional arguments to specify resampling and - # progress callback, or `NULL` for default behaviour. The - # `GDAL_RASTERIO_RESAMPLING` configuration option can also be - # defined to override the default resampling to one of `BILINEAR`, - # `CUBIC`, `CUBICSPLINE`, `LANCZOS`, `AVERAGE` or `MODE`. - (dataset == C_NULL) && error("Can't read invalid rasterband") - xbsize, ybsize, zbsize = size(buffer) - nband = length(bands) - bands = isa(bands, Vector{Cint}) ? bands : Cint.(collect(bands)) - @assert nband == zbsize - result = ccall((:GDALDatasetRasterIOEx,GDAL.libgdal), - GDAL.CPLErr, # return type - (GDAL.GDALDatasetH, - GDAL.GDALRWFlag, # access - Cint, # xoffset - Cint, # yoffset - Cint, # xsize - Cint, # ysize - Ptr{Cvoid}, # poiter to buffer - Cint, # xbsize - Cint, # ybsize - GDAL.GDALDataType, - Cint, # number of bands - Ptr{Cint}, # bands - GDAL.GSpacing, # pxspace - GDAL.GSpacing, # linespace - GDAL.GSpacing, # bandspace - Ptr{GDAL.GDALRasterIOExtraArg} # extra args - ), - dataset.ptr, - access, - xoffset, - yoffset, - xsize, - ysize, - pointer(buffer), - xbsize, - ybsize, - $GT, - nband, - pointer(bands), - pxspace, - linespace, - bandspace, - extraargs) - @cplerr result "Access in DatasetRasterIO failed." - return buffer - end - - function rasterio!( - rasterband::AbstractRasterBand, - buffer::Matrix{$T}, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, - access::GDALRWFlag = GDAL.GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) - )::Matrix{$T} - # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg - # structure with additional arguments to specify resampling and - # progress callback, or `NULL` for default behaviour. The - # `GDAL_RASTERIO_RESAMPLING` configuration option can also be - # defined to override the default resampling to one of `BILINEAR`, - # `CUBIC`, `CUBICSPLINE`, `LANCZOS`, `AVERAGE` or `MODE`. - (rasterband == C_NULL) && error("Can't read invalid rasterband") - xbsize, ybsize = size(buffer) - result = ccall((:GDALRasterIOEx,GDAL.libgdal),GDAL.CPLErr, - (GDAL.GDALRasterBandH,GDAL.GDALRWFlag,Cint,Cint,Cint,Cint, - Ptr{Cvoid},Cint,Cint,GDAL.GDALDataType,GDAL.GSpacing, - GDAL.GSpacing,Ptr{GDAL.GDALRasterIOExtraArg}),rasterband.ptr, - access,xoffset,yoffset,xsize,ysize,pointer(buffer),xbsize, - ybsize,$GT,pxspace,linespace,extraargs) - @cplerr result "Access in RasterIO failed." - return buffer - end - end) -end - """ readblock!(rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, buffer) diff --git a/src/tables.jl b/src/tables.jl index 58dde05b..f802e582 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -11,7 +11,9 @@ function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema field_names, geom_names, featuredefn, fielddefns = schema_names(layer) ngeom = ArchGDAL.ngeom(featuredefn) geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) - field_types = (datatype(gettype(fielddefn)) for fielddefn in fielddefns) + field_types = ( + convert(DataType, gettype(fielddefn)) for fielddefn in fielddefns + ) geom_types = (IGeometry for i in 1:ngeom) Tables.Schema( (field_names..., geom_names...), diff --git a/src/types.jl b/src/types.jl index d8539f11..eb698e00 100644 --- a/src/types.jl +++ b/src/types.jl @@ -95,10 +95,14 @@ end mutable struct StyleManager ptr::GDAL.OGRStyleMgrH + + StyleManager(ptr::GDAL.OGRStyleMgrH = C_NULL) = new(ptr) end mutable struct StyleTable ptr::GDAL.OGRStyleTableH + + StyleTable(ptr::GDAL.OGRStyleTableH = C_NULL) = new(ptr) end mutable struct StyleTool @@ -147,10 +151,14 @@ mutable struct RasterBand{T} <: AbstractRasterBand{T} ptr::GDAL.GDALRasterBandH end +"Fetch the pixel data type for this band." +pixeltype(ptr::GDAL.GDALRasterBandH)::DataType = + convert(GDALDataType, GDAL.gdalgetrasterdatatype(ptr)) + function RasterBand( ptr::GDAL.GDALRasterBandH - )::RasterBand{datatype(GDAL.gdalgetrasterdatatype(ptr))} - return RasterBand{datatype(GDAL.gdalgetrasterdatatype(ptr))}(ptr) + )::RasterBand{pixeltype(ptr)} + return RasterBand{pixeltype(ptr)}(ptr) end mutable struct IRasterBand{T} <: AbstractRasterBand{T} @@ -170,9 +178,8 @@ end function IRasterBand( ptr::GDAL.GDALRasterBandH; ownedby = Dataset() - )::IRasterBand{datatype(GDAL.gdalgetrasterdatatype(ptr))} - T = datatype(GDAL.gdalgetrasterdatatype(ptr)) - return IRasterBand{T}(ptr, ownedby = ownedby) + )::IRasterBand{pixeltype(ptr)} + return IRasterBand{pixeltype(ptr)}(ptr, ownedby = ownedby) end mutable struct SpatialRef <: AbstractSpatialRef @@ -211,20 +218,32 @@ mutable struct ColorTable ptr::GDAL.GDALColorTableH end -"return the corresponding `DataType` in julia" -datatype(gt::GDALDataType)::DataType = get(_JLTYPE, gt) do - error("Unknown GDALDataType: $gt") -end - -"return the corresponding `GDAL.GDALDataType`" -gdaltype(dt::DataType)::GDAL.GDALDataType = get(_GDALTYPE, dt) do - error("Unknown DataType: $dt") -end +eval(@gdalenum(GDALDataType::GDAL.GDALDataType, + GDT_Unknown::GDAL.GDT_Unknown, + GDT_Byte::GDAL.GDT_Byte, + GDT_UInt16::GDAL.GDT_UInt16, + GDT_Int16::GDAL.GDT_Int16, + GDT_UInt32::GDAL.GDT_UInt32, + GDT_Int32::GDAL.GDT_Int32, + GDT_Float32::GDAL.GDT_Float32, + GDT_Float64::GDAL.GDT_Float64, + GDT_CInt16::GDAL.GDT_CInt16, + GDT_CInt32::GDAL.GDT_CInt32, + GDT_CFloat32::GDAL.GDT_CFloat32, + GDT_CFloat64::GDAL.GDT_CFloat64, + GDT_TypeCount::GDAL.GDT_TypeCount, +)) -"return the corresponding `DataType` in julia" -datatype(ft::OGRFieldType)::DataType = get(_FIELDTYPE, ft) do - error("Unknown OGRFieldType: $ft") -end +eval(@gdalenum(GDALDataType::DataType, + GDT_Unknown::Any, + GDT_Byte::UInt8, + GDT_UInt16::UInt16, + GDT_Int16::Int16, + GDT_UInt32::UInt32, + GDT_Int32::Int32, + GDT_Float32::Float32, + GDT_Float64::Float64, +)) eval(@gdalenum(OGRFieldType::GDAL.OGRFieldType, OFTInteger::GDAL.OFTInteger, @@ -240,10 +259,140 @@ eval(@gdalenum(OGRFieldType::GDAL.OGRFieldType, OFTTime::GDAL.OFTTime, OFTDateTime::GDAL.OFTDateTime, OFTInteger64::GDAL.OFTInteger64, - OFTInteger64List::GDAL.OFTInteger64List + OFTInteger64List::GDAL.OFTInteger64List, +)) + +eval(@gdalenum(OGRFieldType::DataType, + OFTInteger::Int32, + OFTIntegerList::Vector{Int32}, + OFTReal::Float64, + OFTRealList::Vector{Float64}, + OFTString::String, + OFTStringList::Vector{String}, + OFTWideString::Nothing, + OFTWideStringList::Nothing, + OFTBinary::Vector{UInt8}, + OFTDate::Dates.Date, + OFTTime::Dates.Time, + OFTDateTime::Dates.DateTime, + OFTInteger64::Int64, + OFTInteger64List::Vector{Int64}, +)) + +eval(@gdalenum(OGRFieldSubType::GDAL.OGRFieldSubType, + OFSTNone::GDAL.OFSTNone, + OFSTBoolean::GDAL.OFSTBoolean, + OFSTInt16::GDAL.OFSTInt16, + OFSTFloat32::GDAL.OFSTFloat32, + OFSTJSON::GDAL.OFSTJSON, +)) + +eval(@gdalenum(OGRFieldSubType::DataType, + OFSTNone::Nothing, + OFSTBoolean::Bool, + OFSTInt16::Int16, + OFSTFloat32::Float32, + OFSTJSON::String, +)) + +eval(@gdalenum(OGRJustification::GDAL.OGRJustification, + OJUndefined::GDAL.OJUndefined, + OJLeft::GDAL.OJLeft, + OJRight::GDAL.OJRight, +)) + +eval(@gdalenum(GDALRATFieldType::GDAL.GDALRATFieldType, + GFT_Integer::GDAL.GFT_Integer, + GFT_Real::GDAL.GFT_Real, + GFT_String::GDAL.GFT_String, +)) + +eval(@gdalenum(GDALRATFieldUsage::GDAL.GDALRATFieldUsage, + GFU_Generic::GDAL.GFU_Generic, + GFU_PixelCount::GDAL.GFU_PixelCount, + GFU_Name::GDAL.GFU_Name, + GFU_Min::GDAL.GFU_Min, + GFU_Max::GDAL.GFU_Max, + GFU_MinMax::GDAL.GFU_MinMax, + GFU_Red::GDAL.GFU_Red, + GFU_Green::GDAL.GFU_Green, + GFU_Blue::GDAL.GFU_Blue, + GFU_Alpha::GDAL.GFU_Alpha, + GFU_RedMin::GDAL.GFU_RedMin, + GFU_GreenMin::GDAL.GFU_GreenMin, + GFU_BlueMin::GDAL.GFU_BlueMin, + GFU_AlphaMin::GDAL.GFU_AlphaMin, + GFU_RedMax::GDAL.GFU_RedMax, + GFU_GreenMax::GDAL.GFU_GreenMax, + GFU_BlueMax::GDAL.GFU_BlueMax, + GFU_AlphaMax::GDAL.GFU_AlphaMax, + GFU_MaxCount::GDAL.GFU_MaxCount, +)) + +eval(@gdalenum(GDALAccess::GDAL.GDALAccess, + GA_ReadOnly::GDAL.GA_ReadOnly, + GA_Update::GDAL.GA_Update, +)) + +eval(@gdalenum(GDALRWFlag::GDAL.GDALRWFlag, + GF_Read::GDAL.GF_Read, + GF_Write::GDAL.GF_Write, +)) + +eval(@gdalenum(GDALPaletteInterp::GDAL.GDALPaletteInterp, + GPI_Gray::GDAL.GPI_Gray, + GPI_RGB::GDAL.GPI_RGB, + GPI_CMYK::GDAL.GPI_CMYK, + GPI_HLS::GDAL.GPI_HLS, )) -eval(@gdalenum(WKBGeometryType::GDAL.OGRwkbGeometryType, +eval(@gdalenum(GDALColorInterp::GDAL.GDALColorInterp, + GCI_Undefined::GDAL.GCI_Undefined, + GCI_GrayIndex::GDAL.GCI_GrayIndex, + GCI_PaletteIndex::GDAL.GCI_PaletteIndex, + GCI_RedBand::GDAL.GCI_RedBand, + GCI_GreenBand::GDAL.GCI_GreenBand, + GCI_BlueBand::GDAL.GCI_BlueBand, + GCI_AlphaBand::GDAL.GCI_AlphaBand, + GCI_HueBand::GDAL.GCI_HueBand, + GCI_SaturationBand::GDAL.GCI_SaturationBand, + GCI_LightnessBand::GDAL.GCI_LightnessBand, + GCI_CyanBand::GDAL.GCI_CyanBand, + GCI_MagentaBand::GDAL.GCI_MagentaBand, + GCI_YellowBand::GDAL.GCI_YellowBand, + GCI_BlackBand::GDAL.GCI_BlackBand, + GCI_YCbCr_YBand::GDAL.GCI_YCbCr_YBand, + GCI_YCbCr_CbBand::GDAL.GCI_YCbCr_CbBand, + GCI_YCbCr_CrBand::GDAL.GCI_YCbCr_CrBand, +)) + +eval(@gdalenum(GDALAsyncStatusType::GDAL.GDALAsyncStatusType, + GARIO_PENDING::GDAL.GARIO_PENDING, + GARIO_UPDATE::GDAL.GARIO_UPDATE, + GARIO_ERROR::GDAL.GARIO_ERROR, + GARIO_COMPLETE::GDAL.GARIO_COMPLETE, + GARIO_TypeCount::GDAL.GARIO_TypeCount, +)) + +eval(@gdalenum(OGRSTClassId::GDAL.OGRSTClassId, + OGRSTCNone::GDAL.OGRSTCNone, + OGRSTCPen::GDAL.OGRSTCPen, + OGRSTCBrush::GDAL.OGRSTCBrush, + OGRSTCSymbol::GDAL.OGRSTCSymbol, + OGRSTCLabel::GDAL.OGRSTCLabel, + OGRSTCVector::GDAL.OGRSTCVector, +)) + +eval(@gdalenum(OGRSTUnitId::GDAL.OGRSTUnitId, + OGRSTUGround::GDAL.OGRSTUGround, + OGRSTUPixel::GDAL.OGRSTUPixel, + OGRSTUPoints::GDAL.OGRSTUPoints, + OGRSTUMM::GDAL.OGRSTUMM, + OGRSTUCM::GDAL.OGRSTUCM, + OGRSTUInches::GDAL.OGRSTUInches, +)) + +eval(@gdalenum(OGRwkbGeometryType::GDAL.OGRwkbGeometryType, wkbUnknown::GDAL.wkbUnknown, wkbPoint::GDAL.wkbPoint, wkbLineString::GDAL.wkbLineString, @@ -317,16 +466,20 @@ eval(@gdalenum(WKBGeometryType::GDAL.OGRwkbGeometryType, wkbGeometryCollection25D::GDAL.wkbGeometryCollection25D, )) -eval(@gdalenum(WKBByteOrder::GDAL.OGRwkbByteOrder, +eval(@gdalenum(OGRwkbByteOrder::GDAL.OGRwkbByteOrder, wkbXDR::GDAL.wkbXDR, wkbNDR::GDAL.wkbNDR, )) import Base.| -|(x::GDALOpenFlag,y::UInt8) = UInt8(x) | y -|(x::UInt8,y::GDALOpenFlag) = x | UInt8(y) -|(x::GDALOpenFlag,y::GDALOpenFlag) = UInt8(x) | UInt8(y) +for T in (GDALOpenFlag, FieldValidation) + eval(quote + |(x::$T, y::UInt8) = UInt8(x) | y + |(x::UInt8, y::$T) = x | UInt8(y) + |(x::$T, y::$T) = UInt8(x) | UInt8(y) + end) +end """ typesize(dt::GDALDataType) @@ -347,7 +500,7 @@ typename(dt::GDALDataType)::String = GDAL.gdalgetdatatypename(dt) Returns GDAL data type by symbolic name. """ -gettype(name::AbstractString)::GDAL.GDALDataType = +gettype(name::AbstractString)::GDALDataType = GDAL.gdalgetdatatypebyname(name) """ @@ -355,7 +508,7 @@ gettype(name::AbstractString)::GDAL.GDALDataType = Return the smallest data type that can fully express both input data types. """ -typeunion(dt1::GDALDataType, dt2::GDALDataType)::GDAL.GDALDataType = +typeunion(dt1::GDALDataType, dt2::GDALDataType)::GDALDataType = GDAL.gdaldatatypeunion(dt1, dt2) """ @@ -363,7 +516,8 @@ typeunion(dt1::GDALDataType, dt2::GDALDataType)::GDAL.GDALDataType = `true` if `dtype` is one of `GDT_{CInt16|CInt32|CFloat32|CFloat64}.` """ -iscomplex(dtype::GDALDataType)::Bool = Bool(GDAL.gdaldatatypeiscomplex(dtype)) +iscomplex(dtype::GDALDataType)::Bool = + Bool(GDAL.gdaldatatypeiscomplex(dtype)) """ getname(dtype::GDALAsyncStatusType) @@ -378,7 +532,7 @@ getname(dtype::GDALAsyncStatusType)::String = Get AsyncStatusType by symbolic name. """ -asyncstatustype(name::AbstractString)::GDAL.GDALAsyncStatusType = +asyncstatustype(name::AbstractString)::GDALAsyncStatusType = GDAL.gdalgetasyncstatustypebyname(name) """ @@ -386,14 +540,15 @@ asyncstatustype(name::AbstractString)::GDAL.GDALAsyncStatusType = Return name (string) corresponding to color interpretation. """ -getname(obj::GDALColorInterp)::String = GDAL.gdalgetcolorinterpretationname(obj) +getname(obj::GDALColorInterp)::String = + GDAL.gdalgetcolorinterpretationname(obj) """ colorinterp(name::AbstractString) Get color interpretation corresponding to the given symbolic name. """ -colorinterp(name::AbstractString)::GDAL.GDALColorInterp = +colorinterp(name::AbstractString)::GDALColorInterp = GDAL.gdalgetcolorinterpretationbyname(name) """ diff --git a/src/utils.jl b/src/utils.jl index e3189630..f7b3413d 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -17,8 +17,7 @@ macro gdalenum(args...) end end - "returns the corresponding type in ArchGDAL" - function ArchGDAL.gdaltype(ft::$type2) + function Base.convert(::Type{$type1}, ft::$type2) rev = Dict{$type2, $type1}(Tuple{$type2, $type1}[$(reverse_map...)]) return get(rev, ft) do error("Unknown type: $ft") diff --git a/test/test_array.jl b/test/test_array.jl index 6359bdaf..e04d24af 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -102,7 +102,7 @@ end cp("ospy/data4/aster.img", "ospy/data4/aster_write.img"; force=true) @testset "Test Array setindex" begin - AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_Update) do ds + AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_UPDATE) do ds @testset "Dataset setindex" begin @test ds[755, 2107, 1] == 0xff ds[755, 2107, 1] = 0x00 @@ -134,7 +134,7 @@ cp("ospy/data4/aster.img", "ospy/data4/aster_write.img"; force=true) end @testset "Test Array constructor" begin - AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_Update) do ds + AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_UPDATE) do ds buffer = Array(ds) typeof(buffer) <: Array{UInt8,3} total = sum(buffer[:, :, 1:1]) diff --git a/test/test_feature.jl b/test/test_feature.jl index 9156c540..beb465c4 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -72,11 +72,11 @@ AG.read("data/point.geojson") do dataset AG.setmediatype!(f, "mediatype2") @test AG.getmediatype(f) == "mediatype2" - @test AG.validate(f, GDAL.OGR_F_VAL_NULL, false) == true - @test AG.validate(f, GDAL.OGR_F_VAL_GEOM_TYPE, false) == false - @test AG.validate(f, GDAL.OGR_F_VAL_WIDTH, false) == true - @test AG.validate(f, GDAL.OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, false) == true - @test AG.validate(f, GDAL.OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, false) == true + @test AG.validate(f, AG.F_VAL_NULL, false) == true + @test AG.validate(f, AG.F_VAL_GEOM_TYPE, false) == false + @test AG.validate(f, AG.F_VAL_WIDTH, false) == true + @test AG.validate(f, AG.F_VAL_ALLOW_NULL_WHEN_DEFAULT, false) == true + @test AG.validate(f, AG.F_VAL_ALLOW_DIFFERENT_GEOM_DIM, false) == true @test AG.getfield(f, 1) == "point-a" @test AG.getdefault(f, 1) == "" diff --git a/test/test_fielddefn.jl b/test/test_fielddefn.jl index 15fe9760..e40a0fb3 100644 --- a/test/test_fielddefn.jl +++ b/test/test_fielddefn.jl @@ -14,27 +14,27 @@ import ArchGDAL; const AG = ArchGDAL AG.settype!(fd, AG.OFTDate) @test AG.gettype(fd) == AG.OFTDate AG.settype!(fd, AG.OFTInteger) - @test AG.getsubtype(fd) == GDAL.OFSTNone - AG.setsubtype!(fd, GDAL.OFSTInt16) - @test AG.getsubtype(fd) == GDAL.OFSTInt16 - AG.setsubtype!(fd, GDAL.OFSTBoolean) - @test AG.getsubtype(fd) == GDAL.OFSTBoolean - AG.setsubtype!(fd, GDAL.OFSTNone) - @test AG.getjustify(fd) == GDAL.OJUndefined - AG.setjustify!(fd, GDAL.OJLeft) - @test AG.getjustify(fd) == GDAL.OJLeft + @test AG.getsubtype(fd) == AG.OFSTNone + AG.setsubtype!(fd, AG.OFSTInt16) + @test AG.getsubtype(fd) == AG.OFSTInt16 + AG.setsubtype!(fd, AG.OFSTBoolean) + @test AG.getsubtype(fd) == AG.OFSTBoolean + AG.setsubtype!(fd, AG.OFSTNone) + @test AG.getjustify(fd) == AG.OJUndefined + AG.setjustify!(fd, AG.OJLeft) + @test AG.getjustify(fd) == AG.OJLeft @test AG.getwidth(fd) == 0 AG.setwidth!(fd, 10) @test AG.getwidth(fd) == 10 @test AG.getprecision(fd) == 0 AG.setprecision!(fd, 20) @test AG.getprecision(fd) == 20 - AG.setparams!(fd, "finalname", AG.OFTDate, nwidth=5, nprecision=2, - justify=GDAL.OJRight) + AG.setparams!(fd, "finalname", AG.OFTDate, nwidth = 5, nprecision = 2, + justify = AG.OJRight) @test AG.gettype(fd) == AG.OFTDate @test AG.getname(fd) == "finalname" - @test AG.getsubtype(fd) == GDAL.OFSTNone - @test AG.getjustify(fd) == GDAL.OJRight + @test AG.getsubtype(fd) == AG.OFSTNone + @test AG.getjustify(fd) == AG.OJRight @test AG.getwidth(fd) == 5 @test AG.getprecision(fd) == 2 @test AG.isignored(fd) == false diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index 3800e456..3eb28b59 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -59,8 +59,8 @@ import ArchGDAL; const AG = ArchGDAL end # Techniques for Creating Files - @test GDAL.gdalgetmetadataitem(driver.ptr, "DCAP_CREATE", "") == "YES" - @test GDAL.gdalgetmetadataitem(driver.ptr, "DCAP_CREATECOPY", "") == "YES" + @test AG.metadataitem(driver, "DCAP_CREATE", domain = "") == "YES" + @test AG.metadataitem(driver, "DCAP_CREATECOPY", domain = "") == "YES" AG.read("data/utmsmall.tif") do ds_src AG.write(ds_src, "/vsimem/utmsmall.tif") diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index a2498e62..c5a59313 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -10,26 +10,26 @@ import ArchGDAL; const AG = ArchGDAL @test AG.nrow(rat) == 0 @test AG.changesarewrittentofile(rat) == false - AG.createcolumn!(rat, "col1", GDAL.GFT_Integer, GDAL.GFU_Generic) + AG.createcolumn!(rat, "col1", AG.GFT_Integer, AG.GFU_Generic) @test AG.ncolumn(rat) == 1 @test AG.columnname(rat, 0) == "col1" - @test AG.columnusage(rat, 0) == GDAL.GFU_Generic - @test AG.columntype(rat, 0) == GDAL.GFT_Integer - @test AG.findcolumnindex(rat, GDAL.GFU_Generic) == 0 - @test AG.findcolumnindex(rat, GDAL.GFU_Red) == -1 + @test AG.columnusage(rat, 0) == AG.GFU_Generic + @test AG.columntype(rat, 0) == AG.GFT_Integer + @test AG.findcolumnindex(rat, AG.GFU_Generic) == 0 + @test AG.findcolumnindex(rat, AG.GFU_Red) == -1 - AG.createcolumn!(rat, "col2", GDAL.GFT_Real, GDAL.GFU_MinMax) - AG.createcolumn!(rat, "col3", GDAL.GFT_String, GDAL.GFU_PixelCount) + AG.createcolumn!(rat, "col2", AG.GFT_Real, AG.GFU_MinMax) + AG.createcolumn!(rat, "col3", AG.GFT_String, AG.GFU_PixelCount) @test AG.ncolumn(rat) == 3 @test AG.nrow(rat) == 0 AG.setrowcount!(rat, 5) @test AG.nrow(rat) == 5 - @test AG.attributeio!(rat, GDAL.GF_Read, 0, 0, 5, Array{Cint}(undef, 5)) == + @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Cint}(undef, 5)) == fill(0,5) - @test AG.attributeio!(rat, GDAL.GF_Read, 0, 0, 5, Array{Float64}(undef, 5)) == + @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Float64}(undef, 5)) == fill(0,5) - @test AG.attributeio!(rat, GDAL.GF_Read, 1, 0, 5, Array{Float64}(undef, 5)) == + @test AG.attributeio!(rat, AG.GF_Read, 1, 0, 5, Array{Float64}(undef, 5)) == fill(0,5) @test AG.asstring(rat, 2, 0) == "0" @@ -57,7 +57,7 @@ import ArchGDAL; const AG = ArchGDAL @test AG.asstring(rat, 0, 2) == "" @test AG.asstring(rat, 2, 2) == "" @test AG.asstring(rat, 4, 2) == "" - AG.attributeio!(rat, GDAL.GF_Write, 2, 0, 5, fill("abc",5)) + AG.attributeio!(rat, AG.GF_Write, 2, 0, 5, fill("abc",5)) @test AG.asstring(rat, 0, 2) == "abc" @test AG.asstring(rat, 2, 2) == "abc" @test AG.asstring(rat, 4, 2) == "abc" @@ -68,8 +68,8 @@ import ArchGDAL; const AG = ArchGDAL @test AG.asstring(ratclone, 4, 2) == "abc" @test AG.ncolumn(ratclone) == 3 @test AG.nrow(ratclone) == 5 - @test AG.findcolumnindex(ratclone, GDAL.GFU_Generic) == 0 - @test AG.findcolumnindex(ratclone, GDAL.GFU_Red) == -1 + @test AG.findcolumnindex(ratclone, AG.GFU_Generic) == 0 + @test AG.findcolumnindex(ratclone, AG.GFU_Red) == -1 end AG.setlinearbinning!(rat, 0, 10) @@ -87,8 +87,8 @@ import ArchGDAL; const AG = ArchGDAL end @testset ("Testing Color Tables") begin - AG.createcolortable(GDAL.GPI_RGB) do ct - @test AG.paletteinterp(ct) == GDAL.GPI_RGB + AG.createcolortable(AG.GPI_RGB) do ct + @test AG.paletteinterp(ct) == AG.GPI_RGB @test AG.ncolorentry(ct) == 0 AG.createcolorramp!(ct, 128, GDAL.GDALColorEntry(0,0,0,0), 255, GDAL.GDALColorEntry(0,0,255,0)) @@ -107,7 +107,7 @@ end @test sprint(print, AG.getcolorentry(ct, 255)) == "GDAL.GDALColorEntry(0, 0, 100, 0)" AG.clone(ct) do ctclone - @test AG.paletteinterp(ctclone) == GDAL.GPI_RGB + @test AG.paletteinterp(ctclone) == AG.GPI_RGB @test AG.ncolorentry(ctclone) == 256 @test sprint(print, AG.getcolorentry(ctclone, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" @test sprint(print, AG.getcolorentry(ctclone, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" @@ -116,7 +116,7 @@ end AG.createRAT(ctclone) do rat ct2 = AG.toColorTable(rat) - @test AG.paletteinterp(ct2) == GDAL.GPI_RGB + @test AG.paletteinterp(ct2) == AG.GPI_RGB @test AG.ncolorentry(ct2) == 256 @test sprint(print, AG.getcolorentry(ct2, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" @test sprint(print, AG.getcolorentry(ct2, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 2dc94d9b..861ee856 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -64,9 +64,9 @@ import ArchGDAL; const AG = ArchGDAL blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: (0) 50x50 (1) 25x25 (2) 13x13 """ - @test AG.getcolorinterp(destband) == GDAL.GCI_GrayIndex - AG.setcolorinterp!(destband, GDAL.GCI_RedBand) - @test AG.getcolorinterp(destband) == GDAL.GCI_RedBand + @test AG.getcolorinterp(destband) == AG.GCI_GrayIndex + AG.setcolorinterp!(destband, AG.GCI_RedBand) + @test AG.getcolorinterp(destband) == AG.GCI_RedBand @test sprint(print, AG.sampleoverview(destband, 100)) == """ [GA_Update] Band 1 (Gray): 13 x 13 (UInt8) @@ -112,7 +112,7 @@ import ArchGDAL; const AG = ArchGDAL ]) end - AG.createcolortable(GDAL.GPI_RGB) do ct + AG.createcolortable(AG.GPI_RGB) do ct AG.createcolorramp!(ct, 128, GDAL.GDALColorEntry(0,0,0,0), 255, GDAL.GDALColorEntry(0,0,255,0) diff --git a/test/test_styletable.jl b/test/test_styletable.jl index 945fad94..ce0e1fb2 100644 --- a/test/test_styletable.jl +++ b/test/test_styletable.jl @@ -19,11 +19,11 @@ import ArchGDAL; const AG = ArchGDAL @test AG.addstyle!(sm, "name2") == false @test AG.npart(sm) == 1 - AG.createstyletool(GDAL.OGRSTCBrush) do st - @test AG.gettype(st) == GDAL.OGRSTCBrush - @test AG.getunit(st) == GDAL.OGRSTUMM - AG.setunit!(st, GDAL.OGRSTUPixel, 2.0) - @test AG.getunit(st) == GDAL.OGRSTUPixel + AG.createstyletool(AG.OGRSTCBrush) do st + @test AG.gettype(st) == AG.OGRSTCBrush + @test AG.getunit(st) == AG.OGRSTUMM + AG.setunit!(st, AG.OGRSTUPixel, 2.0) + @test AG.getunit(st) == AG.OGRSTUPixel AG.setparam!(st, 0, 0) @test AG.asint(st, 0) == 0 diff --git a/test/test_types.jl b/test/test_types.jl index adc382d6..987f1954 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -6,55 +6,47 @@ import ArchGDAL; const AG = ArchGDAL @testset "Testing GDAL Type Methods" begin @testset "GDAL Open Flags" begin - @test AG.OF_ReadOnly | 0x04 == 0x04 - @test 0x06 | AG.OF_ReadOnly == 0x06 - @test AG.OF_ReadOnly | AG.OF_GNM == GDAL.GDAL_OF_READONLY | GDAL.GDAL_OF_GNM + @test AG.OF_READONLY | 0x04 == 0x04 + @test 0x06 | AG.OF_READONLY == 0x06 + @test AG.OF_READONLY | AG.OF_GNM == AG.OF_READONLY | AG.OF_GNM end @testset "GDAL Data Types" begin - @test AG.typesize(GDAL.GDT_UInt16) == 16 - @test AG.typename(GDAL.GDT_UInt16) == "UInt16" - @test AG.gettype("UInt16") == GDAL.GDT_UInt16 + @test AG.typesize(AG.GDT_UInt16) == 16 + @test AG.typename(AG.GDT_UInt16) == "UInt16" + @test AG.gettype("UInt16") == AG.GDT_UInt16 - @test AG.typeunion(GDAL.GDT_UInt16, GDAL.GDT_Byte) == GDAL.GDT_UInt16 - @test AG.iscomplex(GDAL.GDT_Float32) == false - - @test AG.datatype(GDAL.GDT_Int16) == Int16 - @test_throws ErrorException("Unknown GDALDataType: GDT_TypeCount") AG.datatype(GDAL.GDT_TypeCount) - @test AG.gdaltype(Int16) == GDAL.GDT_Int16 - @test_throws ErrorException("Unknown DataType: String") AG.gdaltype(String) + @test AG.typeunion(AG.GDT_UInt16, AG.GDT_Byte) == AG.GDT_UInt16 + @test AG.iscomplex(AG.GDT_Float32) == false end @testset "GDAL Colors and Palettes" begin - @test AG.getname(GDAL.GARIO_COMPLETE) == "COMPLETE" - @test AG.asyncstatustype("COMPLETE") == GDAL.GARIO_COMPLETE - @test AG.asyncstatustype("ERROR") == GDAL.GARIO_ERROR - @test AG.asyncstatustype("PENDING") == GDAL.GARIO_PENDING - @test AG.asyncstatustype("UPDATE") == GDAL.GARIO_UPDATE - - @test AG.colorinterp("Hue") == GDAL.GCI_HueBand - @test AG.colorinterp("Red") == GDAL.GCI_RedBand - @test AG.colorinterp("Blue") == GDAL.GCI_BlueBand - - @test AG.getname(GDAL.GPI_Gray) == "Gray" - @test AG.getname(GDAL.GPI_RGB) == "RGB" - @test AG.getname(GDAL.GPI_CMYK) == "CMYK" - @test AG.getname(GDAL.GPI_HLS) == "HLS" + @test AG.getname(AG.GARIO_COMPLETE) == "COMPLETE" + @test AG.asyncstatustype("COMPLETE") == AG.GARIO_COMPLETE + @test AG.asyncstatustype("ERROR") == AG.GARIO_ERROR + @test AG.asyncstatustype("PENDING") == AG.GARIO_PENDING + @test AG.asyncstatustype("UPDATE") == AG.GARIO_UPDATE + + @test AG.colorinterp("Hue") == AG.GCI_HueBand + @test AG.colorinterp("Red") == AG.GCI_RedBand + @test AG.colorinterp("Blue") == AG.GCI_BlueBand + + @test AG.getname(AG.GPI_Gray) == "Gray" + @test AG.getname(AG.GPI_RGB) == "RGB" + @test AG.getname(AG.GPI_CMYK) == "CMYK" + @test AG.getname(AG.GPI_HLS) == "HLS" end @testset "GDAL Field Types" begin @test AG.getname(AG.OFTString) == "String" @test AG.getname(AG.OFTIntegerList) == "IntegerList" - @test AG.getname(GDAL.OFSTBoolean) == "Boolean" - @test AG.getname(GDAL.OFSTFloat32) == "Float32" - - @test AG.arecompatible(AG.OFTReal, GDAL.OFSTNone) == true - @test AG.arecompatible(AG.OFTReal, GDAL.OFSTBoolean) == false - @test AG.arecompatible(AG.OFTReal, GDAL.OFSTInt16) == false - @test AG.arecompatible(AG.OFTReal, GDAL.OFSTFloat32) == true + @test AG.getname(AG.OFSTBoolean) == "Boolean" + @test AG.getname(AG.OFSTFloat32) == "Float32" - @test AG.datatype(AG.OFTString) == String - @test AG.gdaltype(GDAL.OFTMaxType) == AG.OFTInteger64List + @test AG.arecompatible(AG.OFTReal, AG.OFSTNone) == true + @test AG.arecompatible(AG.OFTReal, AG.OFSTBoolean) == false + @test AG.arecompatible(AG.OFTReal, AG.OFSTInt16) == false + @test AG.arecompatible(AG.OFTReal, AG.OFSTFloat32) == true end end From 2e4ceccd251c74262f0706d50efc3e6fad75b6ed Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 11:57:45 -0700 Subject: [PATCH 029/169] improve test coverage for drivers --- test/test_drivers.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/test_drivers.jl b/test/test_drivers.jl index aa7fbfcc..fc65c91d 100644 --- a/test/test_drivers.jl +++ b/test/test_drivers.jl @@ -49,9 +49,13 @@ end @test sprint(print, AG.identifydriver("data/point.geojson")) == "Driver: GeoJSON/GeoJSON" @test sprint(print, AG.identifydriver("data/utmsmall.tif")) == "Driver: GTiff/GeoTIFF" - @test AG.validate(AG.getdriver("GTiff"), ["COMPRESS=LZW", "INTERLEAVE=PIXEL"]) == true - @test AG.validate(AG.getdriver("GTiff"), ["COMPRESS=LZW"]) == true - @test AG.validate(AG.getdriver("GTiff"), ["INTERLEAVE=PIXEL"]) == true + driver = AG.getdriver("GTiff") + @test isnothing(AG.deregister(driver)) + @test isnothing(AG.register(driver)) + @test AG.validate(driver, ["COMPRESS=LZW", "INTERLEAVE=PIXEL"]) == true + @test AG.validate(driver, ["COMPRESS=LZW"]) == true + @test AG.validate(driver, ["INTERLEAVE=PIXEL"]) == true + AG.read("data/point.geojson") do dataset @test AG.listcapability(dataset) == Dict( "CreateLayer"=>false, From b782646398fb357bca2d3714632b87df3ad8184e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 12:40:02 -0700 Subject: [PATCH 030/169] Remove unnecessary imports of GDAL in the tests --- test/test_array.jl | 1 - test/test_cookbook_geometry.jl | 2 +- test/test_dataset.jl | 13 ++----------- test/test_feature.jl | 1 - test/test_featurelayer.jl | 1 - test/test_fielddefn.jl | 1 - test/test_gdal_tutorials.jl | 1 - test/test_geometry.jl | 2 +- test/test_ospy_examples.jl | 1 - test/test_rasterio.jl | 1 - test/test_spatialref.jl | 1 - test/test_styletable.jl | 1 - test/test_types.jl | 1 - test/test_utils.jl | 1 - 14 files changed, 4 insertions(+), 24 deletions(-) diff --git a/test/test_array.jl b/test/test_array.jl index e04d24af..be707c37 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -1,5 +1,4 @@ using Test -import GDAL using DiskArrays: eachchunk, haschunks, Chunked, GridChunks, readblock! import ArchGDAL; const AG = ArchGDAL diff --git a/test/test_cookbook_geometry.jl b/test/test_cookbook_geometry.jl index 07ef9a00..78f000a3 100644 --- a/test/test_cookbook_geometry.jl +++ b/test/test_cookbook_geometry.jl @@ -1,7 +1,7 @@ # adapted from http://pcjericks.github.io/py-gdalogr-cookbook/geometry.html using Test import GeoInterface -import GDAL, ArchGDAL; const AG = ArchGDAL +import ArchGDAL; const AG = ArchGDAL @testset "test_cookbook_geometry.jl" begin diff --git a/test/test_dataset.jl b/test/test_dataset.jl index 0ce59360..8f5b57d9 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_dataset.jl" begin @@ -13,11 +12,7 @@ import ArchGDAL; const AG = ArchGDAL @test AG.noverview(band) == 0 AG.buildoverviews!(copydataset, Cint[2, 4, 8]) @test AG.noverview(band) == 3 - AG.copywholeraster!( - dataset, - copydataset, - progressfunc = GDAL.gdaltermprogress - ) + AG.copywholeraster!(dataset, copydataset) end end end @@ -27,11 +22,7 @@ import ArchGDAL; const AG = ArchGDAL @test AG.noverview(AG.getband(copydataset,1)) == 0 AG.buildoverviews!(copydataset, Cint[2, 4, 8]) @test AG.noverview(AG.getband(copydataset,1)) == 3 - AG.copywholeraster!( - dataset, - copydataset, - progressfunc = GDAL.gdaltermprogress - ) + AG.copywholeraster!(dataset, copydataset) end AG.copyfiles("GTiff", "/vsimem/utmcopy2.tif", "/vsimem/utmcopy.tif") AG.update("/vsimem/utmcopy2.tif") do copydataset diff --git a/test/test_feature.jl b/test/test_feature.jl index beb465c4..8542cc30 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_feature.jl" begin diff --git a/test/test_featurelayer.jl b/test/test_featurelayer.jl index a0211d19..0a661ccd 100644 --- a/test/test_featurelayer.jl +++ b/test/test_featurelayer.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_featurelayer.jl" begin diff --git a/test/test_fielddefn.jl b/test/test_fielddefn.jl index e40a0fb3..6a844367 100644 --- a/test/test_fielddefn.jl +++ b/test/test_fielddefn.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_fielddefn.jl" begin diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index 3eb28b59..2642a7bb 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_gdal_tutorials.jl" begin diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 32706df9..7e36e374 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -1,5 +1,5 @@ using Test -import GeoInterface, GeoFormatTypes, GDAL, ArchGDAL; +import GeoInterface, GeoFormatTypes, ArchGDAL; const AG = ArchGDAL const GFT = GeoFormatTypes diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index f14c5dc7..1c4c1b1f 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -1,6 +1,5 @@ using Test using Statistics -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_ospy_examples.jl" begin diff --git a/test/test_rasterio.jl b/test/test_rasterio.jl index 15114195..e5bbccf4 100644 --- a/test/test_rasterio.jl +++ b/test/test_rasterio.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_rasterio.jl" begin diff --git a/test/test_spatialref.jl b/test/test_spatialref.jl index 74ba57fb..06561049 100644 --- a/test/test_spatialref.jl +++ b/test/test_spatialref.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL import GeoFormatTypes; const GFT = GeoFormatTypes diff --git a/test/test_styletable.jl b/test/test_styletable.jl index ce0e1fb2..dcde8813 100644 --- a/test/test_styletable.jl +++ b/test/test_styletable.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_styletable.jl" begin diff --git a/test/test_types.jl b/test/test_types.jl index 987f1954..ac7f28cd 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_types.jl" begin diff --git a/test/test_utils.jl b/test/test_utils.jl index 45896325..47301330 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -1,5 +1,4 @@ using Test -import GDAL import ArchGDAL; const AG = ArchGDAL @testset "test_utils.jl" begin From cd4ac78d0ca8f338879652b014ce36a1b2ca6e90 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 13:25:10 -0700 Subject: [PATCH 031/169] Add tests for geotransforms And fix a bug with the implementation for `composegeotransform!()`. --- src/ArchGDAL.jl | 2 +- src/{gcp.jl => geotransform.jl} | 51 ++++++++++++++++----------------- src/utils.jl | 2 +- test/runtests.jl | 1 + test/test_geotransform.jl | 33 +++++++++++++++++++++ 5 files changed, 61 insertions(+), 28 deletions(-) rename src/{gcp.jl => geotransform.jl} (59%) create mode 100644 test/test_geotransform.jl diff --git a/src/ArchGDAL.jl b/src/ArchGDAL.jl index cadbfbf7..035b473e 100644 --- a/src/ArchGDAL.jl +++ b/src/ArchGDAL.jl @@ -12,7 +12,7 @@ module ArchGDAL include("utils.jl") include("types.jl") include("driver.jl") - include("gcp.jl") + include("geotransform.jl") include("spatialref.jl") include("dataset.jl") include("raster/rasterband.jl") diff --git a/src/gcp.jl b/src/geotransform.jl similarity index 59% rename from src/gcp.jl rename to src/geotransform.jl index e72e1618..fff40403 100644 --- a/src/gcp.jl +++ b/src/geotransform.jl @@ -1,5 +1,5 @@ """ - invgeotransform!(gt_in::Vector{Cdouble}, gt_out::Vector{Cdouble}) + invgeotransform!(gt_in::Vector{Float64}, gt_out::Vector{Float64}) Invert Geotransform. @@ -14,20 +14,20 @@ converts the equation from being pixel to geo to being geo to pixel. `gt_out` """ function invgeotransform!( - gt_in::Vector{Cdouble}, - gt_out::Vector{Cdouble} - )::Vector{Cdouble} + gt_in::Vector{Float64}, + gt_out::Vector{Float64} + )::Vector{Float64} result = Bool(GDAL.gdalinvgeotransform(pointer(gt_in), pointer(gt_out))) result || error("Geotransform coefficients is uninvertable") return gt_out end -invgeotransform(gt_in::Vector{Cdouble})::Vector{Cdouble} = - invgeotransform!(gt_in, Array{Cdouble}(undef, 6)) +invgeotransform(gt_in::Vector{Float64})::Vector{Float64} = + invgeotransform!(gt_in, Array{Float64}(undef, 6)) """ - applygeotransform(geotransform::Vector{Cdouble}, pixel::Cdouble, - line::Cdouble) + applygeotransform(geotransform::Vector{Float64}, pixel::Float64, + line::Float64) Apply GeoTransform to x/y coordinate. @@ -43,13 +43,13 @@ georeferenced `(geo_x,geo_y)` location. * `line` input line position. """ function applygeotransform( - geotransform::Vector{Cdouble}, - pixel::Cdouble, - line::Cdouble - )::Vector{Cdouble} - geo_xy = Vector{Cdouble}(undef, 2) + geotransform::Vector{Float64}, + pixel::Float64, + line::Float64 + )::Vector{Float64} + geo_xy = Vector{Float64}(undef, 2) geo_x = pointer(geo_xy) - geo_y = geo_x + sizeof(Cdouble) + geo_y = geo_x + sizeof(Float64) GDAL.gdalapplygeotransform(pointer(geotransform), pixel, line, geo_x, geo_y) return geo_xy end @@ -60,27 +60,26 @@ end Compose two geotransforms. -The resulting geotransform is the equivelent to `padfGT1` and then `padfGT2` +The resulting geotransform is the equivalent to `padfGT1` and then `padfGT2` being applied to a point. ### Parameters * `gt1` the first geotransform, six values. * `gt2` the second geotransform, six values. -* `gtout` the output geotransform, six values, may safely be the same -array as `gt1` or `gt2`. +* `gtout` the output geotransform, six values. """ function composegeotransform!( - gt1::Vector{Cdouble}, - gt2::Vector{Cdouble}, - gtout::Vector{Cdouble} - )::Vector{Cdouble} - GDAL.gdalcomposegeotransform(pointer(gt1), pointer(gt2), pointer(gtout)) + gt1::Vector{Float64}, + gt2::Vector{Float64}, + gtout::Vector{Float64} + )::Vector{Float64} + GDAL.gdalcomposegeotransforms(pointer(gt1), pointer(gt2), pointer(gtout)) return gtout end function composegeotransform( - gt1::Vector{Cdouble}, - gt2::Vector{Cdouble} - )::Vector{Cdouble} - return composegeotransform!(gt1, gt2, Vector{Cdouble}(undef, 6)) + gt1::Vector{Float64}, + gt2::Vector{Float64} + )::Vector{Float64} + return composegeotransform!(gt1, gt2, Vector{Float64}(undef, 6)) end diff --git a/src/utils.jl b/src/utils.jl index f7b3413d..ccedd272 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -100,7 +100,7 @@ metadata(obj; domain::AbstractString = "")::Vector{String} = GDAL.gdalgetmetadata(obj.ptr, domain) """ - metadataitem(obj, name::AbstractString, domain::AbstractString) + metadataitem(obj, name::AbstractString, domain::AbstractString) Fetch single metadata item. diff --git a/test/runtests.jl b/test/runtests.jl index 55b2e28f..fa868ff2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -31,6 +31,7 @@ include("remotefiles.jl") include("test_geos_operations.jl") include("test_cookbook_geometry.jl") include("test_cookbook_projection.jl") + include("test_geotransform.jl") include("test_utils.jl") end end diff --git a/test/test_geotransform.jl b/test/test_geotransform.jl new file mode 100644 index 00000000..54667431 --- /dev/null +++ b/test/test_geotransform.jl @@ -0,0 +1,33 @@ +using Test +import ArchGDAL; const AG = ArchGDAL + +@testset "test_geotransform.jl" begin + + f(gt, pixel, line) = [ + gt[1] + pixel * gt[2] + line * gt[3], + gt[4] + pixel * gt[5] + line * gt[6], + ] + gt1 = [ + -1111950.519667, 463.3127165279167, 0.0, + 6671703.118, 0.0, -463.3127165279165, + ] + for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) + @test AG.applygeotransform(gt1, pixel, line) ≈ f(gt1, pixel, line) + end + + gt2 = AG.invgeotransform(gt1) + @test gt2 ≈ [ + 2400.0, 0.0021583694216166533, 0.0, + 14400.0, 0.0, -0.002158369421616654, + ] + + gt3 = AG.composegeotransform(gt1, gt2) + @test gt3 ≈ [ + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + ] + + for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) + @test AG.applygeotransform(gt3, pixel, line) ≈ [pixel, line] + end +end From 1758d84a99706262bb0fe0904e2527d87eadd49d Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 13:27:24 -0700 Subject: [PATCH 032/169] whitespacing --- test/test_geotransform.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_geotransform.jl b/test/test_geotransform.jl index 54667431..b2962b1e 100644 --- a/test/test_geotransform.jl +++ b/test/test_geotransform.jl @@ -9,7 +9,7 @@ import ArchGDAL; const AG = ArchGDAL ] gt1 = [ -1111950.519667, 463.3127165279167, 0.0, - 6671703.118, 0.0, -463.3127165279165, + 6671703.118, 0.0, -463.3127165279165, ] for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) @test AG.applygeotransform(gt1, pixel, line) ≈ f(gt1, pixel, line) @@ -17,8 +17,8 @@ import ArchGDAL; const AG = ArchGDAL gt2 = AG.invgeotransform(gt1) @test gt2 ≈ [ - 2400.0, 0.0021583694216166533, 0.0, - 14400.0, 0.0, -0.002158369421616654, + 2400.0, 0.0021583694216166533, 0.0, + 14400.0, 0.0, -0.002158369421616654, ] gt3 = AG.composegeotransform(gt1, gt2) From eca39b57eda78cea872489c835febc5c9448c384 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 14:17:56 -0700 Subject: [PATCH 033/169] [Breaking] Update implementation of GeoInterface.coordinates() Coordinate dimensions should now only return 2 or 3. --- src/geointerface.jl | 12 +++++------- src/ogr/geometry.jl | 3 +-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/geointerface.jl b/src/geointerface.jl index c0d63aae..74bf8bf2 100644 --- a/src/geointerface.jl +++ b/src/geointerface.jl @@ -44,25 +44,23 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), elseif ndim == 3 Float64[getx(g,0), gety(g,0), getz(g,0)] else - @assert ndim == 0 - @warn("Empty Point") - nothing + error("getcoorddim($g) returned $ndim: expected 2 or 3") end elseif gtype in multipointtypes Vector{Float64}[ - GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) ] elseif gtype in linetypes || gtype == wkbLinearRing Vector{Float64}[ - collect(getpoint(g,i-1)[1:ndim]) for i in 1:ngeom(g) + collect(getpoint(g, i - 1)[1:ndim]) for i in 1:ngeom(g) ] elseif gtype in multilinetypes || gtype in polygontypes Vector{Vector{Float64}}[ - GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) ] elseif gtype in multipolygontypes Vector{Vector{Vector{Float64}}}[ - GeoInterface.coordinates(getgeom(g,i-1)) for i in 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) ] end end diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 33f78768..c9f13f5b 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -172,8 +172,7 @@ geomdim(geom::AbstractGeometry)::Integer = GDAL.ogr_g_getdimension(geom.ptr) Get the dimension of the coordinates in this geometry. ### Returns -In practice this will return 2 or 3. It can also return 0 in the case of an -empty point. +This will return 2 or 3. """ getcoorddim(geom::AbstractGeometry)::Integer = GDAL.ogr_g_getcoordinatedimension(geom.ptr) From 126ced0eac1c0aaf4db6db6f9895eaf6223c4446 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 14:20:34 -0700 Subject: [PATCH 034/169] LinearRings have the strange property of being treated like linestrings Their geotype returns LineString even though the WKT indicates otherwise, and I have seen reports such as https://trac.osgeo.org/gdal/ticket/1755, but don't think it'll get resolved in this package. For now I'm just going to report what GDAL returns. --- test/test_geometry.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 7e36e374..5bbe23a0 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -121,8 +121,8 @@ end @test AG.toWKT(AG.createlinearring([1.,2.,3.], [4.,5.,6.])) == "LINEARRING (1 4,2 5,3 6)" AG.createlinearring([1.,2.,3.], [4.,5.,6.]) do geom - # @test GeoInterface.geotype(geom) == :LinearRing - @test isapprox(GeoInterface.coordinates(geom), [[1,4],[2,5],[3,6]], atol=1e-6) + @test GeoInterface.geotype(geom) == :LineString + @test isapprox(GeoInterface.coordinates(geom), [[1,4], [2,5], [3,6]], atol=1e-6) @test AG.toWKT(geom) == "LINEARRING (1 4,2 5,3 6)" AG.setpointcount!(geom, 5) @test AG.toWKT(geom) == "LINEARRING (1 4,2 5,3 6,0 0,0 0)" From 2e168dd1eda856199e3f7d4b3a4c4f5f2b5dcb80 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 14:50:54 -0700 Subject: [PATCH 035/169] Implement a basetype() method --- src/types.jl | 7 +++++ test/test_types.jl | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/types.jl b/src/types.jl index eb698e00..5ce9d63a 100644 --- a/src/types.jl +++ b/src/types.jl @@ -466,6 +466,13 @@ eval(@gdalenum(OGRwkbGeometryType::GDAL.OGRwkbGeometryType, wkbGeometryCollection25D::GDAL.wkbGeometryCollection25D, )) +function basetype(gt::OGRwkbGeometryType)::OGRwkbGeometryType + wkbGeomType = convert(GDAL.OGRwkbGeometryType, gt) + wkbGeomType &= (~0x80000000) # Remove 2.5D flag. + wkbGeomType %= 1000 # Normalize Z, M, and ZM types. + return GDAL.OGRwkbGeometryType(wkbGeomType) +end + eval(@gdalenum(OGRwkbByteOrder::GDAL.OGRwkbByteOrder, wkbXDR::GDAL.wkbXDR, wkbNDR::GDAL.wkbNDR, diff --git a/test/test_types.jl b/test/test_types.jl index ac7f28cd..2dc15b27 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -47,6 +47,80 @@ import ArchGDAL; const AG = ArchGDAL @test AG.arecompatible(AG.OFTReal, AG.OFSTInt16) == false @test AG.arecompatible(AG.OFTReal, AG.OFSTFloat32) == true end + + @testset "Base Geometry Types" begin + @test AG.basetype(AG.wkbUnknown) == AG.wkbUnknown + @test AG.basetype(AG.wkbPoint) == AG.wkbPoint + @test AG.basetype(AG.wkbLineString) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygon) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPoint) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineString) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygon) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollection) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbCircularString) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurve) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygon) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurve) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurface) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurve) == AG.wkbCurve + @test AG.basetype(AG.wkbSurface) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurface) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTIN) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangle) == AG.wkbTriangle + @test AG.basetype(AG.wkbNone) == AG.wkbNone + @test AG.basetype(AG.wkbLinearRing) == AG.wkbLinearRing + @test AG.basetype(AG.wkbCircularStringZ) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurveZ) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygonZ) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurveZ) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurfaceZ) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurveZ) == AG.wkbCurve + @test AG.basetype(AG.wkbSurfaceZ) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceZ) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTINZ) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangleZ) == AG.wkbTriangle + @test AG.basetype(AG.wkbPointM) == AG.wkbPoint + @test AG.basetype(AG.wkbLineStringM) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygonM) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPointM) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineStringM) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygonM) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollectionM) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbCircularStringM) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurveM) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygonM) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurveM) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurfaceM) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurveM) == AG.wkbCurve + @test AG.basetype(AG.wkbSurfaceM) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceM) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTINM) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangleM) == AG.wkbTriangle + @test AG.basetype(AG.wkbPointZM) == AG.wkbPoint + @test AG.basetype(AG.wkbLineStringZM) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygonZM) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPointZM) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineStringZM) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygonZM) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollectionZM) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbCircularStringZM) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurveZM) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygonZM) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurveZM) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurfaceZM) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurveZM) == AG.wkbCurve + @test AG.basetype(AG.wkbSurfaceZM) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceZM) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTINZM) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangleZM) == AG.wkbTriangle + @test AG.basetype(AG.wkbPoint25D) == AG.wkbPoint + @test AG.basetype(AG.wkbLineString25D) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygon25D) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPoint25D) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineString25D) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygon25D) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollection25D) == AG.wkbGeometryCollection + end end end From d1d81569b8033e92d6464ceee6c0ea7b1fb61d26 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 15:05:56 -0700 Subject: [PATCH 036/169] Remove nextnamedtuple() from tables.jl It is not part of the Tables.jl interface. (We can provide a more general conversion from Features to NamedTuples as a feature request if desired.) --- src/tables.jl | 15 --------------- test/test_display.jl | 2 -- test/test_tables.jl | 9 +++++---- 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/tables.jl b/src/tables.jl index f802e582..228599f6 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -57,21 +57,6 @@ function Tables.columnnames( return (field_names..., geom_names...) end -""" -Returns the feature row of a layer as a `NamedTuple` - -Calling it iteratively will work similar to `nextfeature` i.e. give the -consecutive feature as `NamedTuple`. -""" -function nextnamedtuple(layer::IFeatureLayer)::NamedTuple - field_names, geom_names = schema_names(layer) - return nextfeature(layer) do feature - prop = (getfield(feature, name) for name in field_names) - geom = (getgeom(feature, i - 1) for i in 1:length(geom_names)) - NamedTuple{(field_names..., geom_names...)}((prop..., geom...)) - end -end - function schema_names(layer::AbstractFeatureLayer) featuredefn = layerdefn(layer) fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(layer)-1) diff --git a/test/test_display.jl b/test/test_display.jl index dc17aa9f..cd4e8771 100644 --- a/test/test_display.jl +++ b/test/test_display.jl @@ -21,8 +21,6 @@ import ArchGDAL; const AG = ArchGDAL Field 0 (FID): [OFTReal], 2.0, 3.0, 0.0, 3.0 Field 1 (pointname): [OFTString], point-a, point-b, a, b """ - @test sprint(print, AG.nextnamedtuple(layer), context=:compact => true) == - "(FID = 2.0, pointname = \"point-a\", = Geometry: wkbPoint)" @test sprint(print, AG.layerdefn(layer)) == """ Geometry (index 0): (wkbPoint) Field (index 0): FID (OFTReal) diff --git a/test/test_tables.jl b/test/test_tables.jl index 38a40f44..8c729d7c 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -35,12 +35,13 @@ using Tables @testset "Misc. methods" begin AG.resetreading!(layer) AG.resetreading!(layer1) + + schema_names = AG.schema_names(layer) + schema_names1 = AG.schema_names(layer1) - @test AG.nextnamedtuple(layer) isa NamedTuple{(:FID, :pointname, Symbol("")),Tuple{Float64,String,ArchGDAL.IGeometry}} - @test AG.nextnamedtuple(layer1) isa NamedTuple{(:id, :zoom, :location, :point, :linestring),Tuple{String,String,String,ArchGDAL.IGeometry,ArchGDAL.IGeometry}} for i in 1:4 - @test AG.schema_names(layer)[i] isa Base.Generator || AG.schema_names(layer)[i] isa ArchGDAL.IFeatureDefnView - @test AG.schema_names(layer1)[i] isa Base.Generator || AG.schema_names(layer1)[i] isa ArchGDAL.IFeatureDefnView + @test schema_names[i] isa Base.Generator || schema_names[i] isa ArchGDAL.IFeatureDefnView + @test schema_names1[i] isa Base.Generator || schema_names1[i] isa ArchGDAL.IFeatureDefnView end end end From 3dc7eb7f533fe5ed69bef52cf6d5c0ec3ac9abb2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 15:32:09 -0700 Subject: [PATCH 037/169] Add tests for tables.jl --- src/tables.jl | 15 ++++++++------- test/test_tables.jl | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/tables.jl b/src/tables.jl index 228599f6..884e4c61 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -8,7 +8,8 @@ struct Table{T <: AbstractFeatureLayer} end function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema - field_names, geom_names, featuredefn, fielddefns = schema_names(layer) + field_names, geom_names, featuredefn, fielddefns = + schema_names(layerdefn(layer)) ngeom = ArchGDAL.ngeom(featuredefn) geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) field_types = ( @@ -52,17 +53,17 @@ end function Tables.columnnames( row::Feature - )::NTuple{nfield(row) + ngeom(row), String} - field_names, geom_names = schema_names(layer) + )::NTuple{Int64(nfield(row) + ngeom(row)), Symbol} + field_names, geom_names = schema_names(getfeaturedefn(row)) return (field_names..., geom_names...) end -function schema_names(layer::AbstractFeatureLayer) - featuredefn = layerdefn(layer) - fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(layer)-1) +function schema_names(featuredefn::IFeatureDefnView) + fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(featuredefn)-1) field_names = (Symbol(getname(fielddefn)) for fielddefn in fielddefns) geom_names = ( - Symbol(getname(getgeomdefn(featuredefn, i - 1))) for i in 1:ngeom(layer) + Symbol(getname(getgeomdefn(featuredefn, i - 1))) + for i in 1:ngeom(featuredefn) ) return (field_names, geom_names, featuredefn, fielddefns) end diff --git a/test/test_tables.jl b/test/test_tables.jl index 8c729d7c..7a0640ba 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -30,14 +30,47 @@ using Tables (String, String, String, AG.IGeometry, AG.IGeometry) ) @test Tables.istable(AG.Table) == true + @test Tables.rowaccess(AG.Table) == true + @test Tables.rows(gt) isa AG.AbstractFeatureLayer + @test Tables.rows(gt1) isa AG.AbstractFeatureLayer + @test Tables.rows(gt2) isa AG.AbstractFeatureLayer + + features = collect(Tables.rows(gt1)) + @test length(features) == 2 + + @test Tables.columnnames(features[1]) == (:id, :zoom, :location, :point, :linestring) + @test Tables.getcolumn(features[1], 1) == "5.1" + @test Tables.getcolumn(features[1], 2) == "1.0" + @test Tables.getcolumn(features[1], 3) == "Mumbai" + @test AG.toWKT(Tables.getcolumn(features[1], 4)) == "POINT (30 10)" + @test AG.toWKT(Tables.getcolumn(features[1], 5)) == "LINESTRING (30 10,10 30,40 40)" + @test Tables.getcolumn(features[1], :id) == "5.1" + @test Tables.getcolumn(features[1], :zoom) == "1.0" + @test Tables.getcolumn(features[1], :location) == "Mumbai" + @test AG.toWKT(Tables.getcolumn(features[1], :point)) == "POINT (30 10)" + @test AG.toWKT(Tables.getcolumn(features[1], :linestring)) == "LINESTRING (30 10,10 30,40 40)" + @test isnothing(Tables.getcolumn(features[1], :fake)) + + @test Tables.columnnames(features[2]) == (:id, :zoom, :location, :point, :linestring) + @test Tables.getcolumn(features[2], 1) == "5.2" + @test Tables.getcolumn(features[2], 2) == "2.0" + @test Tables.getcolumn(features[2], 3) == "New Delhi" + @test AG.toWKT(Tables.getcolumn(features[2], 4)) == "POINT (35 15)" + @test AG.toWKT(Tables.getcolumn(features[2], 5)) == "LINESTRING (35 15,15 35,45 45)" + @test Tables.getcolumn(features[2], :id) == "5.2" + @test Tables.getcolumn(features[2], :zoom) == "2.0" + @test Tables.getcolumn(features[2], :location) == "New Delhi" + @test AG.toWKT(Tables.getcolumn(features[2], :point)) == "POINT (35 15)" + @test AG.toWKT(Tables.getcolumn(features[2], :linestring)) == "LINESTRING (35 15,15 35,45 45)" + @test isnothing(Tables.getcolumn(features[2], :fake)) end @testset "Misc. methods" begin AG.resetreading!(layer) AG.resetreading!(layer1) - schema_names = AG.schema_names(layer) - schema_names1 = AG.schema_names(layer1) + schema_names = AG.schema_names(AG.layerdefn(layer)) + schema_names1 = AG.schema_names(AG.layerdefn(layer1)) for i in 1:4 @test schema_names[i] isa Base.Generator || schema_names[i] isa ArchGDAL.IFeatureDefnView From b13e5dbf5e65e38f2b9b6bc35c84c0deb79f9f0d Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 18:59:54 -0700 Subject: [PATCH 038/169] Add tests for rasterio!(...) Spotted an indexing bug and fixed it along the way. --- src/raster/rasterio.jl | 93 ++++++++++++--------------- test/test_rasterio.jl | 140 ++++++++++++++++++++++++----------------- 2 files changed, 122 insertions(+), 111 deletions(-) diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index eec4712f..63cf1cf0 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -69,10 +69,10 @@ function rasterio!( dataset::AbstractDataset, buffer::T, bands, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, )::T where {T <: Array{<:Real, 3}} rasterio!(dataset, buffer, bands, 0, 0, size(buffer, 1), size(buffer, 2), access, pxspace, linespace, bandspace) @@ -81,19 +81,19 @@ end function rasterio!( dataset::AbstractDataset, - buffer::T, + buffer::Array{T, 3}, bands, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0 - )::T where {T <: Array{<:Real, 3}} + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, + )::Array{T, 3} where {T <: Any} xsize = cols[end] - cols[1] + 1; xsize < 0 && error("invalid window width") ysize = rows[end] - rows[1] + 1; ysize < 0 && error("invalid window height") - rasterio!(dataset, buffer, bands, cols[1], rows[1], xsize, ysize, access, - pxspace, linespace, bandspace) + rasterio!(dataset, buffer, bands, cols[1] - 1, rows[1] - 1, xsize, ysize, + access, pxspace, linespace, bandspace) return buffer end @@ -105,11 +105,11 @@ function rasterio!( yoffset::Integer, xsize::Integer, ysize::Integer, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0, - extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, + extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) )::Array{T, 3} where {T <: Any} # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg # structure with additional arguments to specify resampling and @@ -132,9 +132,9 @@ end function rasterio!( rasterband::AbstractRasterBand, buffer::T, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, )::T where {T <: Matrix{<:Real}} rasterio!(rasterband, buffer, 0, 0, width(rasterband), height(rasterband), access, pxspace, linespace) @@ -146,14 +146,14 @@ function rasterio!( buffer::T, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0 + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, )::T where {T <: Matrix{<:Real}} xsize = length(cols); xsize < 1 && error("invalid window width") ysize = length(rows); ysize < 1 && error("invalid window height") - rasterio!(rasterband, buffer, cols[1]-1, rows[1]-1, xsize, ysize, access, - pxspace, linespace) + rasterio!(rasterband, buffer, cols[1] - 1, rows[1] - 1, xsize, ysize, + access, pxspace, linespace) return buffer end @@ -164,10 +164,10 @@ function rasterio!( yoffset::Integer, xsize::Integer, ysize::Integer, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL), )::Matrix{T} where {T <: Any} # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg # structure with additional arguments to specify resampling and @@ -239,14 +239,6 @@ function read( return buffer end -function write!( - rb::AbstractRasterBand, - buffer::T - )::T where {T <: Matrix{<:Real}} - rasterio!(rb, buffer, GF_Write) - return buffer -end - function write!( rb::AbstractRasterBand, buffer::T, @@ -262,8 +254,8 @@ end function write!( rb::AbstractRasterBand, buffer::T, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} + rows::UnitRange{<:Integer} = 1:height(rb), + cols::UnitRange{<:Integer} = 1:width(rb), )::T where {T <: Matrix{<:Real}} rasterio!(rb, buffer, rows, cols, GF_Write) return buffer @@ -372,7 +364,9 @@ function read( xsize::Integer, ysize::Integer )::Matrix{pixeltype(dataset)} - buffer = read(getband(dataset, i), xoffset, yoffset, xsize, ysize) + band = getband(dataset, i) + buffer = Matrix{pixeltype(band)}(undef, xsize, ysize) + read!(dataset, buffer, i, xoffset, yoffset, xsize, ysize) return buffer end @@ -412,15 +406,6 @@ function read( return buffer end -function write!( - dataset::T, - buffer::Matrix{<:Real}, - i::Integer - )::T where {T <: AbstractDataset} - write!(getband(dataset, i), buffer) - return dataset -end - function write!( dataset::T, buffer::Array{<:Real, 3}, @@ -461,8 +446,8 @@ function write!( dataset::T, buffer::Matrix{<:Real}, i::Integer, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} + rows::UnitRange{<:Integer} = 1:height(getband(dataset, i)), + cols::UnitRange{<:Integer} = 1:width(getband(dataset, i)), )::T where {T <: AbstractDataset} write!(getband(dataset, i), buffer, rows, cols) return dataset @@ -472,8 +457,8 @@ function write!( dataset::T, buffer::Array{<:Real, 3}, indices, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} + rows::UnitRange{<:Integer} = 1:height(dataset), + cols::UnitRange{<:Integer} = 1:width(dataset), )::T where {T <: AbstractDataset} rasterio!(dataset, buffer, indices, rows, cols, GF_Write) return dataset @@ -535,6 +520,6 @@ function writeblock!( buffer )::T where {T <: AbstractRasterBand} result = GDAL.gdalwriteblock(rb.ptr, xoffset, yoffset, buffer) - @cplerr result "Failed to write block at ($xoffset,$yoffset)" + @cplerr result "Failed to write block at ($xoffset, $yoffset)" return rb end diff --git a/test/test_rasterio.jl b/test/test_rasterio.jl index e5bbccf4..4dc87e5b 100644 --- a/test/test_rasterio.jl +++ b/test/test_rasterio.jl @@ -10,8 +10,8 @@ AG.read("ospy/data4/aster.img") do ds total = 0 buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) for (cols,rows) in AG.windows(band) - AG.rasterio!(ds, buffer, [1], rows .- 1, cols .- 1) - data = buffer[1:length(cols),1:length(rows)] + AG.rasterio!(ds, buffer, [1], rows, cols) + data = buffer[1:length(cols), 1:length(rows)] count += sum(data .> 0) total += sum(data) end @@ -25,8 +25,8 @@ AG.read("ospy/data4/aster.img") do ds total = 0 buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) for (cols,rows) in AG.windows(band) - AG.read!(ds, buffer, [1], rows .- 1, cols .- 1) - data = buffer[1:length(cols),1:length(rows)] + AG.read!(ds, buffer, [1], rows, cols) + data = buffer[1:length(cols), 1:length(rows)] count += sum(data .> 0) total += sum(data) end @@ -38,7 +38,7 @@ AG.read("ospy/data4/aster.img") do ds band = AG.getband(ds, 1) count = 0 total = 0 - buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)...) + buffer = Matrix{AG.pixeltype(band)}(undef, AG.blocksize(band)...) for (cols,rows) in AG.windows(band) AG.read!(ds, buffer, 1, rows, cols) data = buffer[1:length(cols),1:length(rows)] @@ -53,7 +53,7 @@ AG.read("ospy/data4/aster.img") do ds band = AG.getband(ds, 1) count = 0 total = 0 - buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)...) + buffer = Matrix{AG.pixeltype(band)}(undef, AG.blocksize(band)...) for (cols,rows) in AG.windows(band) AG.read!(band, buffer, rows, cols) data = buffer[1:length(cols),1:length(rows)] @@ -69,7 +69,7 @@ AG.read("ospy/data4/aster.img") do ds count = 0 total = 0 xbsize, ybsize = AG.blocksize(band) - buffer = Array{AG.pixeltype(band)}(undef, ybsize, xbsize) + buffer = Matrix{AG.pixeltype(band)}(undef, ybsize, xbsize) for ((i,j),(nrows,ncols)) in AG.blocks(band) # AG.rasterio!(ds,buffer,[1],i,j,nrows,ncols) # AG.read!(band, buffer, j, i, ncols, nrows) @@ -94,7 +94,7 @@ AG.read("ospy/data4/aster.img") do ds @testset "version 7" begin band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) + buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) AG.read!(band, buffer) count = sum(buffer .> 0) total = sum(buffer) @@ -104,7 +104,7 @@ AG.read("ospy/data4/aster.img") do ds @testset "version 8" begin band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) + buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) AG.read!(ds, buffer, 1) count = sum(buffer .> 0) total = sum(buffer) @@ -139,7 +139,7 @@ AG.read("ospy/data4/aster.img") do ds total = 0 buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) for (cols,rows) in AG.windows(band) - AG.rasterio!(ds, buffer, (1,), rows .- 1, cols .- 1) + AG.rasterio!(ds, buffer, (1,), rows, cols) data = buffer[1:length(cols),1:length(rows)] count += sum(data .> 0) total += sum(data) @@ -153,56 +153,82 @@ AG.read("ospy/data4/aster.img") do ds @test size(AG.read(ds, [1, 3], 0, 0, 20, 10)) === (20, 10, 2) @test size(AG.read(ds, 1, 1:10, 31:50)) === (20, 10) @test size(AG.read(ds, [1, 3], 1:10, 31:50)) === (20, 10, 2) + @test size(AG.read(ds, 1:2)) == (5665, 5033, 2) band = AG.getband(ds, 1) @test size(AG.read( band, 0, 0, 20, 10)) === (20, 10) end -end -# Untested -# writeblock!(rb::RasterBand, xoffset::Integer, yoffset::Integer, buffer) -# read!(rb::RasterBand, buffer::Array{Real,2}, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer) -# read!(dataset::Dataset, buffer::Array{T,2}, i::Integer, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer) -# read!(dataset::Dataset, buffer::Array{T,3}, indices, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer) - -# read{U <: Integer}(rb::RasterBand, rows::UnitRange{U}, cols::UnitRange{U}) -# read(dataset::Dataset, indices) -# read(dataset::Dataset) -# read{T <: Integer}(dataset::Dataset, indices::Vector{T}, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer) -# read{U <: Integer}(dataset::Dataset, i::Integer, rows::UnitRange{U}, cols::UnitRange{U}) -# read{U <: Integer}(dataset::Dataset, indices, rows::UnitRange{U}, cols::UnitRange{U})update!{T <: Real}(rb::RasterBand, buffer::Array{T,2}) = - -# write!(rb::RasterBand, buffer::Array{T,2}, rows::UnitRange{U}, cols::UnitRange{U}) -# write!(dataset::Dataset, buffer::Array{T,2}, i::Integer) -# write!(dataset::Dataset, buffer::Array{T,3}, indices) -# write!(dataset::Dataset, buffer::Array{T,3}, indices, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer) -# write!(dataset::Dataset, buffer::Array{T,2}, i::Integer, rows::UnitRange{U}, cols::UnitRange{U}) -# write!(dataset::Dataset, buffer::Array{T,3}, indices, rows::UnitRange{U}, cols::UnitRange{U}) - -# function rasterio!(dataset::Dataset, -# buffer::Array{$T, 3}, -# bands, -# xoffset::Integer, -# yoffset::Integer, -# xsize::Integer, -# ysize::Integer, -# access::GDALRWFlag=GF_Read, -# pxspace::Integer=0, -# linespace::Integer=0, -# bandspace::Integer=0, -# extraargs=Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL)) -# (dataset == C_NULL) && error("Can't read invalid rasterband") -# xbsize, ybsize, zbsize = size(buffer) -# nband = length(bands); @assert nband == zbsize -# result = ccall((:GDALDatasetRasterIOEx,GDAL.libgdal),GDAL.CPLErr, -# (Dataset,GDAL.GDALRWFlag,Cint,Cint,Cint,Cint, -# Ptr{Cvoid},Cint,Cint,GDAL.GDALDataType,Cint, -# Ptr{Cint},GDAL.GSpacing,GDAL.GSpacing,GDAL.GSpacing, -# Ptr{GDAL.GDALRasterIOExtraArg}),dataset,access, -# xoffset,yoffset,xsize,ysize,pointer(buffer),xbsize, -# ybsize,$GT,nband,pointer(bands),pxspace,linespace, -# bandspace,extraargs) -# @cplerr result "Access in DatasetRasterIO failed." -# buffer -# end + @testset "Writing to buffers" begin + band = AG.getband(ds, 1) + @test AG.pixeltype(band) == UInt8 + xbsize, ybsize = AG.blocksize(band) + AG.create( + AG.getdriver("MEM"), + width = AG.width(band), + height = AG.height(band), + nbands = 2, + dtype = AG.pixeltype(band) + ) do dsout + bandout = AG.getband(dsout, 1) + + @testset "writeblock!(rb::RasterBand, xoffset, yoffset, buffer)" begin + # We write everything to typemax(UInt8) + for ((i,j),(nrows,ncols)) in AG.blocks(bandout) + AG.writeblock!(bandout, j, i, fill(typemax(UInt8), ncols, nrows)) + end + buffer = AG.read(bandout) + nnzero = sum(buffer .> 0) + @test nnzero == AG.height(bandout) * AG.width(bandout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + for ((i,j),(nrows,ncols)) in AG.blocks(bandout) + AG.writeblock!(bandout, j, i, fill(0x00, ncols, nrows)) + end + @test sum(AG.read(bandout) .> 0) == 0 + end + + @testset "write!(rb::RasterBand, buffer::Matrix[, rows, cols])" begin + # We write everything to typemax(UInt8) + AG.write!(bandout, fill(typemax(UInt8), AG.height(bandout), AG.width(bandout))) + buffer = AG.read(bandout) + nnzero = sum(buffer .> 0) + @test nnzero == AG.height(bandout) * AG.width(bandout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + AG.write!(bandout, fill(0x00, AG.height(bandout), AG.width(bandout))) + @test sum(AG.read(bandout) .> 0) == 0 + end + + @testset "write!(dataset::Dataset, buffer::Matrix, i::Integer[, rows, cols])" begin + # We write everything to typemax(UInt8) + AG.write!(dsout, fill(typemax(UInt8), AG.height(bandout), AG.width(bandout)), 1) + buffer = AG.read(bandout) + nnzero = sum(buffer .> 0) + @test nnzero == AG.height(bandout) * AG.width(bandout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + AG.write!(dsout, fill(0x00, AG.height(bandout), AG.width(bandout)), 1) + @test sum(AG.read(bandout) .> 0) == 0 + end + + @testset "write!(dataset::Dataset, buffer::Array, indices[, rows, cols])" begin + # We write everything to typemax(UInt8) + AG.write!(dsout, fill(typemax(UInt8), AG.height(dsout), AG.width(dsout), 2), 1:2) + buffer = AG.read(dsout) + nnzero = sum(buffer .> 0) + @test nnzero == 2 * AG.height(dsout) * AG.width(dsout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + AG.write!(dsout, fill(0x00, AG.height(dsout), AG.width(dsout), 2), 1:2) + @test sum(AG.read(dsout) .> 0) == 0 + end + end + end + +end end From 26cd97ad33ae4e702511656666e60b34400621d3 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:14:57 -0700 Subject: [PATCH 039/169] Add tests for raster/array.jl --- src/raster/array.jl | 10 +++++----- test/test_array.jl | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/raster/array.jl b/src/raster/array.jl index 487fbd87..6a1b52b3 100644 --- a/src/raster/array.jl +++ b/src/raster/array.jl @@ -39,9 +39,9 @@ end # Forward a few functions # Here we try to include all functions that are relevant # for raster-like datasets. -for f in (:getgeotransform, :nraster, :getband, :getproj, - :width, :height, :destroy, :getdriver, :filelist, :listcapability, - :ngcp, :copy, :write, :testcapability, :setproj!, :buildoverviews!) +for f in (:getgeotransform, :nraster, :getband, :getproj, :width, :height, + :destroy, :getdriver, :filelist, :listcapability, :ngcp, :copy, + :unsafe_copy, :write, :testcapability, :setproj!, :buildoverviews!) eval(:( $(f)(x::RasterDataset, args...; kwargs...) = $(f)(x.ds, args...; kwargs...) @@ -63,7 +63,7 @@ function copywholeraster!( dest::RasterDataset; kwargs... )::RasterDataset - copywholeraster!(source.ds, dest.ds; kwargs...) + copywholeraster!(source, dest.ds; kwargs...) return dest end @@ -72,7 +72,7 @@ function copywholeraster!( dest::RasterDataset; kwargs... )::RasterDataset - copywholeraster!(source.ds, dest.ds; kwargs...) + copywholeraster!(source, dest.ds; kwargs...) return dest end diff --git a/test/test_array.jl b/test/test_array.jl index be707c37..25c1b066 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -140,6 +140,11 @@ end count = sum(buffer[:, :, 1:1] .> 0) @test total / count ≈ 76.33891347095299 @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + + AG.copy(ds) do copy1 + @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) + @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) + end end end From 63c6eb4202b270b4bf6f1a21139c2f92f5c545fb Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:23:36 -0700 Subject: [PATCH 040/169] [Breaking] Remove untested method for addfielddefn() --- src/context.jl | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/context.jl b/src/context.jl index 33bb8b90..d66f950b 100644 --- a/src/context.jl +++ b/src/context.jl @@ -116,27 +116,6 @@ function addfielddefn!( return layer end -function addfielddefn( - f::Function, - layer::AbstractFeatureLayer, - name::AbstractString, - etype::OGRFieldType; - nwidth::Integer = 0, - nprecision::Integer = 0, - justify::OGRJustification = OJUndefined, - approx::Bool = false - ) - fielddefn = unsafe_createfielddefn(name, etype) - setparams!(fielddefn, name, etype, nwidth = nwidth, nprecision = nprecision, - justify = justify) - return try - f(fielddefn) - addfielddefn!(layer, fielddefn) - finally - destroy(fielddefn) - end -end - """ writegeomdefn!(layer::AbstractFeatureLayer, name, etype::OGRwkbGeometryType, approx=false) From 987fe10106cbde6082616b617ca362c53b585354 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:39:41 -0700 Subject: [PATCH 041/169] Add tests for displays of different objects --- src/base/display.jl | 4 ++-- test/test_array.jl | 11 +++++++++++ test/test_display.jl | 11 +++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index d2dbf0ba..acadf4ce 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -108,7 +108,7 @@ end # assumes that the layer is reset, and will reset it after display function Base.show(io::IO, layer::AbstractFeatureLayer)::IO if layer.ptr == C_NULL - println(io, "NULL Layer") + print(io, "NULL FeatureLayer") return io end layergeomtype = getgeomtype(layer) @@ -214,7 +214,7 @@ end function Base.show(io::IO, feature::Feature)::IO if feature.ptr == C_NULL - println(io, "NULL Feature") + print(io, "NULL Feature") return io end println(io, "Feature") diff --git a/test/test_array.jl b/test/test_array.jl index 25c1b066..1beb2963 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -134,6 +134,17 @@ end @testset "Test Array constructor" begin AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_UPDATE) do ds + @test sprint(print, ds) == """ + GDAL Dataset (Driver: HFA/Erdas Imagine Images (.img)) + File(s): + ospy/data4/aster_write.img + + Dataset (width x height): 5665 x 5033 (pixels) + Number of raster bands: 3 + [GA_Update] Band 1 (Undefined): 5665 x 5033 (UInt8) + [GA_Update] Band 2 (Undefined): 5665 x 5033 (UInt8) + [GA_Update] Band 3 (Undefined): 5665 x 5033 (UInt8) + """ buffer = Array(ds) typeof(buffer) <: Array{UInt8,3} total = sum(buffer[:, :, 1:1]) diff --git a/test/test_display.jl b/test/test_display.jl index cd4e8771..b8bfec86 100644 --- a/test/test_display.jl +++ b/test/test_display.jl @@ -3,6 +3,17 @@ import ArchGDAL; const AG = ArchGDAL @testset "test_display.jl" begin +@testset "Testing Displays for NULL objects" begin + @test sprint(print, AG.Driver(C_NULL)) == "NULL Driver" + @test sprint(print, AG.IDataset()) == "NULL Dataset" + @test sprint(print, AG.IRasterBand{UInt8}()) == "NULL RasterBand" + @test sprint(print, AG.IFeatureLayer()) == "NULL FeatureLayer" + @test sprint(print, AG.IFeatureDefnView()) == "NULL FeatureDefn" + @test sprint(print, AG.IFieldDefnView()) == "NULL FieldDefn" + @test sprint(print, AG.IGeomFieldDefnView()) == "NULL GeomFieldDefn" + @test sprint(print, AG.Feature(C_NULL)) == "NULL Feature" +end + @testset "Testing Displays for different objects" begin AG.read("data/point.geojson") do dataset @test sprint(print, dataset) == """ From 1d0b36514b5d3d05c4a2011b03f073da180d65ec Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:42:57 -0700 Subject: [PATCH 042/169] Add test for unsafe_getgeom(feature) --- test/test_feature.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_feature.jl b/test/test_feature.jl index 8542cc30..3d7881dd 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -13,7 +13,9 @@ AG.read("data/point.geojson") do dataset (index 0) FID => 2.0 (index 1) pointname => point-a """ - @test sprint(print, AG.getgeom(f1)) == "Geometry: POINT (100 0)" + AG.getgeom(f1) do g1 + @test sprint(print, g1) == "Geometry: POINT (100 0)" + end fid1 = AG.getfid(f1) @test fid1 == 0 From a4eb87ee2465feee6a0b8aa15f6d09e616277985 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:50:27 -0700 Subject: [PATCH 043/169] Improve test coverage for raster/array.jl --- test/test_array.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_array.jl b/test/test_array.jl index 1beb2963..20cb5839 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -154,7 +154,7 @@ end AG.copy(ds) do copy1 @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) - @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) + @test typeof(AG.copywholeraster!(RasterDataset(copy1), ds)) == typeof(ds) end end end From 4446f220291c4124e3be7ab1161070db76f1592c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:53:51 -0700 Subject: [PATCH 044/169] add tests for tables.jl --- test/test_tables.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_tables.jl b/test/test_tables.jl index 7a0640ba..81bcc514 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -39,6 +39,8 @@ using Tables @test length(features) == 2 @test Tables.columnnames(features[1]) == (:id, :zoom, :location, :point, :linestring) + @test Tables.getcolumn(features[2], -5) == nothing + @test Tables.getcolumn(features[2], 0) == nothing @test Tables.getcolumn(features[1], 1) == "5.1" @test Tables.getcolumn(features[1], 2) == "1.0" @test Tables.getcolumn(features[1], 3) == "Mumbai" @@ -52,6 +54,8 @@ using Tables @test isnothing(Tables.getcolumn(features[1], :fake)) @test Tables.columnnames(features[2]) == (:id, :zoom, :location, :point, :linestring) + @test Tables.getcolumn(features[2], -5) == nothing + @test Tables.getcolumn(features[2], 0) == nothing @test Tables.getcolumn(features[2], 1) == "5.2" @test Tables.getcolumn(features[2], 2) == "2.0" @test Tables.getcolumn(features[2], 3) == "New Delhi" From f93587d2e31f15b13a24981bc06a0e74ce53c1f0 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 19:55:01 -0700 Subject: [PATCH 045/169] add prefix --- test/test_array.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_array.jl b/test/test_array.jl index 20cb5839..74ce33c7 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -154,7 +154,7 @@ end AG.copy(ds) do copy1 @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) - @test typeof(AG.copywholeraster!(RasterDataset(copy1), ds)) == typeof(ds) + @test typeof(AG.copywholeraster!(AG.RasterDataset(copy1), ds)) == typeof(ds) end end end From 83bec76c9dc2dce3696fcf7190d176fc7fd5221e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 20:29:13 -0700 Subject: [PATCH 046/169] Remove obsolete function It has been overridden by the following function further below: ``` write!( dataset::T, buffer::Array{<:Real, 3}, indices, rows::UnitRange{<:Integer} = 1:height(dataset), cols::UnitRange{<:Integer} = 1:width(dataset), )::T where {T <: AbstractDataset} ``` --- src/raster/rasterio.jl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 63cf1cf0..944b28ba 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -406,15 +406,6 @@ function read( return buffer end -function write!( - dataset::T, - buffer::Array{<:Real, 3}, - indices - )::T where {T <: AbstractDataset} - rasterio!(dataset, buffer, indices, GF_Write) - return dataset -end - function write!( dataset::T, buffer::Matrix{<:Real}, From 340d43188881d5d4a491a6780218024db266142e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 20:58:25 -0700 Subject: [PATCH 047/169] Add support for displaying color tables --- src/base/display.jl | 13 +++++++++++++ src/raster/colortable.jl | 9 +++++++-- src/raster/rasterband.jl | 10 ++-------- test/test_rasterattrtable.jl | 6 ++++++ 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index acadf4ce..a58b88d2 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -270,3 +270,16 @@ function Base.show(io::IO, geom::AbstractGeometry)::IO end return io end + +function Base.show(io::IO, ct::ColorTable)::IO + if ct.ptr == C_NULL + print(io, "NULL ColorTable") + return io + end + palette = paletteinterp(ct) + print(io, "ColorTable[$palette] with $nentries entries") + return io +end + +Base.show(io::IO, ::MIME"text/plain", ct::ColorTable)::IO = + show(io, ct) diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index 8bfb211b..82987c80 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -18,8 +18,13 @@ end Make a copy of a color table. """ -unsafe_clone(ct::ColorTable)::ColorTable = - ColorTable(GDAL.gdalclonecolortable(ct.ptr)) +function unsafe_clone(ct::ColorTable)::ColorTable + return if ct.ptr == C_NULL + ColorTable(C_NULL) + else + ColorTable(GDAL.gdalclonecolortable(ct.ptr)) + end +end """ paletteinterp(ct::ColorTable) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 1e39305d..393b3ed2 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -375,14 +375,8 @@ Returns a clone of the color table associated with the band. original color table remains owned by the `RasterBand`, and can't be depended on for long, nor should it ever be modified by the caller.) """ -function unsafe_getcolortable(band::AbstractRasterBand)::ColorTable - result = ColorTable(GDAL.gdalgetrastercolortable(band.ptr)) - return if result.ptr == C_NULL - result - else - unsafe_clone(result) - end -end +unsafe_getcolortable(band::AbstractRasterBand)::ColorTable = + unsafe_clone(ColorTable(GDAL.gdalgetrastercolortable(band.ptr))) """ setcolortable!(band::AbstractRasterBand, colortable::ColorTable) diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index c5a59313..10a10316 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -88,11 +88,13 @@ end @testset ("Testing Color Tables") begin AG.createcolortable(AG.GPI_RGB) do ct + @test sprint(print, ct) == "ColorTable[GPI_RGB] with 0 entries" @test AG.paletteinterp(ct) == AG.GPI_RGB @test AG.ncolorentry(ct) == 0 AG.createcolorramp!(ct, 128, GDAL.GDALColorEntry(0,0,0,0), 255, GDAL.GDALColorEntry(0,0,255,0)) @test AG.ncolorentry(ct) == 256 + @test sprint(print, ct) == "ColorTable[GPI_RGB] with 256 entries" @test sprint(print, AG.getcolorentry(ct, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" @test sprint(print, AG.getcolorentry(ct, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" @test sprint(print, AG.getcolorentry(ct, 200)) == "GDAL.GDALColorEntry(0, 0, 144, 0)" @@ -124,6 +126,10 @@ end @test sprint(print, AG.getcolorentry(ct2, 255)) == "GDAL.GDALColorEntry(0, 0, 100, 0)" end end + + AG.clone(AG.ColorTable(C_NULL)) do ct + @test sprint(print, ct) == "NULL ColorTable" + end end end From d557d0a8cc87651d82caa0f18df10562fa3cb422 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 20:58:45 -0700 Subject: [PATCH 048/169] got missed in the previous commit --- src/base/display.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base/display.jl b/src/base/display.jl index a58b88d2..84b65fad 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -277,6 +277,7 @@ function Base.show(io::IO, ct::ColorTable)::IO return io end palette = paletteinterp(ct) + nentries = ncolorentry(ct) print(io, "ColorTable[$palette] with $nentries entries") return io end From c8aaeb8fdcbce7547c5cb3db4798cfcb6edc2b01 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:03:13 -0700 Subject: [PATCH 049/169] Delete obsolete function It has an alternative implementation below, which is exercised in the unit test. --- src/raster/rasterband.jl | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 393b3ed2..6d394203 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -214,17 +214,6 @@ function deletenodatavalue!(band::T)::T where {T <: AbstractRasterBand} return band end -""" - setcategorynames!(band::AbstractRasterBand, names) - -Set the category names for this band. -""" -function setcategorynames!(band::T, names)::T where {T <: AbstractRasterBand} - result = GDAL.gdalsetrastercategorynames(band.ptr, names) - @cplerr result "Failed to set category names" - return band -end - """ minimum(band::AbstractRasterBand) From 8b499d667a2a28f0c622694f875d3d60f362c62d Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:03:21 -0700 Subject: [PATCH 050/169] Whitespacing --- test/test_rasterband.jl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 861ee856..73c47056 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -91,7 +91,12 @@ import ArchGDAL; const AG = ArchGDAL blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: """ @test AG.maskflags(destband) == 1 - @test AG.maskflaginfo(rb) == (all_valid = true, per_dataset = false, alpha = false, nodata = false) + @test AG.maskflaginfo(rb) == ( + all_valid = true, + per_dataset = false, + alpha = false, + nodata = false + ) AG.createmaskband!(destband, 3) AG.getmaskband(destband) do maskband @test sprint(print, maskband) == """ @@ -100,9 +105,14 @@ import ArchGDAL; const AG = ArchGDAL overviews: """ end @test AG.maskflags(destband) == 3 - @test AG.maskflaginfo(destband) == (all_valid = true, per_dataset = true, alpha = false, nodata = false) + @test AG.maskflaginfo(destband) == ( + all_valid = true, + per_dataset = true, + alpha = false, + nodata = false + ) AG.fillraster!(destband, 3) - AG.setcategorynames!(destband, ["foo","bar"]) + AG.setcategorynames!(destband, ["foo", "bar"]) @test AG.getcategorynames(destband) == ["foo", "bar"] AG.getoverview(destband, 0) do overview From 8c720e7f24e633475c18dc4288e8743b3d0767fc Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:08:54 -0700 Subject: [PATCH 051/169] Add test for reproject in the case of a no-op --- test/test_cookbook_projection.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_cookbook_projection.jl b/test/test_cookbook_projection.jl index f4f869ee..1e286ddf 100644 --- a/test/test_cookbook_projection.jl +++ b/test/test_cookbook_projection.jl @@ -39,6 +39,7 @@ const GFT = GeoFormatTypes end @testset "reproject vector, vector of vector, or tuple" begin coord = [1120351.57, 741921.42] + @test AG.reproject(coord, GFT.EPSG(2927), nothing) ≈ [1120351.57, 741921.42] @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326)) ≈ [47.3488070138318, -122.5981499431438] @test AG.reproject([coord], GFT.EPSG(2927), GFT.EPSG(4326)) ≈ From 3221556544fed87642cb5138afd3f019d787a44c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:12:44 -0700 Subject: [PATCH 052/169] Add test for copywholeraster! --- test/test_array.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_array.jl b/test/test_array.jl index 74ce33c7..e5e8f6ac 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -155,6 +155,7 @@ end AG.copy(ds) do copy1 @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) @test typeof(AG.copywholeraster!(AG.RasterDataset(copy1), ds)) == typeof(ds) + @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) end end end From d19f53e180d19a6670b88909cb64ac594313f5f3 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:19:25 -0700 Subject: [PATCH 053/169] Add test for unsafe_getgeom(feature, name) --- test/test_feature.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test_feature.jl b/test/test_feature.jl index 3d7881dd..487f16cb 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -19,13 +19,19 @@ AG.read("data/point.geojson") do dataset fid1 = AG.getfid(f1) @test fid1 == 0 + AG.getgeom(f2, "fake name") do g + @test sprint(print, g) == "NULL Geometry" + end + @test sprint(print, f2) == """ Feature (index 0) geom => POINT (index 0) FID => 0.0 (index 1) pointname => a """ - @test sprint(print, AG.getgeom(f2)) == "Geometry: POINT (100 0)" + AG.getgeom(f2, "") do g2 + @test sprint(print, g2) == "Geometry: POINT (100 0)" + end fid2 = AG.getfid(f2) @test fid2 == 2 From e73d91c3155819c2edcb5fb806d9434551e3a163 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:19:43 -0700 Subject: [PATCH 054/169] Add test for unsafe_copy(layer) --- test/test_featurelayer.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_featurelayer.jl b/test/test_featurelayer.jl index 0a661ccd..593c4d3b 100644 --- a/test/test_featurelayer.jl +++ b/test/test_featurelayer.jl @@ -19,6 +19,9 @@ import ArchGDAL; const AG = ArchGDAL AG.copy(dataset, driver = AG.getdriver("Memory")) do tmpcopy tmplayer = AG.getlayer(dataset, 0) + AG.copy(tmplayer) do copylayer + @test AG.nfeature(tmplayer) == AG.nfeature(copylayer) + end @test sprint(print, AG.getspatialref(tmplayer)) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" AG.getspatialref(tmplayer) do spref @test sprint(print, spref) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" From 97654628d5b2c39363b5e1bd59b0632c0af390db Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 21:23:25 -0700 Subject: [PATCH 055/169] Add tests for cloning null geometries --- test/test_geometry.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 5bbe23a0..33c5af30 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -312,4 +312,12 @@ end end end end end end +@testset "Cloning NULL geometries" begin + geom = AG.IGeometry() + @test sprint(print, AG.clone(geom)) == "NULL Geometry" + AG.clone(geom) do g + @test sprint(print, g) == "NULL Geometry" + end +end + end From f5ee1205d11c5a9e1a7aaa3a6ea4d48503101d5e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 23:04:22 -0700 Subject: [PATCH 056/169] Update the documentation for working with the tables interface --- docs/src/tables.md | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/docs/src/tables.md b/docs/src/tables.md index 0f8ae9f6..ff34b244 100644 --- a/docs/src/tables.md +++ b/docs/src/tables.md @@ -28,21 +28,7 @@ The [`ArchGDAL.Table`](@ref) method accepts an `ArchGDAL.FeatureLayer`. table = ArchGDAL.Table(layer) ``` -Individual rows can be retrieved using the `Base.getindex(t::ArchGDAL.Table, idx::Int)` method or simply `table[idx]`. - -```@example tables -row = table[1] -``` - -Layers are retrievable! -One can get back the layer that a Table is made up of. -```@example tables -lyr = ArchGDAL.getlayer(table) -``` - -The Tables interface also support multiple geometries per layer. - -Here, we visit the +Finally layers can be converted to DataFrames to perform miscellaneous spatial operations. Here, we visit the [`data/multi_geom.csv`](https://github.com/yeesian/ArchGDALDatasets/blob/master/data/multi_geom.csv) dataset. @@ -51,22 +37,7 @@ dataset1 = ArchGDAL.read("data/multi_geom.csv", options = ["GEOM_POSSIBLE_NAMES= layer = ArchGDAL.getlayer(dataset, 0) table = ArchGDAL.Table(layer) -``` - -Exatracting a row from the table, we see that the row/feature is made up of two geometries -viz. `point` and `linestring`. -```@example tables -row = table[1] -``` - -Finally layers can be converted to DataFrames to perform miscellaneous spatial operations. -```@example tables df = DataFrame(table) ``` -In some cases the `nextfeature` might become a bit tedious to use. In which case the `ArchGDAL.nextnamedtuple()` method comes in handy. Though built upon `nextfeature`, simply calling it, yields the `feature` as a `NamedTuple`. Though one might have to use `ArchGDAL.resetreading!(layer)` method to reset the layer reading to the start. -```@example tables -ArchGDAL.resetreading!(layer) -feat1 = ArchGDAL.nextnamedtuple(layer) -feat2 = ArchGDAL.nextnamedtuple(layer) -``` +The Tables interface also supports multiple geometries per layer. From 37ad420d5cec202cf579a3de328e1326b8c1f4a2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 23:32:14 -0700 Subject: [PATCH 057/169] Update API reference for geotransfromations --- docs/src/reference.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/src/reference.md b/docs/src/reference.md index 0c16580e..3519bf58 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -4,7 +4,7 @@ ```@autodocs Modules = [ArchGDAL] -Pages = ["ArchGDAL.jl", "display.jl", "iterators.jl", "gcp.jl", "types.jl", "utils.jl"] +Pages = ["ArchGDAL.jl", "display.jl", "iterators.jl", "types.jl", "utils.jl"] ``` ## [GDAL Datasets](@id API-GDAL-Datasets) @@ -34,13 +34,20 @@ Modules = [ArchGDAL] Pages = ["array.jl", "colortable.jl", "rasterattributetable.jl", "rasterband.jl", "rasterio.jl"] ``` -## [Spatial projections](@id API-Spatial-projections) +## [Spatial Projections](@id API-Spatial-Projections) ```@autodocs Modules = [ArchGDAL] Pages = ["spatialref.jl"] ``` +## [Geo Transformations](@id API-GeoTransforms) + +```@autodocs +Modules = [ArchGDAL] +Pages = ["geotransform.jl"] +``` + ## [Utilities](@id API-Utilities) ```@autodocs From c840bb2eca84fe5753923e2ba199359b7e94ccdc Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 25 Apr 2021 23:32:27 -0700 Subject: [PATCH 058/169] Add README for building the documentation --- docs/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..3526e372 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,9 @@ +# ArchGDAL.jl documentation + +The latest stable version of the documentation can be viewed at https://yeesian.com/ArchGDAL.jl/stable/. To build a local version of the documentation, navigate to this directory and run the following command: + +```shell +$ julia make.jl +``` + +It should create files in a subdirectory named `build/`. If it builds successfully, you should be able to preview the documentation in a browser by opening `build/index.html` in a browser. From d7a67df5fb6c9fe6559823e823928e91c137ed4f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Tue, 27 Apr 2021 18:53:40 -0700 Subject: [PATCH 059/169] Fix command for activating the environment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb45b832..d36a719e 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ shell> cd /Users/yeesian/.julia/dev/ArchGDAL 2. Activate the environment corresponding to `Project.toml`): ```julia -(@v1.6) pkg> activate +(@v1.6) pkg> activate . Activating environment at `~/.julia/environments/v1.6/Project.toml` ``` From dfe9652619f384209de6368b0187ae20a8a4bd51 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 30 Apr 2021 20:31:22 -0700 Subject: [PATCH 060/169] Update macro name to reflect its usage and provide a docstring --- src/types.jl | 36 ++++++++++++++++++------------------ src/utils.jl | 24 +++++++++++++++++++++++- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/types.jl b/src/types.jl index 5ce9d63a..2413d6b0 100644 --- a/src/types.jl +++ b/src/types.jl @@ -218,7 +218,7 @@ mutable struct ColorTable ptr::GDAL.GDALColorTableH end -eval(@gdalenum(GDALDataType::GDAL.GDALDataType, +eval(@convert(GDALDataType::GDAL.GDALDataType, GDT_Unknown::GDAL.GDT_Unknown, GDT_Byte::GDAL.GDT_Byte, GDT_UInt16::GDAL.GDT_UInt16, @@ -234,7 +234,7 @@ eval(@gdalenum(GDALDataType::GDAL.GDALDataType, GDT_TypeCount::GDAL.GDT_TypeCount, )) -eval(@gdalenum(GDALDataType::DataType, +eval(@convert(GDALDataType::DataType, GDT_Unknown::Any, GDT_Byte::UInt8, GDT_UInt16::UInt16, @@ -245,7 +245,7 @@ eval(@gdalenum(GDALDataType::DataType, GDT_Float64::Float64, )) -eval(@gdalenum(OGRFieldType::GDAL.OGRFieldType, +eval(@convert(OGRFieldType::GDAL.OGRFieldType, OFTInteger::GDAL.OFTInteger, OFTIntegerList::GDAL.OFTIntegerList, OFTReal::GDAL.OFTReal, @@ -262,7 +262,7 @@ eval(@gdalenum(OGRFieldType::GDAL.OGRFieldType, OFTInteger64List::GDAL.OFTInteger64List, )) -eval(@gdalenum(OGRFieldType::DataType, +eval(@convert(OGRFieldType::DataType, OFTInteger::Int32, OFTIntegerList::Vector{Int32}, OFTReal::Float64, @@ -279,7 +279,7 @@ eval(@gdalenum(OGRFieldType::DataType, OFTInteger64List::Vector{Int64}, )) -eval(@gdalenum(OGRFieldSubType::GDAL.OGRFieldSubType, +eval(@convert(OGRFieldSubType::GDAL.OGRFieldSubType, OFSTNone::GDAL.OFSTNone, OFSTBoolean::GDAL.OFSTBoolean, OFSTInt16::GDAL.OFSTInt16, @@ -287,7 +287,7 @@ eval(@gdalenum(OGRFieldSubType::GDAL.OGRFieldSubType, OFSTJSON::GDAL.OFSTJSON, )) -eval(@gdalenum(OGRFieldSubType::DataType, +eval(@convert(OGRFieldSubType::DataType, OFSTNone::Nothing, OFSTBoolean::Bool, OFSTInt16::Int16, @@ -295,19 +295,19 @@ eval(@gdalenum(OGRFieldSubType::DataType, OFSTJSON::String, )) -eval(@gdalenum(OGRJustification::GDAL.OGRJustification, +eval(@convert(OGRJustification::GDAL.OGRJustification, OJUndefined::GDAL.OJUndefined, OJLeft::GDAL.OJLeft, OJRight::GDAL.OJRight, )) -eval(@gdalenum(GDALRATFieldType::GDAL.GDALRATFieldType, +eval(@convert(GDALRATFieldType::GDAL.GDALRATFieldType, GFT_Integer::GDAL.GFT_Integer, GFT_Real::GDAL.GFT_Real, GFT_String::GDAL.GFT_String, )) -eval(@gdalenum(GDALRATFieldUsage::GDAL.GDALRATFieldUsage, +eval(@convert(GDALRATFieldUsage::GDAL.GDALRATFieldUsage, GFU_Generic::GDAL.GFU_Generic, GFU_PixelCount::GDAL.GFU_PixelCount, GFU_Name::GDAL.GFU_Name, @@ -329,24 +329,24 @@ eval(@gdalenum(GDALRATFieldUsage::GDAL.GDALRATFieldUsage, GFU_MaxCount::GDAL.GFU_MaxCount, )) -eval(@gdalenum(GDALAccess::GDAL.GDALAccess, +eval(@convert(GDALAccess::GDAL.GDALAccess, GA_ReadOnly::GDAL.GA_ReadOnly, GA_Update::GDAL.GA_Update, )) -eval(@gdalenum(GDALRWFlag::GDAL.GDALRWFlag, +eval(@convert(GDALRWFlag::GDAL.GDALRWFlag, GF_Read::GDAL.GF_Read, GF_Write::GDAL.GF_Write, )) -eval(@gdalenum(GDALPaletteInterp::GDAL.GDALPaletteInterp, +eval(@convert(GDALPaletteInterp::GDAL.GDALPaletteInterp, GPI_Gray::GDAL.GPI_Gray, GPI_RGB::GDAL.GPI_RGB, GPI_CMYK::GDAL.GPI_CMYK, GPI_HLS::GDAL.GPI_HLS, )) -eval(@gdalenum(GDALColorInterp::GDAL.GDALColorInterp, +eval(@convert(GDALColorInterp::GDAL.GDALColorInterp, GCI_Undefined::GDAL.GCI_Undefined, GCI_GrayIndex::GDAL.GCI_GrayIndex, GCI_PaletteIndex::GDAL.GCI_PaletteIndex, @@ -366,7 +366,7 @@ eval(@gdalenum(GDALColorInterp::GDAL.GDALColorInterp, GCI_YCbCr_CrBand::GDAL.GCI_YCbCr_CrBand, )) -eval(@gdalenum(GDALAsyncStatusType::GDAL.GDALAsyncStatusType, +eval(@convert(GDALAsyncStatusType::GDAL.GDALAsyncStatusType, GARIO_PENDING::GDAL.GARIO_PENDING, GARIO_UPDATE::GDAL.GARIO_UPDATE, GARIO_ERROR::GDAL.GARIO_ERROR, @@ -374,7 +374,7 @@ eval(@gdalenum(GDALAsyncStatusType::GDAL.GDALAsyncStatusType, GARIO_TypeCount::GDAL.GARIO_TypeCount, )) -eval(@gdalenum(OGRSTClassId::GDAL.OGRSTClassId, +eval(@convert(OGRSTClassId::GDAL.OGRSTClassId, OGRSTCNone::GDAL.OGRSTCNone, OGRSTCPen::GDAL.OGRSTCPen, OGRSTCBrush::GDAL.OGRSTCBrush, @@ -383,7 +383,7 @@ eval(@gdalenum(OGRSTClassId::GDAL.OGRSTClassId, OGRSTCVector::GDAL.OGRSTCVector, )) -eval(@gdalenum(OGRSTUnitId::GDAL.OGRSTUnitId, +eval(@convert(OGRSTUnitId::GDAL.OGRSTUnitId, OGRSTUGround::GDAL.OGRSTUGround, OGRSTUPixel::GDAL.OGRSTUPixel, OGRSTUPoints::GDAL.OGRSTUPoints, @@ -392,7 +392,7 @@ eval(@gdalenum(OGRSTUnitId::GDAL.OGRSTUnitId, OGRSTUInches::GDAL.OGRSTUInches, )) -eval(@gdalenum(OGRwkbGeometryType::GDAL.OGRwkbGeometryType, +eval(@convert(OGRwkbGeometryType::GDAL.OGRwkbGeometryType, wkbUnknown::GDAL.wkbUnknown, wkbPoint::GDAL.wkbPoint, wkbLineString::GDAL.wkbLineString, @@ -473,7 +473,7 @@ function basetype(gt::OGRwkbGeometryType)::OGRwkbGeometryType return GDAL.OGRwkbGeometryType(wkbGeomType) end -eval(@gdalenum(OGRwkbByteOrder::GDAL.OGRwkbByteOrder, +eval(@convert(OGRwkbByteOrder::GDAL.OGRwkbByteOrder, wkbXDR::GDAL.wkbXDR, wkbNDR::GDAL.wkbNDR, )) diff --git a/src/utils.jl b/src/utils.jl index ccedd272..2203e9a9 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,4 +1,26 @@ -macro gdalenum(args...) +""" + + eval(@convert(GDALRWFlag::GDAL.GDALRWFlag, + GF_Read::GDAL.GF_Read, + GF_Write::GDAL.GF_Write, + )) + +does the equivalent of + + Base.convert(::Type{GDAL.GDALRWFlag}, ft::GDALRWFlag) = + Dict{GDALRWFlag, GDAL.GDALRWFlag}( + GF_Read => GDAL.GF_Read, + GF_Write => GDAL.GF_Write + )[ft] + + Base.convert(::Type{GDALRWFlag}, ft::GDAL.GDALRWFlag) = + Dict{GDAL.GDALRWFlag, GDALRWFlag}( + GDAL.GF_Read => GF_Read, + GDAL.GF_Write => GF_Write + )[ft] + +""" +macro convert(args...) @assert length(args) > 0 @assert args[1].head == :(::) type1 = esc(args[1].args[1]) From f9e028c26039e522eb85919bea693f0204f66d05 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 30 Apr 2021 21:52:32 -0700 Subject: [PATCH 061/169] Add support for images Based on the current snapshot of https://github.com/yeesian/ArchGDAL.jl/tree/images. (I got drawn into this from wanting to have proper support for GDAL.GDALColorEntry.) --- .gitignore | 1 + Project.toml | 2 + src/ArchGDAL.jl | 3 ++ src/raster/images.jl | 84 ++++++++++++++++++++++++++++++++++++++++++ src/raster/rasterio.jl | 48 ++++++++++++------------ src/types.jl | 21 ++++++----- 6 files changed, 126 insertions(+), 33 deletions(-) create mode 100644 src/raster/images.jl diff --git a/.gitignore b/.gitignore index 0d6ff5ce..acd3f803 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ test/ospy/ test/pyrasterio/ test/spatialite/ .DS_Store +Manifest.toml diff --git a/Project.toml b/Project.toml index 3faa6b2b..3cb66eb0 100644 --- a/Project.toml +++ b/Project.toml @@ -6,11 +6,13 @@ desc = "A high level API for GDAL - Geospatial Data Abstraction Library" version = "0.6.0" [deps] +ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a" GeoFormatTypes = "68eda718-8dee-11e9-39e7-89f7f65f511f" GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" [compat] diff --git a/src/ArchGDAL.jl b/src/ArchGDAL.jl index 035b473e..0a5b141b 100644 --- a/src/ArchGDAL.jl +++ b/src/ArchGDAL.jl @@ -5,6 +5,8 @@ module ArchGDAL using GeoFormatTypes: GeoFormatTypes using GeoInterface: GeoInterface using Tables: Tables + using ImageCore: ImageCore + using ColorTypes: ColorTypes const GFT = GeoFormatTypes @@ -20,6 +22,7 @@ module ArchGDAL include("raster/array.jl") include("raster/rasterattributetable.jl") include("raster/colortable.jl") + include("raster/images.jl") include("ogr/geometry.jl") include("ogr/feature.jl") include("ogr/featurelayer.jl") diff --git a/src/raster/images.jl b/src/raster/images.jl new file mode 100644 index 00000000..a7a1f42e --- /dev/null +++ b/src/raster/images.jl @@ -0,0 +1,84 @@ +function imread( + colortable::ColorTable, + dataset::AbstractDataset, + indices::NTuple{1, <:Integer} + ) + palette = getcolortable(getband(dataset,indices[1])) do ct + getpaletteinterp(ct) + end + colortype = if palette == GDAL.GPI_Gray; ColorTypes.Gray + elseif palette == GDAL.GPI_RGB; ColorTypes.RGB + elseif palette == GDAL.GPI_HLS; ColorTypes.HSL + elseif palette == GDAL.GPI_CMYK + error(""" + CMYK not yet supported. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues + """) + else; error("Unknown color palette: $palette") + end + ImageCore.permuteddimsview(ImageCore.colorview(colortype, + ImageCore.normedview(read(dataset, indices[1])) + ), (2,1)) +end + +function imread( + colortype::Type{ColorTypes.Gray}, + dataset::AbstractDataset, + indices::NTuple{1, <:Integer} + ) + ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.Gray, + ImageCore.normedview(read(dataset, indices[1])) + ), (2,1)) +end + +function imread( + colortype::Type{ColorTypes.RGB}, + dataset::AbstractDataset, + indices::NTuple{3,<:Integer} + ) + ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGB, + ImageCore.normedview(read(dataset, indices[1])), + ImageCore.normedview(read(dataset, indices[2])), + ImageCore.normedview(read(dataset, indices[3])) + ), (2,1)) +end + +function imread( + colortype::Type{ColorTypes.RGBA}, + dataset::Dataset, + indices::NTuple{4,<:Integer} + ) + ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGBA, + ImageCore.normedview(read(dataset, indices[1])), + ImageCore.normedview(read(dataset, indices[2])), + ImageCore.normedview(read(dataset, indices[3])), + ImageCore.normedview(read(dataset, indices[4])) + ), (2,1)) +end + +function imread(dataset::AbstractDataset, indices::Vector{<:Integer}) + gci = GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices] + gciorder = sort(gci) + colortype = if gciorder == [GCI_GrayIndex] + ColorTypes.Gray + elseif gciorder == [GCI_PaletteIndex] + ColorTable + elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand] + ColorTypes.RGB + elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand] + ColorTypes.RGBA + elseif gciorder == [GCI_HueBand, GCI_SaturationBand, GCI_LightnessBand] + ColorTypes.HSL + elseif gciorder == [ + GCI_CyanBand, GCI_MagentaBand, GCI_YellowBand, GCI_BlackBand + ] + else + error(""" + Unknown GCI: $colororder. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues + """) + end + imread(colortype, dataset, Tuple(indices[sortperm(gci)])) +end + +imread(dataset::AbstractDataset) = imread(dataset, collect(1:nraster(dataset))) diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 944b28ba..6fbc7144 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -1,12 +1,12 @@ """ - rasterio!(dataset::AbstractDataset, buffer::Array{<:Real, 3}, + rasterio!(dataset::AbstractDataset, buffer::Array{<:Any, 3}, bands; ) - rasterio!(dataset::AbstractDataset, buffer::Array{<:Real, 3}, bands, rows, + rasterio!(dataset::AbstractDataset, buffer::Array{<:Any, 3}, bands, rows, cols; ) - rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Real}; + rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Any}; ) - rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Real}, rows, + rasterio!(rasterband::AbstractRasterBand, buffer::Matrix{<:Any}, rows, cols; ) @@ -15,7 +15,7 @@ Read/write a region of image data from multiple bands. This method allows reading a region of one or more `RasterBand`s from this dataset into a buffer, or writing data from a buffer into a region of the `RasterBand`s. It automatically takes care of data type translation if the -element type (`<:Real`) of the buffer is different than that of the +element type (`<:Any`) of the buffer is different than that of the `RasterBand`. The method also takes care of image decimation / replication if the buffer size (`xsz × ysz`) is different than the size of the region being accessed (`xsize × ysize`). @@ -73,7 +73,7 @@ function rasterio!( pxspace::Integer = 0, linespace::Integer = 0, bandspace::Integer = 0, - )::T where {T <: Array{<:Real, 3}} + )::T where {T <: Array{<:Any, 3}} rasterio!(dataset, buffer, bands, 0, 0, size(buffer, 1), size(buffer, 2), access, pxspace, linespace, bandspace) return buffer @@ -135,7 +135,7 @@ function rasterio!( access::GDALRWFlag = GF_Read, pxspace::Integer = 0, linespace::Integer = 0, - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} rasterio!(rasterband, buffer, 0, 0, width(rasterband), height(rasterband), access, pxspace, linespace) return buffer @@ -149,7 +149,7 @@ function rasterio!( access::GDALRWFlag = GF_Read, pxspace::Integer = 0, linespace::Integer = 0, - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} xsize = length(cols); xsize < 1 && error("invalid window width") ysize = length(rows); ysize < 1 && error("invalid window height") rasterio!(rasterband, buffer, cols[1] - 1, rows[1] - 1, xsize, ysize, @@ -187,7 +187,7 @@ end function read!( rb::AbstractRasterBand, buffer::T - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} rasterio!(rb, buffer, GF_Read) return buffer end @@ -199,7 +199,7 @@ function read!( yoffset::Integer, xsize::Integer, ysize::Integer - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize) return buffer end @@ -209,7 +209,7 @@ function read!( buffer::T, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} rasterio!(rb, buffer, rows, cols) return buffer end @@ -246,7 +246,7 @@ function write!( yoffset::Integer, xsize::Integer, ysize::Integer - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize, GF_Write) return buffer end @@ -256,7 +256,7 @@ function write!( buffer::T, rows::UnitRange{<:Integer} = 1:height(rb), cols::UnitRange{<:Integer} = 1:width(rb), - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} rasterio!(rb, buffer, rows, cols, GF_Write) return buffer end @@ -265,7 +265,7 @@ function read!( dataset::AbstractDataset, buffer::T, i::Integer - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} read!(getband(dataset, i), buffer) return buffer end @@ -274,7 +274,7 @@ function read!( dataset::AbstractDataset, buffer::T, indices - )::T where {T <: Array{<:Real, 3}} + )::T where {T <: Array{<:Any, 3}} rasterio!(dataset, buffer, indices, GF_Read) return buffer end @@ -282,7 +282,7 @@ end function read!( dataset::AbstractDataset, buffer::T - )::T where {T <: Array{<:Real, 3}} + )::T where {T <: Array{<:Any, 3}} nband = nraster(dataset) @assert size(buffer, 3) == nband rasterio!(dataset, buffer, collect(Cint, 1:nband), GF_Read) @@ -297,7 +297,7 @@ function read!( yoffset::Integer, xsize::Integer, ysize::Integer - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} read!(getband(dataset, i), buffer, xoffset, yoffset, xsize, ysize) return buffer end @@ -310,7 +310,7 @@ function read!( yoffset::Integer, xsize::Integer, ysize::Integer - )::T where {T <: Array{<:Real, 3}} + )::T where {T <: Array{<:Any, 3}} rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize) return buffer end @@ -321,7 +321,7 @@ function read!( i::Integer, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - )::T where {T <: Matrix{<:Real}} + )::T where {T <: Matrix{<:Any}} read!(getband(dataset, i), buffer, rows, cols) return buffer end @@ -332,7 +332,7 @@ function read!( indices, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer} - )::T where {T <: Array{<:Real, 3}} + )::T where {T <: Array{<:Any, 3}} rasterio!(dataset, buffer, indices, rows, cols) return buffer end @@ -408,7 +408,7 @@ end function write!( dataset::T, - buffer::Matrix{<:Real}, + buffer::Matrix{<:Any}, i::Integer, xoffset::Integer, yoffset::Integer, @@ -421,7 +421,7 @@ end function write!( dataset::T, - buffer::Array{<:Real, 3}, + buffer::Array{<:Any, 3}, indices, xoffset::Integer, yoffset::Integer, @@ -435,7 +435,7 @@ end function write!( dataset::T, - buffer::Matrix{<:Real}, + buffer::Matrix{<:Any}, i::Integer, rows::UnitRange{<:Integer} = 1:height(getband(dataset, i)), cols::UnitRange{<:Integer} = 1:width(getband(dataset, i)), @@ -446,7 +446,7 @@ end function write!( dataset::T, - buffer::Array{<:Real, 3}, + buffer::Array{<:Any, 3}, indices, rows::UnitRange{<:Integer} = 1:height(dataset), cols::UnitRange{<:Integer} = 1:width(dataset), diff --git a/src/types.jl b/src/types.jl index 2413d6b0..b517ce5c 100644 --- a/src/types.jl +++ b/src/types.jl @@ -147,20 +147,17 @@ mutable struct IFeatureDefnView <: AbstractFeatureDefn end end -mutable struct RasterBand{T} <: AbstractRasterBand{T} - ptr::GDAL.GDALRasterBandH -end - "Fetch the pixel data type for this band." pixeltype(ptr::GDAL.GDALRasterBandH)::DataType = convert(GDALDataType, GDAL.gdalgetrasterdatatype(ptr)) -function RasterBand( - ptr::GDAL.GDALRasterBandH - )::RasterBand{pixeltype(ptr)} - return RasterBand{pixeltype(ptr)}(ptr) +mutable struct RasterBand{T} <: AbstractRasterBand{T} + ptr::GDAL.GDALRasterBandH end +RasterBand(ptr::GDAL.GDALRasterBandH)::RasterBand{pixeltype(ptr)} = + RasterBand{pixeltype(ptr)}(ptr) + mutable struct IRasterBand{T} <: AbstractRasterBand{T} ptr::GDAL.GDALRasterBandH ownedby::AbstractDataset @@ -168,7 +165,7 @@ mutable struct IRasterBand{T} <: AbstractRasterBand{T} function IRasterBand{T}( ptr::GDAL.GDALRasterBandH = C_NULL; ownedby::AbstractDataset = Dataset() - ) where T + )::IRasterBand{T} where T rasterband = new(ptr, ownedby) finalizer(destroy, rasterband) return rasterband @@ -234,6 +231,12 @@ eval(@convert(GDALDataType::GDAL.GDALDataType, GDT_TypeCount::GDAL.GDT_TypeCount, )) +eval(@convert(GDALDataType::ImageCore.Normed, + GDT_Byte::ImageCore.N0f8, + GDT_UInt16::ImageCore.N0f16, + GDT_UInt32::ImageCore.N0f32, +)) + eval(@convert(GDALDataType::DataType, GDT_Unknown::Any, GDT_Byte::UInt8, From d3c3ad2e97859ea5db9a2c25783adb4bc94bd1c3 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 30 Apr 2021 22:08:10 -0700 Subject: [PATCH 062/169] Add the return keyword --- src/raster/images.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index a7a1f42e..8bd3cb97 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -16,7 +16,7 @@ function imread( """) else; error("Unknown color palette: $palette") end - ImageCore.permuteddimsview(ImageCore.colorview(colortype, + return ImageCore.permuteddimsview(ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, indices[1])) ), (2,1)) end @@ -26,7 +26,7 @@ function imread( dataset::AbstractDataset, indices::NTuple{1, <:Integer} ) - ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.Gray, + return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.Gray, ImageCore.normedview(read(dataset, indices[1])) ), (2,1)) end @@ -36,7 +36,7 @@ function imread( dataset::AbstractDataset, indices::NTuple{3,<:Integer} ) - ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGB, + return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGB, ImageCore.normedview(read(dataset, indices[1])), ImageCore.normedview(read(dataset, indices[2])), ImageCore.normedview(read(dataset, indices[3])) @@ -48,7 +48,7 @@ function imread( dataset::Dataset, indices::NTuple{4,<:Integer} ) - ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGBA, + return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGBA, ImageCore.normedview(read(dataset, indices[1])), ImageCore.normedview(read(dataset, indices[2])), ImageCore.normedview(read(dataset, indices[3])), @@ -78,7 +78,7 @@ function imread(dataset::AbstractDataset, indices::Vector{<:Integer}) https://github.com/yeesian/ArchGDAL.jl/issues """) end - imread(colortype, dataset, Tuple(indices[sortperm(gci)])) + return imread(colortype, dataset, Tuple(indices[sortperm(gci)])) end imread(dataset::AbstractDataset) = imread(dataset, collect(1:nraster(dataset))) From 1f7405740ce4d8c2ae7a3792943c58e225519b81 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 08:09:55 -0700 Subject: [PATCH 063/169] Add support for YCbCr --- src/constants.jl | 34 +++++++++++++++++----------------- src/raster/images.jl | 22 +++++++++++++++++++--- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index e73b196a..80fdb622 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -96,23 +96,23 @@ const StringList = Ptr{Cstring} @enum(GDALColorInterp, GCI_Undefined = 0, - GCI_GrayIndex = 1, - GCI_PaletteIndex = 2, - GCI_RedBand = 3, - GCI_GreenBand = 4, - GCI_BlueBand = 5, - GCI_AlphaBand = 6, - GCI_HueBand = 7, - GCI_SaturationBand = 8, - GCI_LightnessBand = 9, - GCI_CyanBand = 10, - GCI_MagentaBand = 11, - GCI_YellowBand = 12, - GCI_BlackBand = 13, - GCI_YCbCr_YBand = 14, - GCI_YCbCr_CbBand = 15, - GCI_YCbCr_CrBand = 16, - GCI_Max = 17, # 16 + GCI_GrayIndex = 1, # GreyScale + GCI_PaletteIndex = 2, # Paletted (see associated color table) + GCI_RedBand = 3, # Red band of RGBA image + GCI_GreenBand = 4, # Green band of RGBA image + GCI_BlueBand = 5, # Green band of RGBA image + GCI_AlphaBand = 6, # Alpha (0=transparent, 255=opaque) + GCI_HueBand = 7, # Hue band of HLS image + GCI_SaturationBand = 8, # Saturation band of HLS image + GCI_LightnessBand = 9, # Lightness band of HLS image + GCI_CyanBand = 10, # Cyan band of CMYK image + GCI_MagentaBand = 11, # Magenta band of CMYK image + GCI_YellowBand = 12, # Yellow band of CMYK image + GCI_BlackBand = 13, # Black band of CMYK image + GCI_YCbCr_YBand = 14, # Y Luminance + GCI_YCbCr_CbBand = 15, # Cb Chroma + GCI_YCbCr_CrBand = 16, # Cr Chroma + GCI_Max = 17, # Max current value = 16 ) @enum(GDALAsyncStatusType, diff --git a/src/raster/images.jl b/src/raster/images.jl index 8bd3cb97..04c4abde 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -56,6 +56,19 @@ function imread( ), (2,1)) end +function imread( + colortype::Type{ColorTypes.YCbCr}, + dataset::Dataset, + indices::NTuple{4,<:Integer} + ) + return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.YCbCr, + ImageCore.normedview(read(dataset, indices[1])), + ImageCore.normedview(read(dataset, indices[2])), + ImageCore.normedview(read(dataset, indices[3])), + ImageCore.normedview(read(dataset, indices[4])) + ), (2,1)) +end + function imread(dataset::AbstractDataset, indices::Vector{<:Integer}) gci = GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices] gciorder = sort(gci) @@ -69,9 +82,12 @@ function imread(dataset::AbstractDataset, indices::Vector{<:Integer}) ColorTypes.RGBA elseif gciorder == [GCI_HueBand, GCI_SaturationBand, GCI_LightnessBand] ColorTypes.HSL - elseif gciorder == [ - GCI_CyanBand, GCI_MagentaBand, GCI_YellowBand, GCI_BlackBand - ] + # elseif gciorder == [ + # GCI_CyanBand, GCI_MagentaBand, GCI_YellowBand, GCI_BlackBand + # ] + # ColorTypes.CMYK + elseif gciorder == [GCI_YCbCr_YBand, GCI_YCbCr_CbBand, GCI_YCbCr_CrBand] + ColorTypes.YCbCr else error(""" Unknown GCI: $colororder. Please file an issue at From 979bc6092187f9d092ebb5818b168a625578a023 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 08:34:33 -0700 Subject: [PATCH 064/169] [Breaking] Delete unneeded ColorTable methods The single most useful thing from the colortable is the palette interpretation. Rather than encouraging operations on colortables (with very limited functionality from GDAL), users are better served by arrays of ColorTypes using Colors.jl, e.g. (http://juliagraphics.github.io/Colors.jl/stable/colormapsandcolorscales/#Generating-a-range-of-colors) ``` range(c1, stop=c2, length=15)` ``` instead of ``` createcolorramp!(colortable, startindex, startcolor, endindex, endcolor) ``` --- src/base/display.jl | 3 +- src/raster/colortable.jl | 97 ------------------------------------ test/test_rasterattrtable.jl | 39 +-------------- test/test_rasterband.jl | 22 -------- 4 files changed, 2 insertions(+), 159 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index 84b65fad..dd89313f 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -277,8 +277,7 @@ function Base.show(io::IO, ct::ColorTable)::IO return io end palette = paletteinterp(ct) - nentries = ncolorentry(ct) - print(io, "ColorTable[$palette] with $nentries entries") + print(io, "ColorTable[$palette]") return io end diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index 82987c80..7b6bb0f3 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -36,100 +36,3 @@ palette interpretation enumeration value, usually `GPI_RGB`. """ paletteinterp(ct::ColorTable)::GDALPaletteInterp = GDAL.gdalgetpaletteinterpretation(ct.ptr) - -""" - ncolorentry(ct::ColorTable) - -Get number of color entries in table. -""" -ncolorentry(ct::ColorTable)::Integer = GDAL.gdalgetcolorentrycount(ct.ptr) - -""" - getcolorentry(ct::ColorTable, i::Integer) - -Fetch a color entry from table. -""" -getcolorentry(ct::ColorTable, i::Integer)::GDAL.GDALColorEntry = - unsafe_load(GDAL.gdalgetcolorentry(ct.ptr, i)) - -""" - getcolorentryasrgb(ct::ColorTable, i::Integer) - -Fetch a table entry in RGB format. - -In theory this method should support translation of color palettes in non-RGB -color spaces into RGB on the fly, but currently it only works on RGB color -tables. - -### Parameters -* `i` entry offset from zero to GetColorEntryCount()-1. - -### Returns -The color entry in RGB format. -""" -function getcolorentryasrgb(ct::ColorTable, i::Integer)::GDAL.GDALColorEntry - colorentry = Ref{GDAL.GDALColorEntry}(GDAL.GDALColorEntry(0, 0, 0, 0)) - result = Bool(GDAL.gdalgetcolorentryasrgb(ct.ptr, i, colorentry)) - result || @warn("The conversion to RGB isn't supported.") - return colorentry[] -end - -""" - setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry) - -Set entry in color table. - -Note that the passed in color entry is copied, and no internal reference to it -is maintained. Also, the passed in entry must match the color interpretation of -the table to which it is being assigned. - -The table is grown as needed to hold the supplied offset. - -### Parameters -* `i` entry offset from `0` to `ncolorentry()-1`. -* `entry` value to assign to table. -""" -function setcolorentry!( - ct::ColorTable, - i::Integer, - entry::GDAL.GDALColorEntry - )::ColorTable - GDAL.gdalsetcolorentry(ct.ptr, i, Ref{GDAL.GDALColorEntry}(entry)) - return ct -end - -""" - createcolorramp!(ct::ColorTable, startindex, - startcolor::GDAL.GDALColorEntry, endindex, - endcolor::GDAL.GDALColorEntry) - -Create color ramp. - -Automatically creates a color ramp from one color entry to another. It can be -called several times to create multiples ramps in the same color table. - -### Parameters -* `startindex` index to start the ramp on the color table [0..255] -* `startcolor` a color entry value to start the ramp -* `endindex` index to end the ramp on the color table [0..255] -* `endcolor` a color entry value to end the ramp - -### Returns -The color table with the created color ramp. -""" -function createcolorramp!( - ct::ColorTable, - startindex::Integer, - startcolor::GDAL.GDALColorEntry, - endindex::Integer, - endcolor::GDAL.GDALColorEntry - )::ColorTable - GDAL.gdalcreatecolorramp( - ct.ptr, - startindex, - Ref{GDAL.GDALColorEntry}(startcolor), - endindex, - Ref{GDAL.GDALColorEntry}(endcolor) - ) - return ct -end diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index 10a10316..03d24c1d 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -88,45 +88,8 @@ end @testset ("Testing Color Tables") begin AG.createcolortable(AG.GPI_RGB) do ct - @test sprint(print, ct) == "ColorTable[GPI_RGB] with 0 entries" + @test sprint(print, ct) == "ColorTable[GPI_RGB]" @test AG.paletteinterp(ct) == AG.GPI_RGB - @test AG.ncolorentry(ct) == 0 - AG.createcolorramp!(ct, 128, GDAL.GDALColorEntry(0,0,0,0), - 255, GDAL.GDALColorEntry(0,0,255,0)) - @test AG.ncolorentry(ct) == 256 - @test sprint(print, ct) == "ColorTable[GPI_RGB] with 256 entries" - @test sprint(print, AG.getcolorentry(ct, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentry(ct, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentry(ct, 200)) == "GDAL.GDALColorEntry(0, 0, 144, 0)" - @test sprint(print, AG.getcolorentry(ct, 255)) == "GDAL.GDALColorEntry(0, 0, 255, 0)" - - @test sprint(print, AG.getcolorentryasrgb(ct, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentryasrgb(ct, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentryasrgb(ct, 200)) == "GDAL.GDALColorEntry(0, 0, 144, 0)" - @test sprint(print, AG.getcolorentryasrgb(ct, 255)) == "GDAL.GDALColorEntry(0, 0, 255, 0)" - - AG.setcolorentry!(ct, 255, GDAL.GDALColorEntry(0,0,100,0)) - @test sprint(print, AG.getcolorentry(ct, 255)) == "GDAL.GDALColorEntry(0, 0, 100, 0)" - - AG.clone(ct) do ctclone - @test AG.paletteinterp(ctclone) == AG.GPI_RGB - @test AG.ncolorentry(ctclone) == 256 - @test sprint(print, AG.getcolorentry(ctclone, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentry(ctclone, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentry(ctclone, 200)) == "GDAL.GDALColorEntry(0, 0, 144, 0)" - @test sprint(print, AG.getcolorentry(ctclone, 255)) == "GDAL.GDALColorEntry(0, 0, 100, 0)" - - AG.createRAT(ctclone) do rat - ct2 = AG.toColorTable(rat) - @test AG.paletteinterp(ct2) == AG.GPI_RGB - @test AG.ncolorentry(ct2) == 256 - @test sprint(print, AG.getcolorentry(ct2, 0)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentry(ct2, 128)) == "GDAL.GDALColorEntry(0, 0, 0, 0)" - @test sprint(print, AG.getcolorentry(ct2, 200)) == "GDAL.GDALColorEntry(0, 0, 144, 0)" - @test sprint(print, AG.getcolorentry(ct2, 255)) == "GDAL.GDALColorEntry(0, 0, 100, 0)" - end - end - AG.clone(AG.ColorTable(C_NULL)) do ct @test sprint(print, ct) == "NULL ColorTable" end diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 73c47056..11e16b6a 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -121,30 +121,8 @@ import ArchGDAL; const AG = ArchGDAL AG.getoverview(destband, 2) ]) end - - AG.createcolortable(AG.GPI_RGB) do ct - AG.createcolorramp!(ct, - 128, GDAL.GDALColorEntry(0,0,0,0), - 255, GDAL.GDALColorEntry(0,0,255,0) - ) - AG.setcolortable!(destband, ct) - @test AG.ncolorentry(ct) == 256 - AG.getcolortable(destband) do ct2 - @test AG.ncolorentry(ct) == AG.ncolorentry(ct2) - end - AG.clearcolortable!(destband) - - AG.createRAT(ct) do rat - AG.setdefaultRAT!(destband, rat) - @test AG.getdefaultRAT(destband) != C_NULL - end - end end end end -# untested -# setcategorynames!(rasterband, names) -# getcolortable(band) do C_NULL - end From eca12eb8ae7119cdd8e0055081ec5e77a4c31db3 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 08:53:11 -0700 Subject: [PATCH 065/169] Add tests for uncovered methods of features Namely, * getgeom(feature) * getgeom(feature, i) * unsafe_getgeom(feature) * unsafe_getgeom(feature, i) * getstyletable(feature) --- test/test_feature.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_feature.jl b/test/test_feature.jl index 487f16cb..6c2ca4c6 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -66,7 +66,9 @@ AG.read("data/point.geojson") do dataset @test AG.getstylestring(f) == "NewName" AG.createstyletable() do st + AG.addstyle!(st, "name", "style") AG.setstyletable!(f, st) + @test AG.findstylestring(AG.getstyletable(f), "name") == "style" end AG.setnativedata!(f, "nativedata1") @@ -133,6 +135,14 @@ end AG.setfield!(feature, 5, ["1", "2.0"]) AG.setfield!(feature, 6, UInt8[1,2,3,4]) AG.setfield!(feature, 7, Dates.DateTime(2016,9,25,21,17,0)) + @test sprint(print, AG.getgeom(feature)) == "NULL Geometry" + AG.getgeom(feature) do geom + @test sprint(print, geom) == "NULL Geometry" + end + @test sprint(print, AG.getgeom(feature, 0)) == "NULL Geometry" + AG.getgeom(feature, 0) do geom + @test sprint(print, geom) == "NULL Geometry" + end AG.addfeature(layer) do newfeature AG.setfrom!(newfeature, feature) From 3d0019735d44661a04ba6c6986cba56cf7206bf6 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 09:48:10 -0700 Subject: [PATCH 066/169] Add support for options in toJSON --- src/ogr/geometry.jl | 22 +++++++++++++--------- test/test_geometry.jl | 2 ++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index c9f13f5b..d4a5eadc 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -374,25 +374,29 @@ toKML(geom::AbstractGeometry, altitudemode = C_NULL)::String = # ↑ * `altitudemode`: value to write in altitudeMode element, or NULL. """ - toJSON(geom::AbstractGeometry) + toJSON(geom::AbstractGeometry; kwargs...) Convert a geometry into GeoJSON format. -""" -toJSON(geom::AbstractGeometry)::String = GDAL.ogr_g_exporttojson(geom.ptr) -""" - toJSON(geom::AbstractGeometry, options) - -Convert a geometry into GeoJSON format. + * The following options are supported : + * `COORDINATE_PRECISION=number`: maximum number of figures after decimal + separator to write in coordinates. + * `SIGNIFICANT_FIGURES=number`: maximum number of significant figures. + * + * If COORDINATE_PRECISION is defined, SIGNIFICANT_FIGURES will be ignored if + * specified. + * When none are defined, the default is COORDINATE_PRECISION=15. ### Parameters * `geom`: handle to the geometry. -* `options`: a list of options. ### Returns A GeoJSON fragment or NULL in case of error. """ -toJSON(geom::AbstractGeometry, options)::String = +toJSON(geom::AbstractGeometry; kwargs...)::String = + GDAL.ogr_g_exporttojsonex(geom.ptr, String["$k=$v" for (k,v) in kwargs]) + +toJSON(geom::AbstractGeometry, options::Vector{String})::String = GDAL.ogr_g_exporttojsonex(geom.ptr, options) """ diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 33c5af30..1865d5f8 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -41,6 +41,8 @@ end @test AG.toKML(point, "clampToGround") == "clampToGround100,70,0" @test AG.toKML(point) == "100,70,0" @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" + @test AG.toJSON(point, SIGNIFICANT_FIGURES=1) == "{ \"type\": \"Point\", \"coordinates\": [ 1e+02, 7e+01, 0.0 ] }" + @test AG.toJSON(point, ["SIGNIFICANT_FIGURES=1"]) == "{ \"type\": \"Point\", \"coordinates\": [ 1e+02, 7e+01, 0.0 ] }" AG.createpoint(100,70,0) do point2 @test isapprox(GeoInterface.coordinates(point2), [100,70,0], atol=1e-6) @test AG.equals(point, point2) == true From c3f7d55596380a586c3d6a93f759b76bec0e3e23 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 09:59:58 -0700 Subject: [PATCH 067/169] Increase test coverage for NULL geometries --- test/test_geometry.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 1865d5f8..3471d057 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -273,6 +273,7 @@ end @test AG.getgeomtype(AG.getgeom(geom3, 1)) == AG.wkbPolygon25D @test AG.getgeomtype(AG.getgeom(geom3, 2)) == AG.wkbPolygon25D @test sprint(print, AG.getgeom(geom3, 3)) == "NULL Geometry" + @test sprint(print, AG.getgeom(AG.IGeometry(), 3)) == "NULL Geometry" AG.getgeom(geom3, 0) do geom4 @test AG.getgeomtype(geom4) == AG.wkbPoint25D end @@ -285,9 +286,19 @@ end AG.getgeom(geom3, 3) do geom4 @test sprint(print, geom4) == "NULL Geometry" end + AG.getgeom(AG.IGeometry(), 0) do geom + @test sprint(print, geom) == "NULL Geometry" + end end @testset "Spatial Reference Systems" begin + AG.createpoint(100,70,0) do geom + @test sprint(print, AG.getspatialref(geom)) == "NULL Spatial Reference System" + AG.getspatialref(geom) do spatialref + @test sprint(print, spatialref) == "NULL Spatial Reference System" + end + end + AG.read("data/point.geojson") do dataset layer = AG.getlayer(dataset, 0) AG.nextfeature(layer) do feature From b75d0d46d93f9b4c42c4ad3a8d45f1f7a9708018 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 10:19:38 -0700 Subject: [PATCH 068/169] Add support for kwargs in lineargeom --- src/ogr/geometry.jl | 31 +++++++++++++++++++++++++------ test/test_geometry.jl | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index d4a5eadc..5b755707 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -1287,15 +1287,34 @@ MULTICURVE or MULTISURFACE in it, by approximating curve geometries. * `options`: options as a null-terminated list of strings or NULL. See OGRGeometryFactory::curveToLineString() for valid options. """ -lineargeom(geom::AbstractGeometry, stepsize::Real = 0)::IGeometry = - IGeometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, C_NULL)) -unsafe_lineargeom(geom::AbstractGeometry, stepsize::Real = 0)::Geometry = - Geometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, C_NULL)) +function lineargeom( + geom::AbstractGeometry, + stepsize::Real = 0; + kwargs... + )::IGeometry + return lineargeom( + geom, + String["$k=$v" for (k, v) in kwargs], + stepsize + ) +end + +function unsafe_lineargeom( + geom::AbstractGeometry, + stepsize::Real = 0; + kwargs... + )::Geometry + return unsafe_lineargeom( + geom, + String["$k=$v" for (k, v) in kwargs], + stepsize + ) +end function lineargeom( geom::AbstractGeometry, - options::Vector, + options::Vector{String}, stepsize::Real = 0 )::IGeometry return IGeometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) @@ -1303,7 +1322,7 @@ end function unsafe_lineargeom( geom::AbstractGeometry, - options::Vector, + options::Vector{String}, stepsize::Real = 0 )::Geometry return Geometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 3471d057..d07a5214 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -198,6 +198,32 @@ end end end end + + @test startswith(AG.toWKT(AG.curvegeom(AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT="NO"))), "CURVEPOLYGON (CIRCULARSTRING (") + AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT="NO") do lgeom + AG.curvegeom(lgeom) do clgeom + @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") + end + @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom + AG.polygonize(mlsgeom) do plgeom + @test AG.ngeom(plgeom) == 2 + end + end + end + + @test startswith(AG.toWKT(AG.curvegeom(AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5))), "CURVEPOLYGON (CIRCULARSTRING (") + AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5) do lgeom + AG.curvegeom(lgeom) do clgeom + @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") + end + @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom + AG.polygonize(mlsgeom) do plgeom + @test AG.ngeom(plgeom) == 2 + end + end + end end end From 7871cffc15f27974581a2746a3fc0ee0847bd66e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 10:20:48 -0700 Subject: [PATCH 069/169] [Breaking] Remove initialize!(stylemanager, feature) Use initialize!(stylemanager, getstylestring(feature)) instead. --- src/ogr/styletable.jl | 21 ++++----------------- test/test_styletable.jl | 1 - 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index 7bbd7f04..bda4582f 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -27,22 +27,6 @@ function destroy(sm::StyleManager)::Nothing return nothing end - -""" - initialize!(stylemanager::StyleManager, feature::Feature) - -Initialize style manager from the style string of a feature. - -### Parameters -* `stylemanager`: handle to the style manager. -* `feature`: handle to the new feature from which to read the style. - -### Returns -the style string read from the feature, or NULL in case of error. -""" -initialize!(stylemanager::StyleManager, feature::Feature)::String = - GDAL.ogr_sm_initfromfeature(stylemanager.ptr, feature.ptr) - """ initialize!(stylemanager::StyleManager, stylestring = C_NULL) @@ -54,9 +38,12 @@ Initialize style manager from the style string. ### Returns `true` on success, `false` on error. """ -initialize!(stylemanager::StyleManager, stylestring = C_NULL)::Bool = +initialize!(stylemanager::StyleManager, stylestring::String)::Bool = Bool(GDAL.ogr_sm_initstylestring(stylemanager.ptr, stylestring)) +initialize!(stylemanager::StyleManager)::Bool = + Bool(GDAL.ogr_sm_initstylestring(stylemanager.ptr, C_NULL)) + """ npart(stylemanager::StyleManager) npart(stylemanager::StyleManager, stylestring::AbstractString) diff --git a/test/test_styletable.jl b/test/test_styletable.jl index dcde8813..f6d2aeab 100644 --- a/test/test_styletable.jl +++ b/test/test_styletable.jl @@ -69,5 +69,4 @@ import ArchGDAL; const AG = ArchGDAL end end -# Untested: initialize!(stylemanager::StyleManager, feature::Feature) end From 21e4772f48ea298304f197f01708c52e1adda1a8 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 11:05:37 -0700 Subject: [PATCH 070/169] Use summarize(io, rasterband) for NULL bands --- src/base/display.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index dd89313f..867c38cb 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -14,7 +14,7 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO end println(io, "GDAL Dataset ($(getdriver(dataset)))") println(io, "File(s): ") - for (i,filename) in enumerate(filelist(dataset)) + for (i, filename) in enumerate(filelist(dataset)) println(io, " $filename") if i > 5 println(io, " ...") @@ -83,11 +83,10 @@ function Base.show( ::MIME"text/plain", rasterband::AbstractRasterBand )::IO + summarize(io, rasterband) if rasterband.ptr == C_NULL - print(io, "NULL RasterBand") return io end - summarize(io, rasterband) (x,y) = blocksize(rasterband) sc = getscale(rasterband) ofs = getoffset(rasterband) From 513a98ed750eeda4377f37f13a49b209cc3160e7 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 11:16:32 -0700 Subject: [PATCH 071/169] remove obsolete comment --- test/test_feature.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_feature.jl b/test/test_feature.jl index 6c2ca4c6..8872661b 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -185,7 +185,4 @@ end end end -# untested -# getstyletable - end From 2dbd579f0451d1d4eb37d312ea4698889b258540 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 11:27:49 -0700 Subject: [PATCH 072/169] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d36a719e..7b6b060d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [GDAL](http://gdal.org/) is a translator library for raster and vector geospatial data formats that is released under an [X/MIT](https://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse) license by the [Open Source Geospatial Foundation](http://www.osgeo.org/). As a library, it presents an abstract data model to drivers for various [raster](http://www.gdal.org/formats_list.html) and [vector](http://www.gdal.org/ogr_formats.html) formats. -This package aims to be a complete solution for working with GDAL in Julia, similar in scope to [the SWIG bindings for Python](https://pypi.python.org/pypi/GDAL/). It builds on top of [GDAL.jl](https://github.com/JuliaGeo/GDAL.jl), and provides a high level API for GDAL, espousing the following principles. +This package aims to be a complete solution for working with GDAL in Julia, similar in scope to [the SWIG bindings for Python](https://pypi.python.org/pypi/GDAL/) and the user-friendliness of [Fiona](https://github.com/Toblerity/Fiona) and [Rasterio](https://github.com/mapbox/rasterio). It builds on top of [GDAL.jl](https://github.com/JuliaGeo/GDAL.jl), and provides a high level API for GDAL, espousing the following principles. ## Principles (The Arch Way) (adapted from: https://wiki.archlinux.org/index.php/Arch_Linux#Principles) From 2aee418d9803171e636de7e7a9b2a7756c7c8660 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 11:54:13 -0700 Subject: [PATCH 073/169] Add tests for raster attribute tables and color tables --- src/raster/rasterband.jl | 8 +++++--- test/test_rasterband.jl | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 6d394203..393d4787 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -233,10 +233,12 @@ maximum(band::AbstractRasterBand)::Real = """ getdefaultRAT(band::AbstractRasterBand) -Fetch default Raster Attribute Table. +A RAT will be returned if there is a default one associated with the band, +otherwise NULL is returned. The returned RAT is owned by the band and should not +be deleted by the application. """ -getdefaultRAT(band::AbstractRasterBand)::GDAL.GDALRasterAttributeTableH = - GDAL.gdalgetdefaultrat(band.ptr) +getdefaultRAT(band::AbstractRasterBand)::RasterAttrTable = + RasterAttrTable(GDAL.gdalgetdefaultrat(band.ptr)) """ setdefaultRAT!(band::AbstractRasterBand, rat::RasterAttrTable) diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 11e16b6a..c34fc044 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -121,6 +121,24 @@ import ArchGDAL; const AG = ArchGDAL AG.getoverview(destband, 2) ]) end + + AG.createRAT() do rat + AG.setdefaultRAT!(destband, rat) + @test AG.getdefaultRAT(destband).ptr != rat.ptr + end + @test AG.getdefaultRAT(destband).ptr != GDAL.GDALRasterAttributeTableH(C_NULL) + + AG.getcolortable(destband) do ct + @test ct.ptr == GDAL.GDALColorTableH(C_NULL) + end + AG.createcolortable(AG.GPI_RGB) do ct + @test ct.ptr != GDAL.GDALColorTableH(C_NULL) + AG.setcolortable!(destband, ct) + end + AG.clearcolortable!(destband) + AG.getcolortable(destband) do ct + @test ct.ptr == GDAL.GDALColorTableH(C_NULL) + end end end end From 83e1024de82becf8382fe4ae2478c4fc528e4d94 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 12:00:13 -0700 Subject: [PATCH 074/169] Add tests for ColorTable <-> RAT --- test/test_rasterattrtable.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index 03d24c1d..b3d9c465 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -93,6 +93,9 @@ end AG.clone(AG.ColorTable(C_NULL)) do ct @test sprint(print, ct) == "NULL ColorTable" end + AG.createRAT(ct) do rat + @test sprint(print, AG.toColorTable(rat, 0)) == "ColorTable[GPI_RGB]" + end end end From c5ef729ecfa9879f9508b290972fb65afdaead06 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 12:03:09 -0700 Subject: [PATCH 075/169] Add test for cloning raster attribute tables --- test/test_rasterattrtable.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index b3d9c465..7de2fd27 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -90,8 +90,11 @@ end AG.createcolortable(AG.GPI_RGB) do ct @test sprint(print, ct) == "ColorTable[GPI_RGB]" @test AG.paletteinterp(ct) == AG.GPI_RGB - AG.clone(AG.ColorTable(C_NULL)) do ct - @test sprint(print, ct) == "NULL ColorTable" + AG.clone(ct) do ct1 + @test sprint(print, ct1) == "ColorTable[GPI_RGB]" + end + AG.clone(AG.ColorTable(C_NULL)) do ct2 + @test sprint(print, ct2) == "NULL ColorTable" end AG.createRAT(ct) do rat @test sprint(print, AG.toColorTable(rat, 0)) == "ColorTable[GPI_RGB]" From 5da6c4ba2905884be949fcac1332b76693951ae8 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 12:12:41 -0700 Subject: [PATCH 076/169] Fix flakey test Caught in CI for windows-latest - x64: ``` Create a Point: Test Failed at D:\a\ArchGDAL.jl\ArchGDAL.jl\test\test_geometry.jl:45 Expression: AG.toJSON(point, ["SIGNIFICANT_FIGURES=1"]) == "{ \"type\": \"Point\", \"coordinates\": [ 1e+02, 7e+01, 0.0 ] }" Evaluated: "{ \"type\": \"Point\", \"coordinates\": [ 1e+002, 7e+001, 0.0 ] }" == "{ \"type\": \"Point\", \"coordinates\": [ 1e+02, 7e+01, 0.0 ] }" ``` --- test/test_geometry.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index d07a5214..22b1a0da 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -41,8 +41,8 @@ end @test AG.toKML(point, "clampToGround") == "clampToGround100,70,0" @test AG.toKML(point) == "100,70,0" @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" - @test AG.toJSON(point, SIGNIFICANT_FIGURES=1) == "{ \"type\": \"Point\", \"coordinates\": [ 1e+02, 7e+01, 0.0 ] }" - @test AG.toJSON(point, ["SIGNIFICANT_FIGURES=1"]) == "{ \"type\": \"Point\", \"coordinates\": [ 1e+02, 7e+01, 0.0 ] }" + @test startswith(AG.toJSON(point, SIGNIFICANT_FIGURES=1), "{ \"type\": \"Point\", \"coordinates\": [") + @test startswith(AG.toJSON(point, ["SIGNIFICANT_FIGURES=1"]), "{ \"type\": \"Point\", \"coordinates\": [") AG.createpoint(100,70,0) do point2 @test isapprox(GeoInterface.coordinates(point2), [100,70,0], atol=1e-6) @test AG.equals(point, point2) == true From 72ea24cf1f02c278b2174ceb530a720df2411b15 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 12:38:14 -0700 Subject: [PATCH 077/169] Add tests for conversion errors --- test/test_types.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_types.jl b/test/test_types.jl index 2dc15b27..80113151 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -1,5 +1,6 @@ using Test import ArchGDAL; const AG = ArchGDAL +import ImageCore @testset "test_types.jl" begin @@ -17,6 +18,10 @@ import ArchGDAL; const AG = ArchGDAL @test AG.typeunion(AG.GDT_UInt16, AG.GDT_Byte) == AG.GDT_UInt16 @test AG.iscomplex(AG.GDT_Float32) == false + + @test Base.convert(AG.GDALDataType, UInt8) == AG.GDT_Byte + @test_throws ErrorException Base.convert(AG.GDALDataType, Int64) + @test_throws MethodError Base.convert(ImageCore.Normed, AG.GDT_Float32) end @testset "GDAL Colors and Palettes" begin From a1339ec366a79c3d8659b5d1fe4d80855eee38f9 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 12:41:49 -0700 Subject: [PATCH 078/169] Add test to exercise `macro ogrerr(code, message)` --- test/test_dataset.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_dataset.jl b/test/test_dataset.jl index 8f5b57d9..40ece11b 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -68,6 +68,7 @@ end AG.copy(layer3b, dataset = dataset2) @test AG.nlayer(dataset2) == 2 + @test_throws ErrorException AG.deletelayer!(dataset2, -1) AG.deletelayer!(dataset2, 1) @test AG.nlayer(dataset2) == 1 From 0b477e11d57d7627d4aeb824d98d51e54cda2fb2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 12:48:41 -0700 Subject: [PATCH 079/169] Add test to exercise `macro cplerr(code, message)` --- test/test_dataset.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/test_dataset.jl b/test/test_dataset.jl index 40ece11b..0eb2c0e5 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -45,6 +45,8 @@ end AG.getlayer(dataset1, 0) do layer1 @test AG.nfeature(layer1) == 4 end + # the following test is to cover an example of `macro cplerr(code, message)` + @test_throws ErrorException AG.getgeotransform(dataset1) dataset2 = AG.create(AG.getdriver("Memory")) @test AG.nlayer(dataset2) == 0 @@ -68,10 +70,12 @@ end AG.copy(layer3b, dataset = dataset2) @test AG.nlayer(dataset2) == 2 - @test_throws ErrorException AG.deletelayer!(dataset2, -1) AG.deletelayer!(dataset2, 1) @test AG.nlayer(dataset2) == 1 + # the following test is to cover an example of `macro ogrerr(code, message)` + @test_throws ErrorException AG.deletelayer!(dataset2, -1) + dataset4 = AG.create(tempname(), driver = AG.getdriver("KML")) @test AG.nlayer(dataset4) == 0 layer4 = AG.createlayer( From e8e990cfe919660de58cce727795f5ea6ff9c63a Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 13:06:24 -0700 Subject: [PATCH 080/169] Add tests for imread --- src/raster/images.jl | 6 ++++++ test/runtests.jl | 1 + test/test_images.jl | 11 +++++++++++ 3 files changed, 18 insertions(+) create mode 100644 test/test_images.jl diff --git a/src/raster/images.jl b/src/raster/images.jl index 04c4abde..aafdef2c 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -98,3 +98,9 @@ function imread(dataset::AbstractDataset, indices::Vector{<:Integer}) end imread(dataset::AbstractDataset) = imread(dataset, collect(1:nraster(dataset))) + +function imread(filename::String) + return read(filename) do dataset + imread(dataset) + end +end diff --git a/test/runtests.jl b/test/runtests.jl index fa868ff2..04c4cc0b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -32,6 +32,7 @@ include("remotefiles.jl") include("test_cookbook_geometry.jl") include("test_cookbook_projection.jl") include("test_geotransform.jl") + include("test_images.jl") include("test_utils.jl") end end diff --git a/test/test_images.jl b/test/test_images.jl new file mode 100644 index 00000000..4dd1b239 --- /dev/null +++ b/test/test_images.jl @@ -0,0 +1,11 @@ +using Test +import ArchGDAL; const AG = ArchGDAL +import ImageCore + +@testset "Test Gray colors" begin + @test AG.imread("data/utmsmall.tif") isa ImageCore.PermutedDimsArray +end + +@testset "Test RGBA colors" begin + @test AG.imread("gdalworkshop/world.tif") isa ImageCore.PermutedDimsArray +end From 73d12f51c18c7815d59dd44a5524599ede03fe79 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 13:19:03 -0700 Subject: [PATCH 081/169] Add tests for axisorder when importing CRS --- src/spatialref.jl | 4 ++-- test/test_spatialref.jl | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/spatialref.jl b/src/spatialref.jl index 028e0229..28cb63f1 100644 --- a/src/spatialref.jl +++ b/src/spatialref.jl @@ -207,10 +207,10 @@ Construct a Spatial Reference System from its WKT. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -newspatialref(wkt::AbstractString = ""; order=:compliant) = +newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) = maybesetaxisorder!(ISpatialRef(GDAL.osrnewspatialreference(wkt)), order) -unsafe_newspatialref(wkt::AbstractString = ""; order=:compliant) = +unsafe_newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) = maybesetaxisorder!(SpatialRef(GDAL.osrnewspatialreference(wkt)), order) function maybesetaxisorder!( diff --git a/test/test_spatialref.jl b/test/test_spatialref.jl index 06561049..0ef94f9c 100644 --- a/test/test_spatialref.jl +++ b/test/test_spatialref.jl @@ -235,8 +235,11 @@ import GeoFormatTypes; const GFT = GeoFormatTypes @test AG.toWKT(AG.importCRS(GFT.ESRIWellKnownText(GFT.CRS(), wkt4326))) == AG.toWKT(AG.importESRI(wkt4326)) @test AG.toWKT(AG.importCRS(GFT.ProjString(proj4326))) == AG.toWKT(AG.importPROJ4(proj4326)) @test AG.toWKT(AG.importCRS(GFT.EPSG(4326))) == AG.toWKT(AG.importEPSG(4326)) + @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :trad)) == AG.toWKT(AG.importEPSG(4326)) + @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :compliant)) == AG.toWKT(AG.importEPSG(4326)) @test AG.toWKT(AG.importCRS(GFT.GML(xml4326))) == AG.toWKT(AG.importXML(xml4326)) @test AG.toWKT(AG.importCRS(GFT.KML(""))) == AG.toWKT(AG.importEPSG(4326)) + @test_throws ArgumentError AG.importCRS(GFT.EPSG(4326), order = :unknown) end end From e4a65aa626a99ccd1710a2d07e3ba60f3fc6d565 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 13:28:02 -0700 Subject: [PATCH 082/169] Add tests for CRS conversion --- test/test_convert.jl | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/test/test_convert.jl b/test/test_convert.jl index 9d76f20f..c925eda3 100644 --- a/test/test_convert.jl +++ b/test/test_convert.jl @@ -8,26 +8,33 @@ import GeoFormatTypes; const GFT = GeoFormatTypes @testset "convert point format" begin point = AG.createpoint(100, 70) json = convert(GFT.GeoJSON, point) + @test sprint(print, convert(AG.IGeometry, json)) == + "Geometry: POINT (100 70)" kml = convert(GFT.KML, point) gml = convert(GFT.GML, point) - wkb = convert(GFT.WellKnownBinary, point) - wkt = convert(GFT.WellKnownText, point) + wkb = convert(GFT.WellKnownBinary, point) + wkt = convert(GFT.WellKnownText, point) @test json.val == AG.toJSON(point) @test kml.val == AG.toKML(point) @test gml.val == AG.toGML(point) @test wkb.val == AG.toWKB(point) @test wkt.val == AG.toWKT(point) - @test convert(GFT.GeoJSON, json) == convert(GFT.GeoJSON, wkb) == - convert(GFT.GeoJSON, wkt) == convert(GFT.GeoJSON, gml) == json + @test convert(GFT.GeoJSON, json) == + convert(GFT.GeoJSON, wkb) == + convert(GFT.GeoJSON, wkt) == + convert(GFT.GeoJSON, gml) == + json @test convert(GFT.KML, gml) == convert(GFT.KML, wkt) end @testset "convert crs format" begin proj4326 = GFT.ProjString("+proj=longlat +datum=WGS84 +no_defs") - @test convert(GFT.ProjString, GFT.CRS(), - convert(GFT.WellKnownText, GFT.CRS(), - convert(GFT.ESRIWellKnownText, GFT.CRS(), - GFT.EPSG(4326)))) == proj4326 + @test convert(GFT.ProjString, GFT.CRS(), + convert(GFT.WellKnownText, GFT.CRS(), + convert(GFT.ESRIWellKnownText, GFT.CRS(), + GFT.EPSG(4326)))) == proj4326 + @test convert(GFT.CoordSys, GFT.CRS(), proj4326) isa GFT.CoordSys + @test convert(GFT.GML, GFT.CRS(), proj4326) isa GeoFormatTypes.GML end end From d24e781ec0164f2b2f44273b09dcfb2ee9f11163 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 13:28:14 -0700 Subject: [PATCH 083/169] whitespacing --- src/convert.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/convert.jl b/src/convert.jl index 6e4dfa1b..16dccbf3 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -17,7 +17,7 @@ To convert a `Mixed` format to crs, `CRS` must be explicitly passed for `mode`. function Base.convert( target::Type{<:GFT.GeoFormat}, - mode::Union{GFT.FormatMode,Type{GFT.FormatMode}}, + mode::Union{GFT.FormatMode, Type{GFT.FormatMode}}, source::GFT.GeoFormat ) return convert(target, convert(AbstractGeometry, source)) @@ -71,9 +71,13 @@ Base.convert(::Type{<:GFT.KML}, source::AbstractGeometry) = Convert `GeoFormat` CRS data to another `GeoFormat` CRS type. """ -Base.convert(target::Type{<:GFT.GeoFormat}, mode::Union{GFT.CRS,Type{GFT.CRS}}, - source::GFT.GeoFormat) = - unsafe_convertcrs(target, importCRS(source)) +function Base.convert( + target::Type{<:GFT.GeoFormat}, + mode::Union{GFT.CRS, Type{GFT.CRS}}, + source::GFT.GeoFormat + ) + return unsafe_convertcrs(target, importCRS(source)) +end unsafe_convertcrs(::Type{<:GFT.CoordSys}, crsref) = GFT.CoordSys(toMICoordSys(crsref)) From f0d1ec9341743bd5ea7dc258c27c077f2fcd9de0 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 14:52:15 -0700 Subject: [PATCH 084/169] [Breaking] Remove destroy(driver) We do not provide any ways of creating drivers in this package and should not be in the business of destroying them. --- src/driver.jl | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/driver.jl b/src/driver.jl index 8564c6f3..b3658b9a 100644 --- a/src/driver.jl +++ b/src/driver.jl @@ -12,21 +12,6 @@ Fetch a driver based on the short name (such as `GTiff`). """ getdriver(name::AbstractString)::Driver = Driver(GDAL.gdalgetdriverbyname(name)) -""" - destroy(drv::Driver) - -Destroy a `Driver`. - -This is roughly equivalent to deleting the driver, but is guaranteed to take -place in the GDAL heap. It is important this that function not be called on a -driver that is registered with the `GDALDriverManager`. -""" -function destroy(drv::Driver)::Nothing - GDAL.gdaldestroydriver(drv.ptr) - drv.ptr = C_NULL - return nothing -end - """ register(drv::Driver) From 7023b3911522b7765fcbbff17f739b2b3c69c4a2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 16:11:13 -0700 Subject: [PATCH 085/169] Replace tabs with spaces I didn't realize my text editor was using tabs earlier --- test/test_geotransform.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_geotransform.jl b/test/test_geotransform.jl index b2962b1e..004bb2ae 100644 --- a/test/test_geotransform.jl +++ b/test/test_geotransform.jl @@ -23,8 +23,8 @@ import ArchGDAL; const AG = ArchGDAL gt3 = AG.composegeotransform(gt1, gt2) @test gt3 ≈ [ - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0, ] for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) From 5ba0075d961d8a466b353b21d8eb5fb46803a09b Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 17:14:48 -0700 Subject: [PATCH 086/169] Add tests for images Removed default support for HSL rasters since I haven't seen any examples in the wild of it actually working from GDAL, and we'll benefit from seeing actual files if someone actually wants to use it and runs into the lack of support for it. --- src/raster/images.jl | 78 ++++++++++++++++++-------------------------- test/test_images.jl | 55 +++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index aafdef2c..4be1f15e 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -1,42 +1,40 @@ function imread( colortable::ColorTable, dataset::AbstractDataset, - indices::NTuple{1, <:Integer} + indices ) - palette = getcolortable(getband(dataset,indices[1])) do ct - getpaletteinterp(ct) + palette = getcolortable(getband(dataset, indices[1])) do ct + paletteinterp(ct) end - colortype = if palette == GDAL.GPI_Gray; ColorTypes.Gray - elseif palette == GDAL.GPI_RGB; ColorTypes.RGB - elseif palette == GDAL.GPI_HLS; ColorTypes.HSL - elseif palette == GDAL.GPI_CMYK + colortype = if palette == GPI_Gray + ColorTypes.Gray + elseif palette == GPI_RGB + ColorTypes.RGBA + else error(""" - CMYK not yet supported. Please file an issue at + $palette not yet supported. Please file an issue at https://github.com/yeesian/ArchGDAL.jl/issues """) - else; error("Unknown color palette: $palette") end - return ImageCore.permuteddimsview(ImageCore.colorview(colortype, - ImageCore.normedview(read(dataset, indices[1])) - ), (2,1)) + return imread(colortype, dataset, Tuple(indices)) end function imread( - colortype::Type{ColorTypes.Gray}, + colortype::Type{<:ColorTypes.Colorant}, dataset::AbstractDataset, indices::NTuple{1, <:Integer} ) - return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.Gray, + return ImageCore.PermutedDimsArray(ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, indices[1])) ), (2,1)) end function imread( - colortype::Type{ColorTypes.RGB}, + colortype::Type{<:ColorTypes.Colorant}, dataset::AbstractDataset, indices::NTuple{3,<:Integer} ) - return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGB, + return ImageCore.PermutedDimsArray(ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, indices[1])), ImageCore.normedview(read(dataset, indices[2])), ImageCore.normedview(read(dataset, indices[3])) @@ -44,24 +42,11 @@ function imread( end function imread( - colortype::Type{ColorTypes.RGBA}, - dataset::Dataset, - indices::NTuple{4,<:Integer} - ) - return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.RGBA, - ImageCore.normedview(read(dataset, indices[1])), - ImageCore.normedview(read(dataset, indices[2])), - ImageCore.normedview(read(dataset, indices[3])), - ImageCore.normedview(read(dataset, indices[4])) - ), (2,1)) -end - -function imread( - colortype::Type{ColorTypes.YCbCr}, + colortype::Type{<:ColorTypes.Colorant}, dataset::Dataset, indices::NTuple{4,<:Integer} ) - return ImageCore.permuteddimsview(ImageCore.colorview(ColorTypes.YCbCr, + return ImageCore.PermutedDimsArray(ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, indices[1])), ImageCore.normedview(read(dataset, indices[2])), ImageCore.normedview(read(dataset, indices[3])), @@ -69,35 +54,34 @@ function imread( ), (2,1)) end -function imread(dataset::AbstractDataset, indices::Vector{<:Integer}) - gci = GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices] +function imread(dataset::AbstractDataset, indices) + gci = unique(GDALColorInterp[ + getcolorinterp(getband(dataset, i)) for i in indices + ]) gciorder = sort(gci) - colortype = if gciorder == [GCI_GrayIndex] - ColorTypes.Gray + return if gciorder == [GCI_GrayIndex] + imread(ColorTypes.Gray, dataset, Tuple(indices[sortperm(gci)])) elseif gciorder == [GCI_PaletteIndex] - ColorTable + getcolortable(getband(dataset, 1)) do ct + imread(ct, dataset, indices) + end elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand] - ColorTypes.RGB + imread(ColorTypes.RGB, dataset, Tuple(indices[sortperm(gci)])) elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand] - ColorTypes.RGBA + imread(ColorTypes.RGBA, dataset, Tuple(indices[sortperm(gci)])) elseif gciorder == [GCI_HueBand, GCI_SaturationBand, GCI_LightnessBand] - ColorTypes.HSL - # elseif gciorder == [ - # GCI_CyanBand, GCI_MagentaBand, GCI_YellowBand, GCI_BlackBand - # ] - # ColorTypes.CMYK + imread(ColorTypes.HSL, dataset, Tuple(indices[sortperm(gci)])) elseif gciorder == [GCI_YCbCr_YBand, GCI_YCbCr_CbBand, GCI_YCbCr_CrBand] - ColorTypes.YCbCr + imread(ColorTypes.YCbCr, dataset, Tuple(indices[sortperm(gci)])) else error(""" - Unknown GCI: $colororder. Please file an issue at + Unknown GCI: $gciorder. Please file an issue at https://github.com/yeesian/ArchGDAL.jl/issues """) end - return imread(colortype, dataset, Tuple(indices[sortperm(gci)])) end -imread(dataset::AbstractDataset) = imread(dataset, collect(1:nraster(dataset))) +imread(dataset::AbstractDataset) = imread(dataset, 1:nraster(dataset)) function imread(filename::String) return read(filename) do dataset diff --git a/test/test_images.jl b/test/test_images.jl index 4dd1b239..3e391574 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -1,11 +1,60 @@ using Test import ArchGDAL; const AG = ArchGDAL import ImageCore +import ColorTypes + +@testset "test_images.jl" begin @testset "Test Gray colors" begin - @test AG.imread("data/utmsmall.tif") isa ImageCore.PermutedDimsArray + @test eltype(AG.imread("data/utmsmall.tif")) == + ColorTypes.Gray{ImageCore.N0f8} +end + +AG.read("gdalworkshop/world.tif") do dataset + @testset "Test RGB colors" begin + @test eltype(AG.imread(dataset)) == + ColorTypes.RGB{ImageCore.N0f8} + end +end + +AG.create( + AG.getdriver("MEM"), + width = 2, + height = 2, + nbands = 4, + dtype = UInt8, + ) do dataset + @testset "Test RGBA colors" begin + AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_RedBand) + AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_GreenBand) + AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_BlueBand) + AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_AlphaBand) + @test eltype(AG.imread(dataset)) == + ColorTypes.RGBA{ImageCore.N0f8} + end + + @testset "Test ColorTable colors" begin + AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_PaletteIndex) + AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_PaletteIndex) + AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_PaletteIndex) + AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_PaletteIndex) + + AG.createcolortable(AG.GPI_RGB) do ct + AG.setcolortable!(AG.getband(dataset, 1), ct) + AG.setcolortable!(AG.getband(dataset, 2), ct) + AG.setcolortable!(AG.getband(dataset, 3), ct) + AG.setcolortable!(AG.getband(dataset, 4), ct) + end + @test eltype(AG.imread(dataset)) == + ColorTypes.RGBA{ImageCore.N0f8} + + AG.createcolortable(AG.GPI_CMYK) do ct # CMYK not supported yet + AG.setcolortable!(AG.getband(dataset, 1), ct) + AG.setcolortable!(AG.getband(dataset, 2), ct) + AG.setcolortable!(AG.getband(dataset, 3), ct) + end + @test_throws ErrorException AG.imread(dataset, 1:3) + end end -@testset "Test RGBA colors" begin - @test AG.imread("gdalworkshop/world.tif") isa ImageCore.PermutedDimsArray end From c49c4bcb173dd5bd47ce0a8a3dcf664e119ce55a Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 17:28:51 -0700 Subject: [PATCH 087/169] Remove untested code for HSL --- src/raster/images.jl | 4 ---- test/test_images.jl | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index 4be1f15e..7701bff4 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -69,10 +69,6 @@ function imread(dataset::AbstractDataset, indices) imread(ColorTypes.RGB, dataset, Tuple(indices[sortperm(gci)])) elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand] imread(ColorTypes.RGBA, dataset, Tuple(indices[sortperm(gci)])) - elseif gciorder == [GCI_HueBand, GCI_SaturationBand, GCI_LightnessBand] - imread(ColorTypes.HSL, dataset, Tuple(indices[sortperm(gci)])) - elseif gciorder == [GCI_YCbCr_YBand, GCI_YCbCr_CbBand, GCI_YCbCr_CrBand] - imread(ColorTypes.YCbCr, dataset, Tuple(indices[sortperm(gci)])) else error(""" Unknown GCI: $gciorder. Please file an issue at diff --git a/test/test_images.jl b/test/test_images.jl index 3e391574..efe8bad0 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -33,6 +33,13 @@ AG.create( ColorTypes.RGBA{ImageCore.N0f8} end + @testset "Test HSL colors" begin + AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_HueBand) + AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_SaturationBand) + AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_LightnessBand) + @test_throws ErrorException AG.imread(dataset, 1:3) + end + @testset "Test ColorTable colors" begin AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_PaletteIndex) AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_PaletteIndex) From 3a7287a1c67888961cd61eb9e188784b77173229 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 17:28:59 -0700 Subject: [PATCH 088/169] Test for error cases --- test/test_array.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_array.jl b/test/test_array.jl index e5e8f6ac..69578183 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -158,6 +158,17 @@ end @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) end end + + AG.create( + AG.getdriver("MEM"), + width = 2, + height = 2, + nbands = 0, + dtype = UInt8, + ) do dataset + @test_throws ArgumentError AG.RasterDataset(dataset) + @test_throws DimensionMismatch AG._common_size(dataset) + end end end From 58aa862555d74023609f37f51ec2e06f50655564 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 17:31:07 -0700 Subject: [PATCH 089/169] Add test for gray colortable --- test/test_images.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/test_images.jl b/test/test_images.jl index efe8bad0..4869650f 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -55,6 +55,15 @@ AG.create( @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} + AG.createcolortable(AG.GPI_Gray) do ct + AG.setcolortable!(AG.getband(dataset, 1), ct) + AG.setcolortable!(AG.getband(dataset, 2), ct) + AG.setcolortable!(AG.getband(dataset, 3), ct) + AG.setcolortable!(AG.getband(dataset, 4), ct) + end + @test eltype(AG.imread(dataset)) == + ColorTypes.Gray{ImageCore.N0f8} + AG.createcolortable(AG.GPI_CMYK) do ct # CMYK not supported yet AG.setcolortable!(AG.getband(dataset, 1), ct) AG.setcolortable!(AG.getband(dataset, 2), ct) From 4e2a30a221affd4faea9da091d5d2db95b55fe1a Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 17:54:45 -0700 Subject: [PATCH 090/169] Add test cases for NULL SpatialRefs --- test/test_geometry.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 22b1a0da..cb4c6736 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -318,6 +318,11 @@ end end @testset "Spatial Reference Systems" begin + @test sprint(print, AG.getspatialref(AG.IGeometry())) == "NULL Spatial Reference System" + AG.getspatialref(AG.IGeometry()) do spatialref + @test sprint(print, spatialref) == "NULL Spatial Reference System" + end + AG.createpoint(100,70,0) do geom @test sprint(print, AG.getspatialref(geom)) == "NULL Spatial Reference System" AG.getspatialref(geom) do spatialref From 5cc0c9aa23c3fc4867249b1711476fb2d709275c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 18:05:56 -0700 Subject: [PATCH 091/169] Add test for color relief --- test/remotefiles.jl | 1 + test/test_gdalutilities.jl | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/test/remotefiles.jl b/test/remotefiles.jl index 9193637e..9264d352 100644 --- a/test/remotefiles.jl +++ b/test/remotefiles.jl @@ -23,6 +23,7 @@ remotefiles = [ ("data/multi_geom.csv", "00520017658b66ff21e40cbf553672fa8e280cddae6e7a5d1f8bd36bcd521770"), ("data/missing_testcase.csv", "d49ba446aae9ef334350b64c876b4de652f28595fdecf78bea4e16af4033f7c6"), ("data/point.geojson", "8744593479054a67c784322e0c198bfa880c9388b39a2ddd4c56726944711bd9"), + ("data/color_relief.txt", "f44feef9b8529b3ff9cb64de4d01a3107f99aad7822a0a2d91055e44a915c267"), ("data/utmsmall.tif", "f40dae6e8b5e18f3648e9f095e22a0d7027014bb463418d32f732c3756d8c54f"), ("gdalworkshop/world.tif", "b376dc8af62f9894b5050a6a9273ac0763ae2990b556910d35d4a8f4753278bb"), ("ospy/data1/sites.dbf", "7df95edea06c46418287ae3430887f44f9116b29715783f7d1a11b2b931d6e7d"), diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index c3a747e6..9ced97a4 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -49,6 +49,17 @@ AG.read("data/utmsmall.tif") do ds_small 0 183 181 177 0; 0 0 0 0 0] end + AG.gdaldem( + ds_tiny, + "color-relief", + colorfile = "data/color_relief.txt" + ) do ds_dempr + @test AG.read(ds_dempr, 1) == [ 0x80 0x87 0x80 0x7b 0x7a; + 0x80 0x86 0x83 0x7e 0x7d; + 0x85 0x87 0x88 0x86 0x82; + 0x89 0x8c 0x8c 0x87 0x80; + 0x8a 0x8c 0x8c 0x88 0x80] + end end @testset "GDAL Near Black" begin From 13461549a9881623eaf191106fd0999b8ad26e9f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 18:15:12 -0700 Subject: [PATCH 092/169] Add test for conversion error --- test/test_types.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_types.jl b/test/test_types.jl index 80113151..71ba5e6f 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -21,6 +21,7 @@ import ImageCore @test Base.convert(AG.GDALDataType, UInt8) == AG.GDT_Byte @test_throws ErrorException Base.convert(AG.GDALDataType, Int64) + @test_throws ErrorException Base.convert(DataType, AG.GDT_TypeCount) @test_throws MethodError Base.convert(ImageCore.Normed, AG.GDT_Float32) end From f47104f90f2886dcada9c7db5c9df89680fc2b02 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 18:39:42 -0700 Subject: [PATCH 093/169] Add test for displaying dataset with many feature layers --- src/base/display.jl | 6 +++--- test/test_dataset.jl | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index 867c38cb..6f68edb5 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -43,11 +43,11 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO println(io, " Layer $(i - 1): $(getname(layer)) ($layergeomtype)") end if nlayers > 5 - print(io, " Remaining layers: ") + print(io, " Remaining layers:\n ") for i in 6:nlayers - print(io, "$(getname(getlayer(dataset, i - 1))) ") + print(io, "$(getname(getlayer(dataset, i - 1))), ") # display up to 5 layer names per line - if i % 5 == 0 println() end + if i % 5 == 0 && i < nlayers print(io, "\n ") end end end end diff --git a/test/test_dataset.jl b/test/test_dataset.jl index 0eb2c0e5..5ba2acf3 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -102,6 +102,27 @@ end @test AG.nfeature(layer5) == 0 @test AG.nfield(layer5) == 0 @test AG.ngeom(layer5) == 1 + + AG.create(AG.getdriver("Memory")) do dataset6 + for i in 1:20 + AG.createlayer(name = "layer$(i - 1)", dataset = dataset6) + end + @test AG.nlayer(dataset6) == 20 + @test sprint(print, dataset6) == """ + GDAL Dataset (Driver: Memory/Memory) + File(s): + + Number of feature layers: 20 + Layer 0: layer0 (wkbUnknown) + Layer 1: layer1 (wkbUnknown) + Layer 2: layer2 (wkbUnknown) + Layer 3: layer3 (wkbUnknown) + Layer 4: layer4 (wkbUnknown) + Remaining layers: + layer5, layer6, layer7, layer8, layer9, + layer10, layer11, layer12, layer13, layer14, + layer15, layer16, layer17, layer18, layer19, """ + end end end From 221f3f0975bdca1724a7fbbdec9578be10997905 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 19:14:02 -0700 Subject: [PATCH 094/169] Use format from JuliaFormatter See the README of https://github.com/domluna/JuliaFormatter.jl --- docs/make.jl | 2 +- src/ArchGDAL.jl | 94 +- src/base/display.jl | 43 +- src/base/iterators.jl | 71 +- src/constants.jl | 281 +++--- src/context.jl | 169 ++-- src/convert.jl | 50 +- src/dataset.jl | 335 +++---- src/driver.jl | 31 +- src/geointerface.jl | 42 +- src/geotransform.jl | 26 +- src/ogr/feature.jl | 141 ++- src/ogr/featuredefn.jl | 46 +- src/ogr/featurelayer.jl | 239 +++-- src/ogr/fielddefn.jl | 58 +- src/ogr/geometry.jl | 364 ++++---- src/ogr/styletable.jl | 93 +- src/raster/array.jl | 142 +-- src/raster/colortable.jl | 3 +- src/raster/images.jl | 65 +- src/raster/rasterattributetable.jl | 115 ++- src/raster/rasterband.jl | 132 ++- src/raster/rasterio.jl | 509 +++++----- src/spatialref.jl | 219 ++--- src/tables.jl | 32 +- src/types.jl | 622 +++++++------ src/utilities.jl | 108 ++- src/utils.jl | 38 +- test/remotefiles.jl | 122 ++- test/test_array.jl | 282 +++--- test/test_convert.jl | 72 +- test/test_cookbook_geometry.jl | 1385 ++++++++++++++++------------ test/test_cookbook_projection.jl | 204 ++-- test/test_dataset.jl | 202 ++-- test/test_display.jl | 133 ++- test/test_drivers.jl | 171 ++-- test/test_feature.jl | 330 +++---- test/test_featurelayer.jl | 264 +++--- test/test_fielddefn.jl | 325 +++---- test/test_gdal_tutorials.jl | 316 ++++--- test/test_gdalutilities.jl | 236 +++-- test/test_geometry.jl | 824 +++++++++++------ test/test_geos_operations.jl | 385 ++++---- test/test_geotransform.jl | 26 +- test/test_images.jl | 102 +- test/test_iterators.jl | 23 +- test/test_ospy_examples.jl | 892 +++++++++--------- test/test_rasterattrtable.jl | 187 ++-- test/test_rasterband.jl | 238 +++-- test/test_rasterio.jl | 418 +++++---- test/test_spatialref.jl | 414 +++++---- test/test_styletable.jl | 109 +-- test/test_tables.jl | 159 ++-- test/test_types.jl | 231 ++--- test/test_utils.jl | 15 +- 55 files changed, 6437 insertions(+), 5698 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 2618ddda..06785100 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -25,7 +25,7 @@ makedocs( "Design Considerations" => "considerations.md", "API Reference" => "reference.md", # "Naming Conventions" => "conventions.md", # table between GDAL, GDAL.jl, and ArchGDAL.jl - ] + ], ) deploydocs(; repo = "github.com/yeesian/ArchGDAL.jl.git") diff --git a/src/ArchGDAL.jl b/src/ArchGDAL.jl index 0a5b141b..fa85eb6b 100644 --- a/src/ArchGDAL.jl +++ b/src/ArchGDAL.jl @@ -1,56 +1,56 @@ module ArchGDAL - using Dates - using GDAL: GDAL - using GeoFormatTypes: GeoFormatTypes - using GeoInterface: GeoInterface - using Tables: Tables - using ImageCore: ImageCore - using ColorTypes: ColorTypes - - const GFT = GeoFormatTypes +using Dates +using GDAL: GDAL +using GeoFormatTypes: GeoFormatTypes +using GeoInterface: GeoInterface +using Tables: Tables +using ImageCore: ImageCore +using ColorTypes: ColorTypes - include("constants.jl") - include("utils.jl") - include("types.jl") - include("driver.jl") - include("geotransform.jl") - include("spatialref.jl") - include("dataset.jl") - include("raster/rasterband.jl") - include("raster/rasterio.jl") - include("raster/array.jl") - include("raster/rasterattributetable.jl") - include("raster/colortable.jl") - include("raster/images.jl") - include("ogr/geometry.jl") - include("ogr/feature.jl") - include("ogr/featurelayer.jl") - include("ogr/featuredefn.jl") - include("ogr/fielddefn.jl") - include("ogr/styletable.jl") - include("utilities.jl") - include("context.jl") - include("base/iterators.jl") - include("base/display.jl") - include("tables.jl") - include("geointerface.jl") - include("convert.jl") +const GFT = GeoFormatTypes - mutable struct DriverManager - function DriverManager() - drivermanager = new() - GDAL.gdalallregister() - finalizer((dm,) -> GDAL.gdaldestroydrivermanager(), drivermanager) - return drivermanager - end +include("constants.jl") +include("utils.jl") +include("types.jl") +include("driver.jl") +include("geotransform.jl") +include("spatialref.jl") +include("dataset.jl") +include("raster/rasterband.jl") +include("raster/rasterio.jl") +include("raster/array.jl") +include("raster/rasterattributetable.jl") +include("raster/colortable.jl") +include("raster/images.jl") +include("ogr/geometry.jl") +include("ogr/feature.jl") +include("ogr/featurelayer.jl") +include("ogr/featuredefn.jl") +include("ogr/fielddefn.jl") +include("ogr/styletable.jl") +include("utilities.jl") +include("context.jl") +include("base/iterators.jl") +include("base/display.jl") +include("tables.jl") +include("geointerface.jl") +include("convert.jl") + +mutable struct DriverManager + function DriverManager() + drivermanager = new() + GDAL.gdalallregister() + finalizer((dm,) -> GDAL.gdaldestroydrivermanager(), drivermanager) + return drivermanager end +end - const DRIVER_MANAGER = Ref{DriverManager}() +const DRIVER_MANAGER = Ref{DriverManager}() - function __init__() - DRIVER_MANAGER[] = DriverManager() - return nothing - end +function __init__() + DRIVER_MANAGER[] = DriverManager() + return nothing +end end # module diff --git a/src/base/display.jl b/src/base/display.jl index 6f68edb5..1deb2e3e 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -26,7 +26,7 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO print(io, "\nDataset (width x height): ") println(io, "$(width(dataset)) x $(height(dataset)) (pixels)") println(io, "Number of raster bands: $nrasters") - for i in 1:min(nrasters, 3) + for i = 1:min(nrasters, 3) print(io, " ") summarize(io, getband(dataset, i)) end @@ -37,17 +37,19 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO if nlayers > 0 println(io, "\nNumber of feature layers: $nlayers") ndisplay = min(nlayers, 5) # display up to 5 layers - for i in 1:ndisplay + for i = 1:ndisplay layer = getlayer(dataset, i - 1) layergeomtype = getgeomtype(layer) println(io, " Layer $(i - 1): $(getname(layer)) ($layergeomtype)") end if nlayers > 5 print(io, " Remaining layers:\n ") - for i in 6:nlayers + for i = 6:nlayers print(io, "$(getname(getlayer(dataset, i - 1))), ") # display up to 5 layer names per line - if i % 5 == 0 && i < nlayers print(io, "\n ") end + if i % 5 == 0 && i < nlayers + print(io, "\n ") + end end end end @@ -57,8 +59,7 @@ end #Add method to avoid show from DiskArrays Base.show(io::IO, raster::RasterDataset)::IO = show(io, raster.ds) -Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::IO = - show(io, raster.ds) +Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::IO = show(io, raster.ds) function summarize(io::IO, rasterband::AbstractRasterBand)::IO if rasterband.ptr == C_NULL @@ -75,19 +76,14 @@ function summarize(io::IO, rasterband::AbstractRasterBand)::IO return io end -Base.show(io::IO, rasterband::AbstractRasterBand)::IO = - show(io, "text/plain", rasterband) +Base.show(io::IO, rasterband::AbstractRasterBand)::IO = show(io, "text/plain", rasterband) -function Base.show( - io::IO, - ::MIME"text/plain", - rasterband::AbstractRasterBand - )::IO +function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand)::IO summarize(io, rasterband) if rasterband.ptr == C_NULL return io end - (x,y) = blocksize(rasterband) + (x, y) = blocksize(rasterband) sc = getscale(rasterband) ofs = getoffset(rasterband) norvw = noverview(rasterband) @@ -96,7 +92,7 @@ function Base.show( print(io, " blocksize: $(x)×$(y), nodata: $nv, ") println(io, "units: $(sc)px + $ofs$ut") print(io, " overviews: ") - for i in 1:norvw + for i = 1:norvw ovr_band = getoverview(rasterband, i - 1) print(io, "($(i - 1)) $(width(ovr_band))x$(height(ovr_band)) ") i % 3 == 0 && print(io, "\n ") @@ -117,7 +113,7 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO # Print Geometries n = ngeom(featuredefn) ngeomdisplay = min(n, 3) - for i in 1:ngeomdisplay + for i = 1:ngeomdisplay gfd = getgeomdefn(featuredefn, i - 1) display = " Geometry $(i - 1) ($(getname(gfd))): [$(gettype(gfd))]" if length(display) > 75 @@ -145,7 +141,7 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO # Print Features n = nfield(featuredefn) nfielddisplay = min(n, 5) - for i in 1:nfielddisplay + for i = 1:nfielddisplay fd = getfielddefn(featuredefn, i - 1) display = " Field $(i - 1) ($(getname(fd))): [$(gettype(fd))]" if length(display) > 75 @@ -177,7 +173,7 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO end n = ngeom(featuredefn) ngeomdisplay = min(n, 3) - for i in 1:ngeomdisplay + for i = 1:ngeomdisplay gfd = getgeomdefn(featuredefn, i - 1) println(io, " Geometry (index $(i - 1)): $gfd") end @@ -185,7 +181,7 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO n = nfield(featuredefn) nfielddisplay = min(n, 5) - for i in 1:nfielddisplay + for i = 1:nfielddisplay fd = getfielddefn(featuredefn, i - 1) println(io, " Field (index $(i - 1)): $fd") end @@ -218,13 +214,13 @@ function Base.show(io::IO, feature::Feature)::IO end println(io, "Feature") n = ngeom(feature) - for i in 1:min(n, 3) + for i = 1:min(n, 3) displayname = geomname(getgeom(feature, i - 1)) println(io, " (index $(i - 1)) geom => $displayname") end n > 3 && println(io, "...\n Number of geometries: $n") n = nfield(feature) - for i in 1:min(n, 10) + for i = 1:min(n, 10) displayname = getname(getfielddefn(feature, i - 1)) print(io, " (index $(i - 1)) $displayname => ") println(io, "$(getfield(feature, i - 1))") @@ -241,7 +237,7 @@ function Base.show(io::IO, spref::AbstractSpatialRef)::IO projstr = toPROJ4(spref) if length(projstr) > 45 projstart = projstr[1:35] - projend = projstr[(end - 4):end] + projend = projstr[(end-4):end] print(io, "Spatial Reference System: $projstart ... $projend") else print(io, "Spatial Reference System: $projstr") @@ -280,5 +276,4 @@ function Base.show(io::IO, ct::ColorTable)::IO return io end -Base.show(io::IO, ::MIME"text/plain", ct::ColorTable)::IO = - show(io, ct) +Base.show(io::IO, ::MIME"text/plain", ct::ColorTable)::IO = show(io, ct) diff --git a/src/base/iterators.jl b/src/base/iterators.jl index 57e31117..299232a1 100644 --- a/src/base/iterators.jl +++ b/src/base/iterators.jl @@ -1,7 +1,7 @@ function Base.iterate( - layer::AbstractFeatureLayer, - state::Integer = 0 - )::Union{Nothing, Tuple{Feature, Int64}} + layer::AbstractFeatureLayer, + state::Integer = 0, +)::Union{Nothing,Tuple{Feature,Int64}} layer.ptr == C_NULL && return nothing state == 0 && resetreading!(layer) ptr = GDAL.ogr_l_getnextfeature(layer.ptr) @@ -17,7 +17,7 @@ Base.eltype(layer::AbstractFeatureLayer)::DataType = Feature Base.length(layer::AbstractFeatureLayer)::Integer = nfeature(layer, true) -struct BlockIterator{T <: Integer} +struct BlockIterator{T<:Integer} rows::T cols::T ni::T @@ -27,10 +27,7 @@ struct BlockIterator{T <: Integer} ybsize::T end -function blocks( - ::Type{T}, - raster::AbstractRasterBand - )::BlockIterator{T} where {T <: Integer} +function blocks(::Type{T}, raster::AbstractRasterBand)::BlockIterator{T} where {T<:Integer} (xbsize, ybsize) = blocksize(raster) rows = T(height(raster)) cols = T(width(raster)) @@ -44,9 +41,9 @@ function blocks(raster::AbstractRasterBand)::BlockIterator{Int64} end function Base.iterate( - obj::BlockIterator{T}, - iter::T = 0 - )::Union{Nothing, Tuple{Tuple{Tuple{T, T}, Tuple{T, T}}, T}} where T + obj::BlockIterator{T}, + iter::T = 0, +)::Union{Nothing,Tuple{Tuple{Tuple{T,T},Tuple{T,T}},T}} where {T} iter == obj.n && return nothing j = floor(Int, iter / obj.ni) i = iter % obj.ni @@ -63,75 +60,69 @@ function Base.iterate( return (((i, j), (nrows, ncols)), iter + 1) end -struct WindowIterator{T <: Integer} +struct WindowIterator{T<:Integer} blockiter::BlockIterator{T} end Base.size(i::WindowIterator) = (i.blockiter.ni, i.blockiter.nj) Base.length(i::WindowIterator) = i.blockiter.n -function Base.IteratorSize(::Type{WindowIterator{T}}) where {T <: Integer} +function Base.IteratorSize(::Type{WindowIterator{T}}) where {T<:Integer} return Base.HasShape{2}() end -function Base.IteratorEltype(::Type{WindowIterator{T}}) where {T <: Integer} +function Base.IteratorEltype(::Type{WindowIterator{T}}) where {T<:Integer} return Base.HasEltype() end -function Base.eltype(::WindowIterator{T})::DataType where {T <: Integer} - return Tuple{UnitRange{T}, UnitRange{T}} +function Base.eltype(::WindowIterator{T})::DataType where {T<:Integer} + return Tuple{UnitRange{T},UnitRange{T}} end function windows( - ::Type{T}, - raster::AbstractRasterBand - )::WindowIterator{T} where {T <: Integer} + ::Type{T}, + raster::AbstractRasterBand, +)::WindowIterator{T} where {T<:Integer} return WindowIterator{T}(blocks(T, raster)) end -windows(raster::AbstractRasterBand)::WindowIterator{Int64} = - windows(Int64, raster) +windows(raster::AbstractRasterBand)::WindowIterator{Int64} = windows(Int64, raster) function Base.iterate( - obj::WindowIterator{T}, - iter::T = 0 - )::Union{Nothing, Tuple{NTuple{2, UnitRange{T}}, T}} where T <: Integer + obj::WindowIterator{T}, + iter::T = 0, +)::Union{Nothing,Tuple{NTuple{2,UnitRange{T}},T}} where {T<:Integer} handle = obj.blockiter next = Base.iterate(handle, iter) next == nothing && return nothing (((i, j), (nrows, ncols)), iter) = next - return ( - ((1:ncols) .+ j * handle.xbsize, (1:nrows) .+ i * handle.ybsize), - iter - ) + return (((1:ncols) .+ j * handle.xbsize, (1:nrows) .+ i * handle.ybsize), iter) end -mutable struct BufferIterator{R <: Real, T <: Integer} +mutable struct BufferIterator{R<:Real,T<:Integer} raster::AbstractRasterBand w::WindowIterator{T} buffer::Matrix{R} end function bufferwindows( - ::Type{T}, - raster::AbstractRasterBand - )::BufferIterator{pixeltype(raster), T} where {T <: Integer} - return BufferIterator{pixeltype(raster), T}( + ::Type{T}, + raster::AbstractRasterBand, +)::BufferIterator{pixeltype(raster),T} where {T<:Integer} + return BufferIterator{pixeltype(raster),T}( raster, windows(T, raster), - Matrix{pixeltype(raster)}(undef, blocksize(raster)...) + Matrix{pixeltype(raster)}(undef, blocksize(raster)...), ) end -function bufferwindows( - raster::AbstractRasterBand - )::BufferIterator{pixeltype(raster), Int64} +function bufferwindows(raster::AbstractRasterBand)::BufferIterator{pixeltype(raster),Int64} return bufferwindows(Int64, raster) end function Base.iterate( - obj::BufferIterator{R, T}, - iter::T = 0 - )::Union{Nothing, Tuple{Matrix{R}, T}} where {R <: Real, T <: Integer} + obj::BufferIterator{R,T}, + iter::T = 0, +)::Union{Nothing,Tuple{Matrix{R},T}} where {R<:Real,T<:Integer} next = Base.iterate(obj.w, iter) next == nothing && return nothing ((cols, rows), iter) = next diff --git a/src/constants.jl b/src/constants.jl index 80fdb622..e0e56552 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -1,6 +1,7 @@ const StringList = Ptr{Cstring} -@enum(GDALDataType, +@enum( + GDALDataType, GDT_Unknown = 0, GDT_Byte = 1, GDT_UInt16 = 2, @@ -16,25 +17,27 @@ const StringList = Ptr{Cstring} GDT_TypeCount = 12, ) -@enum(OGRFieldType, - OFTInteger = 0, - OFTIntegerList = 1, - OFTReal = 2, - OFTRealList = 3, - OFTString = 4, - OFTStringList = 5, - OFTWideString = 6, - OFTWideStringList = 7, - OFTBinary = 8, - OFTDate = 9, - OFTTime = 10, - OFTDateTime = 11, - OFTInteger64 = 12, - OFTInteger64List = 13, - OFTMaxType = 14, # 13 -) - -@enum(OGRFieldSubType, +@enum( + OGRFieldType, + OFTInteger = 0, + OFTIntegerList = 1, + OFTReal = 2, + OFTRealList = 3, + OFTString = 4, + OFTStringList = 5, + OFTWideString = 6, + OFTWideStringList = 7, + OFTBinary = 8, + OFTDate = 9, + OFTTime = 10, + OFTDateTime = 11, + OFTInteger64 = 12, + OFTInteger64List = 13, + OFTMaxType = 14, # 13 +) + +@enum( + OGRFieldSubType, OFSTNone = 0, OFSTBoolean = 1, OFSTInt16 = 2, @@ -43,19 +46,12 @@ const StringList = Ptr{Cstring} OFSTMaxSubType = 5, # 4 ) -@enum(OGRJustification, - OJUndefined = 0, - OJLeft = 1, - OJRight = 2, -) +@enum(OGRJustification, OJUndefined = 0, OJLeft = 1, OJRight = 2,) -@enum(GDALRATFieldType, - GFT_Integer = 0, - GFT_Real = 1, - GFT_String = 2, -) +@enum(GDALRATFieldType, GFT_Integer = 0, GFT_Real = 1, GFT_String = 2,) -@enum(GDALRATFieldUsage, +@enum( + GDALRATFieldUsage, GFU_Generic = 0, GFU_PixelCount = 1, GFU_Name = 2, @@ -77,24 +73,14 @@ const StringList = Ptr{Cstring} GFU_MaxCount = 18, ) -@enum(GDALAccess, - GA_ReadOnly = 0, - GA_Update = 1, -) +@enum(GDALAccess, GA_ReadOnly = 0, GA_Update = 1,) -@enum(GDALRWFlag, - GF_Read = 0, - GF_Write = 1, -) +@enum(GDALRWFlag, GF_Read = 0, GF_Write = 1,) -@enum(GDALPaletteInterp, - GPI_Gray = 0, - GPI_RGB = 1, - GPI_CMYK = 2, - GPI_HLS = 3, -) +@enum(GDALPaletteInterp, GPI_Gray = 0, GPI_RGB = 1, GPI_CMYK = 2, GPI_HLS = 3,) -@enum(GDALColorInterp, +@enum( + GDALColorInterp, GCI_Undefined = 0, GCI_GrayIndex = 1, # GreyScale GCI_PaletteIndex = 2, # Paletted (see associated color table) @@ -115,7 +101,8 @@ const StringList = Ptr{Cstring} GCI_Max = 17, # Max current value = 16 ) -@enum(GDALAsyncStatusType, +@enum( + GDALAsyncStatusType, GARIO_PENDING = 0, GARIO_UPDATE = 1, GARIO_ERROR = 2, @@ -123,7 +110,8 @@ const StringList = Ptr{Cstring} GARIO_TypeCount = 4, ) -@enum(OGRSTClassId, +@enum( + OGRSTClassId, OGRSTCNone = 0, OGRSTCPen = 1, OGRSTCBrush = 2, @@ -132,7 +120,8 @@ const StringList = Ptr{Cstring} OGRSTCVector = 5, ) -@enum(OGRSTUnitId, +@enum( + OGRSTUnitId, OGRSTUGround = 0, OGRSTUPixel = 1, OGRSTUPoints = 2, @@ -141,107 +130,107 @@ const StringList = Ptr{Cstring} OGRSTUInches = 5, ) -@enum(OGRwkbGeometryType, - wkbUnknown = 0, - wkbPoint = 1, - wkbLineString = 2, - wkbPolygon = 3, - wkbMultiPoint = 4, - wkbMultiLineString = 5, - wkbMultiPolygon = 6, - wkbGeometryCollection = 7, - wkbCircularString = 8, - wkbCompoundCurve = 9, - wkbCurvePolygon = 10, - wkbMultiCurve = 11, - wkbMultiSurface = 12, - wkbCurve = 13, - wkbSurface = 14, - wkbPolyhedralSurface = 15, - wkbTIN = 16, - wkbTriangle = 17, - wkbNone = 18, - wkbLinearRing = 19, - wkbCircularStringZ = 20, - wkbCompoundCurveZ = 21, - wkbCurvePolygonZ = 22, - wkbMultiCurveZ = 23, - wkbMultiSurfaceZ = 24, - wkbCurveZ = 25, - wkbSurfaceZ = 26, - wkbPolyhedralSurfaceZ = 27, - wkbTINZ = 28, - wkbTriangleZ = 29, - wkbPointM = 30, - wkbLineStringM = 31, - wkbPolygonM = 32, - wkbMultiPointM = 33, - wkbMultiLineStringM = 34, - wkbMultiPolygonM = 35, - wkbGeometryCollectionM = 36, - wkbCircularStringM = 37, - wkbCompoundCurveM = 38, - wkbCurvePolygonM = 39, - wkbMultiCurveM = 40, - wkbMultiSurfaceM = 41, - wkbCurveM = 42, - wkbSurfaceM = 43, - wkbPolyhedralSurfaceM = 44, - wkbTINM = 45, - wkbTriangleM = 46, - wkbPointZM = 47, - wkbLineStringZM = 48, - wkbPolygonZM = 49, - wkbMultiPointZM = 50, - wkbMultiLineStringZM = 51, - wkbMultiPolygonZM = 52, - wkbGeometryCollectionZM = 53, - wkbCircularStringZM = 54, - wkbCompoundCurveZM = 55, - wkbCurvePolygonZM = 56, - wkbMultiCurveZM = 57, - wkbMultiSurfaceZM = 58, - wkbCurveZM = 59, - wkbSurfaceZM = 60, - wkbPolyhedralSurfaceZM = 61, - wkbTINZM = 62, - wkbTriangleZM = 63, - wkbPoint25D = 64, - wkbLineString25D = 65, - wkbPolygon25D = 66, - wkbMultiPoint25D = 67, - wkbMultiLineString25D = 68, - wkbMultiPolygon25D = 69, - wkbGeometryCollection25D = 70, -) - -@enum(OGRwkbByteOrder, - wkbXDR = 0, - wkbNDR = 1, -) - -@enum(GDALOpenFlag, - OF_READONLY = GDAL.GDAL_OF_READONLY, # 0x00 - OF_UPDATE = GDAL.GDAL_OF_UPDATE, # 0x01 +@enum( + OGRwkbGeometryType, + wkbUnknown = 0, + wkbPoint = 1, + wkbLineString = 2, + wkbPolygon = 3, + wkbMultiPoint = 4, + wkbMultiLineString = 5, + wkbMultiPolygon = 6, + wkbGeometryCollection = 7, + wkbCircularString = 8, + wkbCompoundCurve = 9, + wkbCurvePolygon = 10, + wkbMultiCurve = 11, + wkbMultiSurface = 12, + wkbCurve = 13, + wkbSurface = 14, + wkbPolyhedralSurface = 15, + wkbTIN = 16, + wkbTriangle = 17, + wkbNone = 18, + wkbLinearRing = 19, + wkbCircularStringZ = 20, + wkbCompoundCurveZ = 21, + wkbCurvePolygonZ = 22, + wkbMultiCurveZ = 23, + wkbMultiSurfaceZ = 24, + wkbCurveZ = 25, + wkbSurfaceZ = 26, + wkbPolyhedralSurfaceZ = 27, + wkbTINZ = 28, + wkbTriangleZ = 29, + wkbPointM = 30, + wkbLineStringM = 31, + wkbPolygonM = 32, + wkbMultiPointM = 33, + wkbMultiLineStringM = 34, + wkbMultiPolygonM = 35, + wkbGeometryCollectionM = 36, + wkbCircularStringM = 37, + wkbCompoundCurveM = 38, + wkbCurvePolygonM = 39, + wkbMultiCurveM = 40, + wkbMultiSurfaceM = 41, + wkbCurveM = 42, + wkbSurfaceM = 43, + wkbPolyhedralSurfaceM = 44, + wkbTINM = 45, + wkbTriangleM = 46, + wkbPointZM = 47, + wkbLineStringZM = 48, + wkbPolygonZM = 49, + wkbMultiPointZM = 50, + wkbMultiLineStringZM = 51, + wkbMultiPolygonZM = 52, + wkbGeometryCollectionZM = 53, + wkbCircularStringZM = 54, + wkbCompoundCurveZM = 55, + wkbCurvePolygonZM = 56, + wkbMultiCurveZM = 57, + wkbMultiSurfaceZM = 58, + wkbCurveZM = 59, + wkbSurfaceZM = 60, + wkbPolyhedralSurfaceZM = 61, + wkbTINZM = 62, + wkbTriangleZM = 63, + wkbPoint25D = 64, + wkbLineString25D = 65, + wkbPolygon25D = 66, + wkbMultiPoint25D = 67, + wkbMultiLineString25D = 68, + wkbMultiPolygon25D = 69, + wkbGeometryCollection25D = 70, +) + +@enum(OGRwkbByteOrder, wkbXDR = 0, wkbNDR = 1,) + +@enum( + GDALOpenFlag, + OF_READONLY = GDAL.GDAL_OF_READONLY, # 0x00 + OF_UPDATE = GDAL.GDAL_OF_UPDATE, # 0x01 # OF_All = GDAL.GDAL_OF_ALL, # 0x00 - OF_RASTER = GDAL.GDAL_OF_RASTER, # 0x02 - OF_VECTOR = GDAL.GDAL_OF_VECTOR, # 0x04 - OF_GNM = GDAL.GDAL_OF_GNM, # 0x08 - OF_KIND_MASK = GDAL.GDAL_OF_KIND_MASK, # 0x1e - OF_SHARED = GDAL.GDAL_OF_SHARED, # 0x20 - OF_VERBOSE_ERROR = GDAL.GDAL_OF_VERBOSE_ERROR, # 0x40 - OF_INTERNAL = GDAL.GDAL_OF_INTERNAL, # 0x80 + OF_RASTER = GDAL.GDAL_OF_RASTER, # 0x02 + OF_VECTOR = GDAL.GDAL_OF_VECTOR, # 0x04 + OF_GNM = GDAL.GDAL_OF_GNM, # 0x08 + OF_KIND_MASK = GDAL.GDAL_OF_KIND_MASK, # 0x1e + OF_SHARED = GDAL.GDAL_OF_SHARED, # 0x20 + OF_VERBOSE_ERROR = GDAL.GDAL_OF_VERBOSE_ERROR, # 0x40 + OF_INTERNAL = GDAL.GDAL_OF_INTERNAL, # 0x80 # OF_DEFAULT_BLOCK_ACCESS = GDAL.GDAL_OF_DEFAULT_BLOCK_ACCESS, # 0 - OF_ARRAY_BLOCK_ACCESS = GDAL.GDAL_OF_ARRAY_BLOCK_ACCESS, # 0x0100 + OF_ARRAY_BLOCK_ACCESS = GDAL.GDAL_OF_ARRAY_BLOCK_ACCESS, # 0x0100 OF_HASHSET_BLOCK_ACCESS = GDAL.GDAL_OF_HASHSET_BLOCK_ACCESS, # 0x0200 # OF_RESERVED_1 = GDAL.GDAL_OF_RESERVED_1, # 0x0300 - OF_BLOCK_ACCESS_MASK = GDAL.GDAL_OF_BLOCK_ACCESS_MASK, # 0x0300 + OF_BLOCK_ACCESS_MASK = GDAL.GDAL_OF_BLOCK_ACCESS_MASK, # 0x0300 ) -@enum(FieldValidation, - F_VAL_NULL = GDAL.OGR_F_VAL_NULL, # 0x0001 - F_VAL_GEOM_TYPE = GDAL.OGR_F_VAL_GEOM_TYPE, # 0x0002 - F_VAL_WIDTH = GDAL.OGR_F_VAL_WIDTH, # 0x0004 - F_VAL_ALLOW_NULL_WHEN_DEFAULT = GDAL.OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, # 0x0008 - F_VAL_ALLOW_DIFFERENT_GEOM_DIM = GDAL.OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, # 0x0010 +@enum( + FieldValidation, + F_VAL_NULL = GDAL.OGR_F_VAL_NULL, # 0x0001 + F_VAL_GEOM_TYPE = GDAL.OGR_F_VAL_GEOM_TYPE, # 0x0002 + F_VAL_WIDTH = GDAL.OGR_F_VAL_WIDTH, # 0x0004 + F_VAL_ALLOW_NULL_WHEN_DEFAULT = GDAL.OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, # 0x0008 + F_VAL_ALLOW_DIFFERENT_GEOM_DIM = GDAL.OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, # 0x0010 ) diff --git a/src/context.jl b/src/context.jl index d66f950b..35de4b77 100644 --- a/src/context.jl +++ b/src/context.jl @@ -1,8 +1,4 @@ -function environment( - f::Function; - globalconfig::Vector=[], - threadconfig::Vector=[] - ) +function environment(f::Function; globalconfig::Vector = [], threadconfig::Vector = []) # Save the current settings # # CPLGetConfigOption() will return the value of the config option, be it @@ -13,25 +9,27 @@ function environment( # CPLSetThreadLocalConfigOption() # # (ref https://github.com/mapbox/rasterio/pull/997#issuecomment-287117289) - globalsettings = Dict(k => getconfigoption(k) for (k,v) in globalconfig) - localsettings = Dict( - k => getthreadconfigoption(k) for (k,v) in threadconfig - ) - for (k,v) in threadconfig; setthreadconfigoption(k, v) end - for (k,v) in globalconfig; setconfigoption(k, v) end + globalsettings = Dict(k => getconfigoption(k) for (k, v) in globalconfig) + localsettings = Dict(k => getthreadconfigoption(k) for (k, v) in threadconfig) + for (k, v) in threadconfig + setthreadconfigoption(k, v) + end + for (k, v) in globalconfig + setconfigoption(k, v) + end return try f() finally # Restore previous settings - for (k,v) in globalsettings + for (k, v) in globalsettings if v == "" clearconfigoption(k) else setconfigoption(k, v) end end - for (k,v) in localsettings + for (k, v) in localsettings if v == "" clearthreadconfigoption(k) else @@ -100,17 +98,23 @@ to the layer. format driver. """ function addfielddefn!( - layer::T, - name::AbstractString, - etype::OGRFieldType; - nwidth::Integer = 0, - nprecision::Integer = 0, - justify::OGRJustification = OJUndefined, - approx::Bool = false - )::T where {T <: AbstractFeatureLayer} + layer::T, + name::AbstractString, + etype::OGRFieldType; + nwidth::Integer = 0, + nprecision::Integer = 0, + justify::OGRJustification = OJUndefined, + approx::Bool = false, +)::T where {T<:AbstractFeatureLayer} fielddefn = unsafe_createfielddefn(name, etype) - setparams!(fielddefn, name, etype, nwidth = nwidth, nprecision = nprecision, - justify = justify) + setparams!( + fielddefn, + name, + etype, + nwidth = nwidth, + nprecision = nprecision, + justify = justify, + ) addfielddefn!(layer, fielddefn) destroy(fielddefn) return layer @@ -145,11 +149,11 @@ to the layer. slightly different form depending on the limitations of the driver. """ function writegeomdefn!( - layer::T, - name::AbstractString, - etype::OGRwkbGeometryType; - approx::Bool = false - )::T where {T <: AbstractFeatureLayer} + layer::T, + name::AbstractString, + etype::OGRwkbGeometryType; + approx::Bool = false, +)::T where {T<:AbstractFeatureLayer} geomdefn = unsafe_creategeomdefn(name, etype) addgeomdefn!(layer, geomdefn) destroy(geomdefn) @@ -157,12 +161,12 @@ function writegeomdefn!( end function writegeomdefn( - f::Function, - layer::AbstractFeatureLayer, - name::AbstractString, - etype::OGRwkbGeometryType; - approx::Bool = false - ) + f::Function, + layer::AbstractFeatureLayer, + name::AbstractString, + etype::OGRwkbGeometryType; + approx::Bool = false, +) geomdefn = unsafe_creategeomdefn(name, etype) return try f(geomdefn) @@ -173,25 +177,84 @@ function writegeomdefn( end for gdalfunc in ( - :boundary, :buffer, :centroid, :clone, :convexhull, :create, - :createcolortable, :createcoordtrans, :copy, :createfeaturedefn, - :createfielddefn, :creategeom, :creategeomcollection, - :creategeomfieldcollection, :creategeomdefn, :createlayer, - :createlinearring, :createlinestring, :createmultilinestring, - :createmultipoint, :createmultipolygon, :createmultipolygon_noholes, - :createpoint, :createpolygon, :createRAT, :createstylemanager, - :createstyletable, :createstyletool, :curvegeom, :delaunaytriangulation, - :difference, :forceto, :fromGML, :fromJSON, :fromWKB, :fromWKT, - :gdalbuildvrt, :gdaldem, :gdalgrid, :gdalnearblack, :gdalrasterize, - :gdaltranslate, :gdalvectortranslate, :gdalwarp, :getband, - :getcolortable, :getfeature, :getgeom, :getlayer, :getmaskband, - :getoverview, :getpart, :getspatialref, :importCRS, :intersection, - :importEPSG, :importEPSGA, :importESRI, :importPROJ4, :importWKT, - :importXML, :importURL, :lineargeom, :newspatialref, :nextfeature, - :pointalongline, :pointonsurface, :polygonfromedges, :polygonize, :read, - :sampleoverview, :simplify, :simplifypreservetopology, :symdifference, - :union, :update, :readraster, - ) + :boundary, + :buffer, + :centroid, + :clone, + :convexhull, + :create, + :createcolortable, + :createcoordtrans, + :copy, + :createfeaturedefn, + :createfielddefn, + :creategeom, + :creategeomcollection, + :creategeomfieldcollection, + :creategeomdefn, + :createlayer, + :createlinearring, + :createlinestring, + :createmultilinestring, + :createmultipoint, + :createmultipolygon, + :createmultipolygon_noholes, + :createpoint, + :createpolygon, + :createRAT, + :createstylemanager, + :createstyletable, + :createstyletool, + :curvegeom, + :delaunaytriangulation, + :difference, + :forceto, + :fromGML, + :fromJSON, + :fromWKB, + :fromWKT, + :gdalbuildvrt, + :gdaldem, + :gdalgrid, + :gdalnearblack, + :gdalrasterize, + :gdaltranslate, + :gdalvectortranslate, + :gdalwarp, + :getband, + :getcolortable, + :getfeature, + :getgeom, + :getlayer, + :getmaskband, + :getoverview, + :getpart, + :getspatialref, + :importCRS, + :intersection, + :importEPSG, + :importEPSGA, + :importESRI, + :importPROJ4, + :importWKT, + :importXML, + :importURL, + :lineargeom, + :newspatialref, + :nextfeature, + :pointalongline, + :pointonsurface, + :polygonfromedges, + :polygonize, + :read, + :sampleoverview, + :simplify, + :simplifypreservetopology, + :symdifference, + :union, + :update, + :readraster, +) eval(quote function $(gdalfunc)(f::Function, args...; kwargs...) obj = $(Symbol("unsafe_$gdalfunc"))(args...; kwargs...) diff --git a/src/convert.jl b/src/convert.jl index 16dccbf3..7786b5e9 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -16,10 +16,10 @@ To convert a `Mixed` format to crs, `CRS` must be explicitly passed for `mode`. """ function Base.convert( - target::Type{<:GFT.GeoFormat}, - mode::Union{GFT.FormatMode, Type{GFT.FormatMode}}, - source::GFT.GeoFormat - ) + target::Type{<:GFT.GeoFormat}, + mode::Union{GFT.FormatMode,Type{GFT.FormatMode}}, + source::GFT.GeoFormat, +) return convert(target, convert(AbstractGeometry, source)) end @@ -33,14 +33,12 @@ end Convert `GeoFormat` geometry data to an ArchGDAL `Geometry` type """ -Base.convert(::Type{<:AbstractGeometry}, source::GFT.AbstractWellKnownText) = +Base.convert(::Type{<:AbstractGeometry}, source::GFT.AbstractWellKnownText) = fromWKT(GFT.val(source)) -Base.convert(::Type{<:AbstractGeometry}, source::GFT.WellKnownBinary) = +Base.convert(::Type{<:AbstractGeometry}, source::GFT.WellKnownBinary) = fromWKB(GFT.val(source)) -Base.convert(::Type{<:AbstractGeometry}, source::GFT.GeoJSON) = - fromJSON(GFT.val(source)) -Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) = - fromGML(GFT.val(source)) +Base.convert(::Type{<:AbstractGeometry}, source::GFT.GeoJSON) = fromJSON(GFT.val(source)) +Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) = fromGML(GFT.val(source)) """ convert(::Type{<:GeoFormatTypes.AbstractWellKnownText}, @@ -53,16 +51,14 @@ Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) = Convert `AbstractGeometry` data to any geometry `GeoFormat`. """ -Base.convert(::Type{<:GFT.AbstractWellKnownText}, source::AbstractGeometry) = +Base.convert(::Type{<:GFT.AbstractWellKnownText}, source::AbstractGeometry) = GFT.WellKnownText(GFT.Geom(), toWKT(source)) -Base.convert(::Type{<:GFT.WellKnownBinary}, source::AbstractGeometry) = +Base.convert(::Type{<:GFT.WellKnownBinary}, source::AbstractGeometry) = GFT.WellKnownBinary(GFT.Geom(), toWKB(source)) -Base.convert(::Type{<:GFT.GeoJSON}, source::AbstractGeometry) = - GFT.GeoJSON(toJSON(source)) -Base.convert(::Type{<:GFT.GML}, source::AbstractGeometry) = +Base.convert(::Type{<:GFT.GeoJSON}, source::AbstractGeometry) = GFT.GeoJSON(toJSON(source)) +Base.convert(::Type{<:GFT.GML}, source::AbstractGeometry) = GFT.GML(GFT.Geom(), toGML(source)) -Base.convert(::Type{<:GFT.KML}, source::AbstractGeometry) = - GFT.KML(toKML(source)) +Base.convert(::Type{<:GFT.KML}, source::AbstractGeometry) = GFT.KML(toKML(source)) """ convert(target::Type{<:GeoFormatTypes.GeoFormat}, mode::CRS, @@ -72,21 +68,17 @@ Convert `GeoFormat` CRS data to another `GeoFormat` CRS type. """ function Base.convert( - target::Type{<:GFT.GeoFormat}, - mode::Union{GFT.CRS, Type{GFT.CRS}}, - source::GFT.GeoFormat - ) + target::Type{<:GFT.GeoFormat}, + mode::Union{GFT.CRS,Type{GFT.CRS}}, + source::GFT.GeoFormat, +) return unsafe_convertcrs(target, importCRS(source)) end -unsafe_convertcrs(::Type{<:GFT.CoordSys}, crsref) = - GFT.CoordSys(toMICoordSys(crsref)) -unsafe_convertcrs(::Type{<:GFT.ProjString}, crsref) = - GFT.ProjString(toPROJ4(crsref)) -unsafe_convertcrs(::Type{<:GFT.WellKnownText}, crsref) = +unsafe_convertcrs(::Type{<:GFT.CoordSys}, crsref) = GFT.CoordSys(toMICoordSys(crsref)) +unsafe_convertcrs(::Type{<:GFT.ProjString}, crsref) = GFT.ProjString(toPROJ4(crsref)) +unsafe_convertcrs(::Type{<:GFT.WellKnownText}, crsref) = GFT.WellKnownText(GFT.CRS(), toWKT(crsref)) unsafe_convertcrs(::Type{<:GFT.ESRIWellKnownText}, crsref) = GFT.ESRIWellKnownText(GFT.CRS(), toWKT(morphtoESRI!(crsref))) -unsafe_convertcrs(::Type{<:GFT.GML}, crsref) = - GFT.GML(toXML(crsref)) - +unsafe_convertcrs(::Type{<:GFT.GML}, crsref) = GFT.GML(toXML(crsref)) diff --git a/src/dataset.jl b/src/dataset.jl index ff0998cc..9cf816ae 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -21,14 +21,19 @@ particular \"chunking\" the copy in substantial blocks and, if appropriate, performing the transfer in a pixel interleaved fashion. """ function copywholeraster!( - source::AbstractDataset, - dest::D; - options = StringList(C_NULL), - progressfunc::Function = GDAL.gdaldummyprogress, - progressdata::Any = C_NULL - )::D where {D <: AbstractDataset} - result = GDAL.gdaldatasetcopywholeraster(source.ptr, dest.ptr, options, - @cplprogress(progressfunc), progressdata) + source::AbstractDataset, + dest::D; + options = StringList(C_NULL), + progressfunc::Function = GDAL.gdaldummyprogress, + progressdata::Any = C_NULL, +)::D where {D<:AbstractDataset} + result = GDAL.gdaldatasetcopywholeraster( + source.ptr, + dest.ptr, + options, + @cplprogress(progressfunc), + progressdata, + ) @cplerr result "Failed to copy whole raster" return dest end @@ -83,23 +88,25 @@ In some situations, the new dataset can be created in another process through the GDAL API Proxy mechanism. """ function unsafe_copy( - dataset::AbstractDataset; - filename::AbstractString = string("/vsimem/$(gensym())"), - driver::Driver = getdriver(dataset), - strict::Bool = false, - options = StringList(C_NULL), - progressfunc::Function = GDAL.gdaldummyprogress, - progressdata = C_NULL - )::Dataset - return Dataset(GDAL.gdalcreatecopy( - driver.ptr, - filename, - dataset.ptr, - strict, - options, - @cplprogress(progressfunc), - progressdata - )) + dataset::AbstractDataset; + filename::AbstractString = string("/vsimem/$(gensym())"), + driver::Driver = getdriver(dataset), + strict::Bool = false, + options = StringList(C_NULL), + progressfunc::Function = GDAL.gdaldummyprogress, + progressdata = C_NULL, +)::Dataset + return Dataset( + GDAL.gdalcreatecopy( + driver.ptr, + filename, + dataset.ptr, + strict, + options, + @cplprogress(progressfunc), + progressdata, + ), + ) end """ @@ -140,23 +147,25 @@ end The newly created dataset. """ function copy( - dataset::AbstractDataset; - filename::AbstractString = string("/vsimem/$(gensym())"), - driver::Driver = getdriver(dataset), - strict::Bool = false, - options = StringList(C_NULL), - progressfunc::Function = GDAL.gdaldummyprogress, - progressdata = C_NULL - )::IDataset - return IDataset(GDAL.gdalcreatecopy( - driver.ptr, - filename, - dataset.ptr, - strict, - options, - @cplprogress(progressfunc), - progressdata - )) + dataset::AbstractDataset; + filename::AbstractString = string("/vsimem/$(gensym())"), + driver::Driver = getdriver(dataset), + strict::Bool = false, + options = StringList(C_NULL), + progressfunc::Function = GDAL.gdaldummyprogress, + progressdata = C_NULL, +)::IDataset + return IDataset( + GDAL.gdalcreatecopy( + driver.ptr, + filename, + dataset.ptr, + strict, + options, + @cplprogress(progressfunc), + progressdata, + ), + ) end """ @@ -164,11 +173,7 @@ end Writes the dataset to the designated filename. """ -function write( - dataset::AbstractDataset, - filename::AbstractString; - kwargs... - )::Nothing +function write(dataset::AbstractDataset, filename::AbstractString; kwargs...)::Nothing destroy(unsafe_copy(dataset, filename = filename; kwargs...)) return nothing end @@ -198,30 +203,44 @@ In GDAL 2, the arguments nXSize, nYSize and nBands can be passed to 0 when creating a vector-only dataset for a compatible driver. """ function unsafe_create( - filename::AbstractString; - driver::Driver = identifydriver(filename), - width::Integer = 0, - height::Integer = 0, - nbands::Integer = 0, - dtype::DataType = Any, - options = StringList(C_NULL) - )::Dataset - result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - convert(GDALDataType, dtype), options) + filename::AbstractString; + driver::Driver = identifydriver(filename), + width::Integer = 0, + height::Integer = 0, + nbands::Integer = 0, + dtype::DataType = Any, + options = StringList(C_NULL), +)::Dataset + result = GDAL.gdalcreate( + driver.ptr, + filename, + width, + height, + nbands, + convert(GDALDataType, dtype), + options, + ) return Dataset(result) end function unsafe_create( - driver::Driver; - filename::AbstractString = string("/vsimem/$(gensym())"), - width::Integer = 0, - height::Integer = 0, - nbands::Integer = 0, - dtype::DataType = Any, - options = StringList(C_NULL) - )::Dataset - result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - convert(GDALDataType, dtype), options) + driver::Driver; + filename::AbstractString = string("/vsimem/$(gensym())"), + width::Integer = 0, + height::Integer = 0, + nbands::Integer = 0, + dtype::DataType = Any, + options = StringList(C_NULL), +)::Dataset + result = GDAL.gdalcreate( + driver.ptr, + filename, + width, + height, + nbands, + convert(GDALDataType, dtype), + options, + ) return Dataset(result) end @@ -257,30 +276,44 @@ end The newly created dataset. """ function create( - filename::AbstractString; - driver::Driver = identifydriver(filename), - width::Integer = 0, - height::Integer = 0, - nbands::Integer = 0, - dtype::DataType = Any, - options = StringList(C_NULL) - )::IDataset - result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - convert(GDALDataType, dtype), options) + filename::AbstractString; + driver::Driver = identifydriver(filename), + width::Integer = 0, + height::Integer = 0, + nbands::Integer = 0, + dtype::DataType = Any, + options = StringList(C_NULL), +)::IDataset + result = GDAL.gdalcreate( + driver.ptr, + filename, + width, + height, + nbands, + convert(GDALDataType, dtype), + options, + ) return IDataset(result) end function create( - driver::Driver; - filename::AbstractString = string("/vsimem/$(gensym())"), - width::Integer = 0, - height::Integer = 0, - nbands::Integer = 0, - dtype::DataType = Any, - options = StringList(C_NULL) - )::IDataset - result = GDAL.gdalcreate(driver.ptr, filename, width, height, nbands, - convert(GDALDataType, dtype), options) + driver::Driver; + filename::AbstractString = string("/vsimem/$(gensym())"), + width::Integer = 0, + height::Integer = 0, + nbands::Integer = 0, + dtype::DataType = Any, + options = StringList(C_NULL), +)::IDataset + result = GDAL.gdalcreate( + driver.ptr, + filename, + width, + height, + nbands, + convert(GDALDataType, dtype), + options, + ) return IDataset(result) end @@ -343,14 +376,13 @@ archive (see `VSIInstallTarFileHandler()`), or a HTTP / FTP server (see `VSIInstallCurlFileHandler()`) """ function unsafe_read( - filename::AbstractString; - flags = OF_READONLY, - alloweddrivers = StringList(C_NULL), - options = StringList(C_NULL), - siblingfiles = StringList(C_NULL) - )::Dataset - result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, - siblingfiles) + filename::AbstractString; + flags = OF_READONLY, + alloweddrivers = StringList(C_NULL), + options = StringList(C_NULL), + siblingfiles = StringList(C_NULL), +)::Dataset + result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, siblingfiles) return Dataset(result) end @@ -390,14 +422,13 @@ end The corresponding dataset. """ function read( - filename::AbstractString; - flags = OF_READONLY | OF_VERBOSE_ERROR, - alloweddrivers = StringList(C_NULL), - options = StringList(C_NULL), - siblingfiles = StringList(C_NULL) - )::IDataset - result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, - siblingfiles) + filename::AbstractString; + flags = OF_READONLY | OF_VERBOSE_ERROR, + alloweddrivers = StringList(C_NULL), + options = StringList(C_NULL), + siblingfiles = StringList(C_NULL), +)::IDataset + result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, siblingfiles) return IDataset(result) end @@ -423,24 +454,21 @@ height(dataset::AbstractDataset)::Integer = GDAL.gdalgetrasterysize(dataset.ptr) Fetch the number of raster bands on this dataset. """ -nraster(dataset::AbstractDataset)::Integer = - GDAL.gdalgetrastercount(dataset.ptr) +nraster(dataset::AbstractDataset)::Integer = GDAL.gdalgetrastercount(dataset.ptr) """ nlayer(dataset::AbstractDataset) Fetch the number of feature layers on this dataset. """ -nlayer(dataset::AbstractDataset)::Integer = - GDAL.gdaldatasetgetlayercount(dataset.ptr) +nlayer(dataset::AbstractDataset)::Integer = GDAL.gdaldatasetgetlayercount(dataset.ptr) """ getdriver(dataset::AbstractDataset) Fetch the driver that the dataset was created with """ -getdriver(dataset::AbstractDataset)::Driver = - Driver(GDAL.gdalgetdatasetdriver(dataset.ptr)) +getdriver(dataset::AbstractDataset)::Driver = Driver(GDAL.gdalgetdatasetdriver(dataset.ptr)) """ filelist(dataset::AbstractDataset) @@ -455,8 +483,7 @@ list is owned by the caller and should be deallocated with `CSLDestroy()`. The returned filenames will normally be relative or absolute paths depending on the path used to originally open the dataset. The strings will be UTF-8 encoded """ -filelist(dataset::AbstractDataset)::Vector{String} = - GDAL.gdalgetfilelist(dataset.ptr) +filelist(dataset::AbstractDataset)::Vector{String} = GDAL.gdalgetfilelist(dataset.ptr) """ getlayer(dataset::AbstractDataset, i::Integer) @@ -485,7 +512,7 @@ the application. function getlayer(dataset::AbstractDataset, name::AbstractString)::IFeatureLayer return IFeatureLayer( GDAL.gdaldatasetgetlayerbyname(dataset.ptr, name), - ownedby = dataset + ownedby = dataset, ) end @@ -501,7 +528,7 @@ Delete the indicated layer (at index i; between `0` to `nlayer()-1`) `OGRERR_NONE` on success, or `OGRERR_UNSUPPORTED_OPERATION` if deleting layers is not supported for this dataset. """ -function deletelayer!(dataset::T, i::Integer)::T where {T <: AbstractDataset} +function deletelayer!(dataset::T, i::Integer)::T where {T<:AbstractDataset} result = GDAL.gdaldatasetdeletelayer(dataset.ptr, i) @ogrerr result "Failed to delete layer" return dataset @@ -537,17 +564,17 @@ testcapability(dataset::AbstractDataset, capability::AbstractString)::Bool = Bool(GDAL.gdaldatasettestcapability(dataset.ptr, capability)) function listcapability( - dataset::AbstractDataset, - capabilities = (GDAL.ODsCCreateLayer, - GDAL.ODsCDeleteLayer, - GDAL.ODsCCreateGeomFieldAfterCreateLayer, - GDAL.ODsCCurveGeometries, - GDAL.ODsCTransactions, - GDAL.ODsCEmulatedTransactions) - )::Dict{String, Bool} - return Dict{String, Bool}( - c => testcapability(dataset, c) for c in capabilities - ) + dataset::AbstractDataset, + capabilities = ( + GDAL.ODsCCreateLayer, + GDAL.ODsCDeleteLayer, + GDAL.ODsCCreateGeomFieldAfterCreateLayer, + GDAL.ODsCCurveGeometries, + GDAL.ODsCTransactions, + GDAL.ODsCEmulatedTransactions, + ), +)::Dict{String,Bool} + return Dict{String,Bool}(c => testcapability(dataset, c) for c in capabilities) end """ @@ -582,17 +609,14 @@ an OGRLayer containing the results of the query. Deallocate with ReleaseResultSet(). """ function unsafe_executesql( - dataset::AbstractDataset, - query::AbstractString; - dialect::AbstractString = "", - spatialfilter::Geometry = Geometry(C_NULL) - )::FeatureLayer - return FeatureLayer(GDAL.gdaldatasetexecutesql( - dataset.ptr, - query, - spatialfilter.ptr, - dialect - )) + dataset::AbstractDataset, + query::AbstractString; + dialect::AbstractString = "", + spatialfilter::Geometry = Geometry(C_NULL), +)::FeatureLayer + return FeatureLayer( + GDAL.gdaldatasetexecutesql(dataset.ptr, query, spatialfilter.ptr, dialect), + ) end """ @@ -608,10 +632,7 @@ before destroying the `Dataset` may cause errors. * `dataset`: the dataset handle. * `layer`: the result of a previous ExecuteSQL() call. """ -function releaseresultset( - dataset::AbstractDataset, - layer::FeatureLayer - )::Nothing +function releaseresultset(dataset::AbstractDataset, layer::FeatureLayer)::Nothing GDAL.gdaldatasetreleaseresultset(dataset.ptr, layer.ptr) destroy(layer) return nothing @@ -657,9 +678,9 @@ transformation to projection coordinates. `CE_None` on success, or `CE_Failure` if no transform can be fetched. """ function getgeotransform!( - dataset::AbstractDataset, - transform::Vector{Cdouble} - )::Vector{Cdouble} + dataset::AbstractDataset, + transform::Vector{Cdouble}, +)::Vector{Cdouble} @assert length(transform) == 6 result = GDAL.gdalgetgeotransform(dataset.ptr, pointer(transform)) @cplerr result "Failed to get geotransform" @@ -675,9 +696,9 @@ getgeotransform(dataset::AbstractDataset)::Vector{Cdouble} = Set the affine transformation coefficients. """ function setgeotransform!( - dataset::T, - transform::Vector{Cdouble} - )::T where {T <: AbstractDataset} + dataset::T, + transform::Vector{Cdouble}, +)::T where {T<:AbstractDataset} @assert length(transform) == 6 result = GDAL.gdalsetgeotransform(dataset.ptr, pointer(transform)) @cplerr result "Failed to transform raster dataset" @@ -700,18 +721,14 @@ It should be suitable for use with the OGRSpatialReference class. When a projection definition is not available an empty (but not `NULL`) string is returned. """ -getproj(dataset::AbstractDataset)::String = - GDAL.gdalgetprojectionref(dataset.ptr) +getproj(dataset::AbstractDataset)::String = GDAL.gdalgetprojectionref(dataset.ptr) """ setproj!(dataset::AbstractDataset, projstring::AbstractString) Set the projection reference string for this dataset. """ -function setproj!( - dataset::T, - projstring::AbstractString - )::T where {T <: AbstractDataset} +function setproj!(dataset::T, projstring::AbstractString)::T where {T<:AbstractDataset} result = GDAL.gdalsetprojection(dataset.ptr, projstring) @cplerr result "Could not set projection" return dataset @@ -738,13 +755,13 @@ returned, and CPLGetLastErrorNo() will return CPLE_NotSupported. * `progressdata` application data to pass to the progress function. """ function buildoverviews!( - dataset::T, - overviewlist::Vector{Cint}; - bandlist::Vector{Cint} = Cint[], - resampling::AbstractString = "NEAREST", - progressfunc::Function = GDAL.gdaldummyprogress, - progressdata = C_NULL - )::T where {T <: AbstractDataset} + dataset::T, + overviewlist::Vector{Cint}; + bandlist::Vector{Cint} = Cint[], + resampling::AbstractString = "NEAREST", + progressfunc::Function = GDAL.gdaldummyprogress, + progressdata = C_NULL, +)::T where {T<:AbstractDataset} result = GDAL.gdalbuildoverviews( dataset.ptr, resampling, @@ -753,7 +770,7 @@ function buildoverviews!( length(bandlist), bandlist, @cplprogress(progressfunc), - progressdata + progressdata, ) @cplerr result "Failed to build overviews" return dataset diff --git a/src/driver.jl b/src/driver.jl index b3658b9a..3ac64665 100644 --- a/src/driver.jl +++ b/src/driver.jl @@ -67,9 +67,9 @@ ndriver()::Integer = GDAL.gdalgetdrivercount() Returns a listing of all registered drivers. """ -listdrivers()::Dict{String,String} = Dict{String,String}([ - shortname(getdriver(i)) => longname(getdriver(i)) for i in 0:(ndriver()-1) -]) +listdrivers()::Dict{String,String} = Dict{String,String}( + [shortname(getdriver(i)) => longname(getdriver(i)) for i = 0:(ndriver()-1)], +) """ identifydriver(filename::AbstractString) @@ -112,10 +112,7 @@ in the list of creation options are compatible with the capabilities declared by the `GDAL_DMD_CREATIONOPTIONLIST` metadata item. In case of incompatibility a (non fatal) warning will be emited and ``false`` will be returned. """ -function validate( - drv::Driver, - options::Vector{T} - )::Bool where {T <: AbstractString} +function validate(drv::Driver, options::Vector{T})::Bool where {T<:AbstractString} return Bool(GDAL.gdalvalidatecreationoptions(drv.ptr, options)) end @@ -127,21 +124,17 @@ Copy all the files associated with a dataset. """ function copyfiles end -function copyfiles( - drv::Driver, - new::AbstractString, - old::AbstractString - )::Nothing +function copyfiles(drv::Driver, new::AbstractString, old::AbstractString)::Nothing result = GDAL.gdalcopydatasetfiles(drv.ptr, new, old) @cplerr result "Failed to copy dataset files" return nothing end function copyfiles( - drvname::AbstractString, - new::AbstractString, - old::AbstractString - )::Nothing + drvname::AbstractString, + new::AbstractString, + old::AbstractString, +)::Nothing copyfiles(getdriver(drvname), new, old) return nothing end @@ -152,9 +145,9 @@ end Returns a `Dict{String,String}` of all of the file extensions that can be read by GDAL, with their respective drivers' `shortname`s. """ -function extensions()::Dict{String, String} - extdict = Dict{String, String}() - for i in 1:ndriver() +function extensions()::Dict{String,String} + extdict = Dict{String,String}() + for i = 1:ndriver() driver = getdriver(i) if !(driver.ptr == C_NULL) # exts is a space-delimited list in a String, so split it diff --git a/src/geointerface.jl b/src/geointerface.jl index 74bf8bf2..a3a94fe2 100644 --- a/src/geointerface.jl +++ b/src/geointerface.jl @@ -1,15 +1,21 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), - multipointtypes = (wkbMultiPoint, wkbMultiPoint25D, wkbMultiPointM, - wkbMultiPointZM), - linetypes = (wkbLineString, wkbLineString25D, wkbLineStringM, - wkbLineStringZM), - multilinetypes = (wkbMultiLineString, wkbMultiLineString25D, - wkbMultiLineStringM, wkbMultiLineStringZM), + multipointtypes = (wkbMultiPoint, wkbMultiPoint25D, wkbMultiPointM, wkbMultiPointZM), + linetypes = (wkbLineString, wkbLineString25D, wkbLineStringM, wkbLineStringZM), + multilinetypes = ( + wkbMultiLineString, + wkbMultiLineString25D, + wkbMultiLineStringM, + wkbMultiLineStringZM, + ), polygontypes = (wkbPolygon, wkbPolygon25D, wkbPolygonM, wkbPolygonZM), - multipolygontypes = (wkbMultiPolygon, wkbMultiPolygon25D, wkbMultiPolygonM, - wkbMultiPolygonZM), - collectiontypes = (wkbGeometryCollection, wkbGeometryCollection25D, - wkbGeometryCollectionM, wkbGeometryCollectionZM) + multipolygontypes = + (wkbMultiPolygon, wkbMultiPolygon25D, wkbMultiPolygonM, wkbMultiPolygonZM), + collectiontypes = ( + wkbGeometryCollection, + wkbGeometryCollection25D, + wkbGeometryCollectionM, + wkbGeometryCollectionZM, + ) function GeoInterface.geotype(g::AbstractGeometry)::Symbol gtype = getgeomtype(g) @@ -40,27 +46,23 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), ndim = getcoorddim(g) return if gtype in pointtypes if ndim == 2 - Float64[getx(g,0), gety(g,0)] + Float64[getx(g, 0), gety(g, 0)] elseif ndim == 3 - Float64[getx(g,0), gety(g,0), getz(g,0)] + Float64[getx(g, 0), gety(g, 0), getz(g, 0)] else error("getcoorddim($g) returned $ndim: expected 2 or 3") end elseif gtype in multipointtypes - Vector{Float64}[ - GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) - ] + Vector{Float64}[GeoInterface.coordinates(getgeom(g, i - 1)) for i = 1:ngeom(g)] elseif gtype in linetypes || gtype == wkbLinearRing - Vector{Float64}[ - collect(getpoint(g, i - 1)[1:ndim]) for i in 1:ngeom(g) - ] + Vector{Float64}[collect(getpoint(g, i - 1)[1:ndim]) for i = 1:ngeom(g)] elseif gtype in multilinetypes || gtype in polygontypes Vector{Vector{Float64}}[ - GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i = 1:ngeom(g) ] elseif gtype in multipolygontypes Vector{Vector{Vector{Float64}}}[ - GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i = 1:ngeom(g) ] end end diff --git a/src/geotransform.jl b/src/geotransform.jl index fff40403..d73876d1 100644 --- a/src/geotransform.jl +++ b/src/geotransform.jl @@ -13,10 +13,7 @@ converts the equation from being pixel to geo to being geo to pixel. ### Returns `gt_out` """ -function invgeotransform!( - gt_in::Vector{Float64}, - gt_out::Vector{Float64} - )::Vector{Float64} +function invgeotransform!(gt_in::Vector{Float64}, gt_out::Vector{Float64})::Vector{Float64} result = Bool(GDAL.gdalinvgeotransform(pointer(gt_in), pointer(gt_out))) result || error("Geotransform coefficients is uninvertable") return gt_out @@ -43,10 +40,10 @@ georeferenced `(geo_x,geo_y)` location. * `line` input line position. """ function applygeotransform( - geotransform::Vector{Float64}, - pixel::Float64, - line::Float64 - )::Vector{Float64} + geotransform::Vector{Float64}, + pixel::Float64, + line::Float64, +)::Vector{Float64} geo_xy = Vector{Float64}(undef, 2) geo_x = pointer(geo_xy) geo_y = geo_x + sizeof(Float64) @@ -69,17 +66,14 @@ being applied to a point. * `gtout` the output geotransform, six values. """ function composegeotransform!( - gt1::Vector{Float64}, - gt2::Vector{Float64}, - gtout::Vector{Float64} - )::Vector{Float64} + gt1::Vector{Float64}, + gt2::Vector{Float64}, + gtout::Vector{Float64}, +)::Vector{Float64} GDAL.gdalcomposegeotransforms(pointer(gt1), pointer(gt2), pointer(gtout)) return gtout end -function composegeotransform( - gt1::Vector{Float64}, - gt2::Vector{Float64} - )::Vector{Float64} +function composegeotransform(gt1::Vector{Float64}, gt2::Vector{Float64})::Vector{Float64} return composegeotransform!(gt1, gt2, Vector{Float64}(undef, 6)) end diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index f6655207..b78e5714 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -111,10 +111,7 @@ the field index, or -1 if no matching field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. """ -function findfieldindex( - feature::Feature, - name::Union{AbstractString, Symbol} - )::Integer +function findfieldindex(feature::Feature, name::Union{AbstractString,Symbol})::Integer return GDAL.ogr_f_getfieldindex(feature.ptr, name) end @@ -127,8 +124,7 @@ Test if a field has ever been assigned a value or not. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -isfieldset(feature::Feature, i::Integer)::Bool = - Bool(GDAL.ogr_f_isfieldset(feature.ptr, i)) +isfieldset(feature::Feature, i::Integer)::Bool = Bool(GDAL.ogr_f_isfieldset(feature.ptr, i)) """ unsetfield!(feature::Feature, i::Integer) @@ -169,8 +165,7 @@ Fetch field value as integer. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asint(feature::Feature, i::Integer)::Int32 = - GDAL.ogr_f_getfieldasinteger(feature.ptr, i) +asint(feature::Feature, i::Integer)::Int32 = GDAL.ogr_f_getfieldasinteger(feature.ptr, i) """ asint64(feature::Feature, i::Integer) @@ -205,8 +200,7 @@ Fetch field value as a string. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asstring(feature::Feature, i::Integer)::String = - GDAL.ogr_f_getfieldasstring(feature.ptr, i) +asstring(feature::Feature, i::Integer)::String = GDAL.ogr_f_getfieldasstring(feature.ptr, i) """ asintlist(feature::Feature, i::Integer) @@ -320,10 +314,26 @@ OFTDate, OFTTime and OFTDateTime fields. `true` on success or `false` on failure. """ function asdatetime(feature::Feature, i::Integer)::DateTime - pyr = Ref{Cint}(); pmth = Ref{Cint}(); pday = Ref{Cint}() - phr = Ref{Cint}(); pmin = Ref{Cint}(); psec = Ref{Cint}(); ptz=Ref{Cint}() - result = Bool(GDAL.ogr_f_getfieldasdatetime(feature.ptr, i, pyr, pmth, pday, - phr, pmin, psec, ptz)) + pyr = Ref{Cint}() + pmth = Ref{Cint}() + pday = Ref{Cint}() + phr = Ref{Cint}() + pmin = Ref{Cint}() + psec = Ref{Cint}() + ptz = Ref{Cint}() + result = Bool( + GDAL.ogr_f_getfieldasdatetime( + feature.ptr, + i, + pyr, + pmth, + pday, + phr, + pmin, + psec, + ptz, + ), + ) (result == false) && error("Failed to fetch datetime at index $i") return DateTime(pyr[], pmth[], pday[], phr[], pmin[], psec[]) end @@ -365,21 +375,21 @@ function getdefault(feature::Feature, i::Integer)::String end function getfield(feature::Feature, i::Integer) - _FETCHFIELD = Dict{OGRFieldType, Function}( - OFTInteger => asint, #0 - OFTIntegerList => asintlist, #1 - OFTReal => asdouble, #2 - OFTRealList => asdoublelist, #3 - OFTString => asstring, #4 - OFTStringList => asstringlist, #5 - # const OFTWideString = (UInt32)(6) - # const OFTWideStringList = (UInt32)(7) - OFTBinary => asbinary, #8 - OFTDate => asdatetime, #9 - OFTTime => asdatetime, #10 - OFTDateTime => asdatetime, #11 - OFTInteger64 => asint64, #12 - OFTInteger64List => asint64list, #13 + _FETCHFIELD = Dict{OGRFieldType,Function}( + OFTInteger => asint, #0 + OFTIntegerList => asintlist, #1 + OFTReal => asdouble, #2 + OFTRealList => asdoublelist, #3 + OFTString => asstring, #4 + OFTStringList => asstringlist, #5 + # const OFTWideString = (UInt32)(6) + # const OFTWideStringList = (UInt32)(7) + OFTBinary => asbinary, #8 + OFTDate => asdatetime, #9 + OFTTime => asdatetime, #10 + OFTDateTime => asdatetime, #11 + OFTInteger64 => asint64, #12 + OFTInteger64List => asint64list, #13 ) return if isfieldset(feature, i) _fieldtype = gettype(getfielddefn(feature, i)) @@ -390,7 +400,7 @@ function getfield(feature::Feature, i::Integer) end end -function getfield(feature::Feature, name::Union{AbstractString, Symbol}) +function getfield(feature::Feature, name::Union{AbstractString,Symbol}) i = findfieldindex(feature, name) return if i == -1 nothing @@ -452,20 +462,16 @@ function setfield!(feature::Feature, i::Integer, value::Vector{Int64})::Feature return feature end -function setfield!( - feature::Feature, - i::Integer, - value::Vector{Float64} - )::Feature +function setfield!(feature::Feature, i::Integer, value::Vector{Float64})::Feature GDAL.ogr_f_setfielddoublelist(feature.ptr, i, length(value), value) return feature end function setfield!( - feature::Feature, - i::Integer, - value::Vector{T} - )::Feature where T <: AbstractString + feature::Feature, + i::Integer, + value::Vector{T}, +)::Feature where {T<:AbstractString} GDAL.ogr_f_setfieldstringlist(feature.ptr, i, value) return feature end @@ -490,12 +496,7 @@ function setfield!(feature::Feature, i::Integer, value::Vector{UInt8})::Feature return feature end -function setfield!( - feature::Feature, - i::Integer, - dt::DateTime, - tzflag::Int = 0 - )::Feature +function setfield!(feature::Feature, i::Integer, dt::DateTime, tzflag::Int = 0)::Feature GDAL.ogr_f_setfielddatetime( feature.ptr, i, @@ -505,7 +506,7 @@ function setfield!( Dates.hour(dt), Dates.minute(dt), Dates.second(dt), - tzflag + tzflag, ) return feature end @@ -551,10 +552,7 @@ the geometry field index, or -1 if no matching geometry field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetGeomFieldIndex()` method. """ -function findgeomindex( - feature::Feature, - name::Union{AbstractString, Symbol} = "" - )::Integer +function findgeomindex(feature::Feature, name::Union{AbstractString,Symbol} = "")::Integer return GDAL.ogr_f_getgeomfieldindex(feature.ptr, name) end @@ -585,10 +583,7 @@ function unsafe_getgeom(feature::Feature, i::Integer)::Geometry end end -function getgeom( - feature::Feature, - name::Union{AbstractString, Symbol} - )::IGeometry +function getgeom(feature::Feature, name::Union{AbstractString,Symbol})::IGeometry i = findgeomindex(feature, name) return if i == -1 IGeometry() @@ -597,10 +592,7 @@ function getgeom( end end -function unsafe_getgeom( - feature::Feature, - name::Union{AbstractString, Symbol} - )::Geometry +function unsafe_getgeom(feature::Feature, name::Union{AbstractString,Symbol})::Geometry i = findgeomindex(feature, name) return if i == -1 Geometry() @@ -685,24 +677,19 @@ otherwise an error code. """ function setfrom! end -function setfrom!( - feature1::Feature, - feature2::Feature, - forgiving::Bool = false - )::Feature +function setfrom!(feature1::Feature, feature2::Feature, forgiving::Bool = false)::Feature result = GDAL.ogr_f_setfrom(feature1.ptr, feature2.ptr, forgiving) @ogrerr result "OGRErr $result: Failed to set feature" return feature1 end function setfrom!( - feature1::Feature, - feature2::Feature, - indices::Vector{Cint}, - forgiving::Bool = false - )::Feature - result = GDAL.ogr_f_setfromwithmap(feature1.ptr, feature2.ptr, forgiving, - indices) + feature1::Feature, + feature2::Feature, + indices::Vector{Cint}, + forgiving::Bool = false, +)::Feature + result = GDAL.ogr_f_setfromwithmap(feature1.ptr, feature2.ptr, forgiving, indices) @ogrerr result "OGRErr $result: Failed to set feature with map" return feature1 end @@ -713,8 +700,7 @@ end Fetch style string for this feature. """ -getstylestring(feature::Feature)::String = - GDAL.ogr_f_getstylestring(feature.ptr) +getstylestring(feature::Feature)::String = GDAL.ogr_f_getstylestring(feature.ptr) """ setstylestring!(feature::Feature, style::AbstractString) @@ -792,8 +778,7 @@ The native media type is the identifier for the format of the native data. It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type), e.g. \"application/vnd.geo+json\" for JSON. """ -getmediatype(feature::Feature)::String = - GDAL.ogr_f_getnativemediatype(feature.ptr) +getmediatype(feature::Feature)::String = GDAL.ogr_f_getnativemediatype(feature.ptr) """ setmediatype!(feature::Feature, mediatype::AbstractString) @@ -821,10 +806,10 @@ Fill unset fields with default values that might be defined. * `papszOptions`: unused currently. Must be set to `NULL`. """ function fillunsetwithdefault!( - feature::Feature; - notnull::Bool = true, - options = StringList(C_NULL) - )::Feature + feature::Feature; + notnull::Bool = true, + options = StringList(C_NULL), +)::Feature GDAL.ogr_f_fillunsetwithdefault(feature.ptr, notnull, options) return feature end diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index a2a3aad7..0a69bb29 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -19,16 +19,14 @@ The count is used to track the number of `Feature`s referencing this definition. ### Returns The updated reference count. """ -reference(featuredefn::FeatureDefn)::Integer = - GDAL.ogr_fd_reference(featuredefn.ptr) +reference(featuredefn::FeatureDefn)::Integer = GDAL.ogr_fd_reference(featuredefn.ptr) """ dereference(featuredefn::FeatureDefn) Decrements the reference count by one, and returns the updated count. """ -dereference(featuredefn::FeatureDefn)::Integer = - GDAL.ogr_fd_dereference(featuredefn.ptr) +dereference(featuredefn::FeatureDefn)::Integer = GDAL.ogr_fd_dereference(featuredefn.ptr) """ nreference(featuredefn::AbstractFeatureDefn) @@ -66,8 +64,7 @@ end Get name of the OGRFeatureDefn passed as an argument. """ -getname(featuredefn::AbstractFeatureDefn)::String = - GDAL.ogr_fd_getname(featuredefn.ptr) +getname(featuredefn::AbstractFeatureDefn)::String = GDAL.ogr_fd_getname(featuredefn.ptr) """ nfield(featuredefn::AbstractFeatureDefn) @@ -109,9 +106,9 @@ the field index, or -1 if no match found. This uses the OGRFeatureDefn::GetFieldIndex() method. """ function findfieldindex( - featuredefn::AbstractFeatureDefn, - name::Union{AbstractString, Symbol} - )::Integer + featuredefn::AbstractFeatureDefn, + name::Union{AbstractString,Symbol}, +)::Integer return GDAL.ogr_fd_getfieldindex(featuredefn.ptr, name) end @@ -127,10 +124,7 @@ This function should only be called while there are no OGRFeature objects in existence based on this OGRFeatureDefn. The OGRFieldDefn passed in is copied, and remains the responsibility of the caller. """ -function addfielddefn!( - featuredefn::FeatureDefn, - fielddefn::FieldDefn - )::FeatureDefn +function addfielddefn!(featuredefn::FeatureDefn, fielddefn::FieldDefn)::FeatureDefn GDAL.ogr_fd_addfielddefn(featuredefn.ptr, fielddefn.ptr) return featuredefn end @@ -170,10 +164,7 @@ existence based on this OGRFeatureDefn. at position `i` after reordering, its position before reordering was `indices[i]`. """ -function reorderfielddefns!( - featuredefn::FeatureDefn, - indices::Vector{Cint} - )::FeatureDefn +function reorderfielddefns!(featuredefn::FeatureDefn, indices::Vector{Cint})::FeatureDefn result = GDAL.ogr_fd_reorderfielddefns(featuredefn.ptr, indices) @ogrerr result "Failed to reorder $indices in the feature definition" return featuredefn @@ -208,10 +199,7 @@ type. The default upon creation is `wkbUnknown` which allows for any geometry type. The geometry type should generally not be changed after any OGRFeatures have been created against this definition. """ -function setgeomtype!( - featuredefn::FeatureDefn, - etype::OGRwkbGeometryType - )::FeatureDefn +function setgeomtype!(featuredefn::FeatureDefn, etype::OGRwkbGeometryType)::FeatureDefn GDAL.ogr_fd_setgeomtype(featuredefn.ptr, etype) return featuredefn end @@ -289,10 +277,7 @@ name (case insensitively) is returned. ### Returns the geometry field index, or -1 if no match found. """ -function findgeomindex( - featuredefn::AbstractFeatureDefn, - name::AbstractString = "" - )::Integer +function findgeomindex(featuredefn::AbstractFeatureDefn, name::AbstractString = "")::Integer return GDAL.ogr_fd_getgeomfieldindex(featuredefn.ptr, name) end @@ -312,9 +297,9 @@ This method should only be called while there are no OGRFeature objects in existence based on this OGRFeatureDefn. """ function addgeomdefn!( - featuredefn::FeatureDefn, - geomfielddefn::AbstractGeomFieldDefn - )::FeatureDefn + featuredefn::FeatureDefn, + geomfielddefn::AbstractGeomFieldDefn, +)::FeatureDefn # `geomfielddefn` is copied, and remains the responsibility of the caller. GDAL.ogr_fd_addgeomfielddefn(featuredefn.ptr, geomfielddefn.ptr) return featuredefn @@ -342,10 +327,7 @@ end Test if the feature definition is identical to the other one. """ -function issame( - featuredefn1::AbstractFeatureDefn, - featuredefn2::AbstractFeatureDefn - )::Bool +function issame(featuredefn1::AbstractFeatureDefn, featuredefn2::AbstractFeatureDefn)::Bool return Bool(GDAL.ogr_fd_issame(featuredefn1.ptr, featuredefn2.ptr)) end diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index c75d4dd0..139892e6 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -27,29 +27,29 @@ This function attempts to create a new layer on the dataset with the indicated * `options`: a StringList of name=value (driver-specific) options. """ function createlayer(; - name::AbstractString = "", - dataset::AbstractDataset = create(getdriver("Memory")), - geom::OGRwkbGeometryType = wkbUnknown, - spatialref::AbstractSpatialRef = SpatialRef(), - options = StringList(C_NULL) - )::IFeatureLayer + name::AbstractString = "", + dataset::AbstractDataset = create(getdriver("Memory")), + geom::OGRwkbGeometryType = wkbUnknown, + spatialref::AbstractSpatialRef = SpatialRef(), + options = StringList(C_NULL), +)::IFeatureLayer return IFeatureLayer( - GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, - options), + GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, options), ownedby = dataset, - spatialref = spatialref + spatialref = spatialref, ) end function unsafe_createlayer(; - name::AbstractString = "", - dataset::AbstractDataset = create(getdriver("Memory")), - geom::OGRwkbGeometryType = wkbUnknown, - spatialref::AbstractSpatialRef = SpatialRef(), - options = StringList(C_NULL) - )::FeatureLayer - return FeatureLayer(GDAL.gdaldatasetcreatelayer(dataset.ptr, name, - spatialref.ptr, geom, options)) + name::AbstractString = "", + dataset::AbstractDataset = create(getdriver("Memory")), + geom::OGRwkbGeometryType = wkbUnknown, + spatialref::AbstractSpatialRef = SpatialRef(), + options = StringList(C_NULL), +)::FeatureLayer + return FeatureLayer( + GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, options), + ) end """ @@ -69,25 +69,24 @@ layer, and then duplicates each feature of the source layer. * `options`: a StringList of name=value (driver-specific) options. """ function copy( - layer::AbstractFeatureLayer; - dataset::AbstractDataset = create(getdriver("Memory")), - name::AbstractString = "copy($(getname(layer)))", - options = StringList(C_NULL) - )::IFeatureLayer + layer::AbstractFeatureLayer; + dataset::AbstractDataset = create(getdriver("Memory")), + name::AbstractString = "copy($(getname(layer)))", + options = StringList(C_NULL), +)::IFeatureLayer return IFeatureLayer( GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options), - ownedby = dataset + ownedby = dataset, ) end function unsafe_copy( - layer::AbstractFeatureLayer; - dataset::AbstractDataset = create(getdriver("Memory")), - name::AbstractString = "copy($(getname(layer)))", - options = StringList(C_NULL) - )::FeatureLayer - return FeatureLayer(GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, - options)) + layer::AbstractFeatureLayer; + dataset::AbstractDataset = create(getdriver("Memory")), + name::AbstractString = "copy($(getname(layer)))", + options = StringList(C_NULL), +)::FeatureLayer + return FeatureLayer(GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options)) end """ @@ -177,19 +176,14 @@ In the future this may be generalized. Note that only the last spatial filter set is applied, even if several successive calls are done with different iGeomField values. """ -function setspatialfilter!( - layer::L, - geom::Geometry - )::L where {L <: AbstractFeatureLayer} +function setspatialfilter!(layer::L, geom::Geometry)::L where {L<:AbstractFeatureLayer} # This method makes an internal copy of `geom`. The input `geom` remains # the responsibility of the caller, and may be safely destroyed. GDAL.ogr_l_setspatialfilter(layer.ptr, geom.ptr) return layer end -function clearspatialfilter!( - layer::L - )::L where {L <: AbstractFeatureLayer} +function clearspatialfilter!(layer::L)::L where {L<:AbstractFeatureLayer} GDAL.ogr_l_setspatialfilter(layer.ptr, C_NULL) return layer end @@ -212,12 +206,12 @@ The only way to clear a spatial filter set with this method is to call `OGRLayer::SetSpatialFilter(NULL)`. """ function setspatialfilter!( - layer::L, - xmin::Real, - ymin::Real, - xmax::Real, - ymax::Real - )::L where {L <: AbstractFeatureLayer} + layer::L, + xmin::Real, + ymin::Real, + xmax::Real, + ymax::Real, +)::L where {L<:AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterrect(layer.ptr, xmin, ymin, xmax, ymax) return layer end @@ -250,20 +244,17 @@ layer (as returned by OGRLayer::GetSpatialRef()). In the future this may be generalized. """ function setspatialfilter!( - layer::L, - i::Integer, - geom::AbstractGeometry - )::L where {L <: AbstractFeatureLayer} + layer::L, + i::Integer, + geom::AbstractGeometry, +)::L where {L<:AbstractFeatureLayer} # This method makes an internal copy of `geom`. The input `geom` remains # the responsibility of the caller, and may be safely destroyed. GDAL.ogr_l_setspatialfilterex(layer.ptr, i, geom.ptr) return layer end -function clearspatialfilter!( - layer::L, - i::Integer - )::L where {L <: AbstractFeatureLayer} +function clearspatialfilter!(layer::L, i::Integer)::L where {L<:AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterex(layer.ptr, i, C_NULL) return layer end @@ -283,13 +274,13 @@ Set a new rectangular spatial filter. * `ymax`: the maximum Y coordinate for the rectangular region. """ function setspatialfilter!( - layer::L, - i::Integer, - xmin::Real, - ymin::Real, - xmax::Real, - ymax::Real - )::L where {L <: AbstractFeatureLayer} + layer::L, + i::Integer, + xmin::Real, + ymin::Real, + xmax::Real, + ymax::Real, +)::L where {L<:AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterrectex(layer.ptr, i, xmin, ymin, xmax, ymax) return layer end @@ -320,16 +311,16 @@ Note that installing a query string will generally result in resetting the current reading position (ala `resetreading!()`). """ function setattributefilter!( - layer::L, - query::AbstractString - )::L where {L <: AbstractFeatureLayer} + layer::L, + query::AbstractString, +)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_setattributefilter(layer.ptr, query) @ogrerr result """Failed to set a new attribute query. The query expression might be in error.""" return layer end -function clearattributefilter!(layer::L)::L where {L <: AbstractFeatureLayer} +function clearattributefilter!(layer::L)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_setattributefilter(layer.ptr, C_NULL) @ogrerr result "OGRErr $result: Failed to clear attribute query." return layer @@ -342,7 +333,7 @@ Reset feature reading to start on the first feature. This affects `nextfeature()`. """ -function resetreading!(layer::L)::L where {L <: AbstractFeatureLayer} +function resetreading!(layer::L)::L where {L<:AbstractFeatureLayer} GDAL.ogr_l_resetreading(layer.ptr) return layer end @@ -401,10 +392,7 @@ then calls `nextfeature()` `i` times is used. To determine if fast seeking is available on the layer, use the `testcapability()` method with a value of `OLCFastSetNextByIndex`. """ -function setnextbyindex!( - layer::L, - i::Integer - )::L where {L <: AbstractFeatureLayer} +function setnextbyindex!(layer::L, i::Integer)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_setnextbyindex(layer.ptr, i) @ogrerr result "Failed to move the cursor to index $i" return layer @@ -474,16 +462,13 @@ OGRNullFID, then the native implementation may use that as the feature id of the new feature, but not necessarily. Upon successful return the passed feature will have been updated with the new feature id. """ -function addfeature!( - layer::L, - feature::Feature - )::L where {L <: AbstractFeatureLayer} +function addfeature!(layer::L, feature::Feature)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_createfeature(layer.ptr, feature.ptr) @ogrerr result "Failed to create and write feature in layer." return layer end -function addfeature(f::Function, layer::L)::L where {L <: AbstractFeatureLayer} +function addfeature(f::Function, layer::L)::L where {L<:AbstractFeatureLayer} feature = unsafe_createfeature(layer) return try f(feature) @@ -504,10 +489,7 @@ the layer by one), but the feature has not been written to the layer yet. unsafe_createfeature(layer::AbstractFeatureLayer)::Feature = unsafe_createfeature(layerdefn(layer)) -function createfeature( - f::Function, - layer::L - )::L where {L <: AbstractFeatureLayer} +function createfeature(f::Function, layer::L)::L where {L<:AbstractFeatureLayer} feature = unsafe_createfeature(layer) return try f(feature) @@ -528,10 +510,7 @@ by the driver. Most drivers do not support feature deletion, and will return OGRERR_UNSUPPORTED_OPERATION. The OGR_L_TestCapability() function may be called with OLCDeleteFeature to check if the driver supports feature deletion. """ -function deletefeature!( - layer::L, - i::Integer - )::L where {L <: AbstractFeatureLayer} +function deletefeature!(layer::L, i::Integer)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_deletefeature(layer.ptr, i) # OGRERR_NONE if the operation works, otherwise an appropriate error code # (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist). @@ -561,10 +540,10 @@ the driver might apply some changes to make it match, like those it might do if the layer was created (eg. like `LAUNDER` in the OCI driver). """ function findfieldindex( - layer::AbstractFeatureLayer, - field::Union{AbstractString, Symbol}, - exactmatch::Bool - )::Integer + layer::AbstractFeatureLayer, + field::Union{AbstractString,Symbol}, + exactmatch::Bool, +)::Integer return GDAL.ogr_l_findfieldindex(layer.ptr, field, exactmatch) end @@ -625,20 +604,17 @@ Note that some implementations of this method may alter the read cursor of the layer. """ function envelope( - layer::AbstractFeatureLayer, - i::Integer, - force::Bool = false - )::GDAL.OGREnvelope + layer::AbstractFeatureLayer, + i::Integer, + force::Bool = false, +)::GDAL.OGREnvelope envelope = Ref{GDAL.OGREnvelope}(GDAL.OGREnvelope(0, 0, 0, 0)) result = GDAL.ogr_l_getextentex(layer.ptr, i, envelope, force) @ogrerr result "Extent not known" return envelope[] end -function envelope( - layer::AbstractFeatureLayer, - force::Bool = false - )::GDAL.OGREnvelope +function envelope(layer::AbstractFeatureLayer, force::Bool = false)::GDAL.OGREnvelope envelope = Ref{GDAL.OGREnvelope}(GDAL.OGREnvelope(0, 0, 0, 0)) result = GDAL.ogr_l_getextent(layer.ptr, envelope, force) @ogrerr result "Extent not known" @@ -736,29 +712,29 @@ testcapability(layer::AbstractFeatureLayer, capability::AbstractString)::Bool = Bool(GDAL.ogr_l_testcapability(layer.ptr, capability)) function listcapability( - layer::AbstractFeatureLayer, - capabilities = (GDAL.OLCRandomRead, - GDAL.OLCSequentialWrite, - GDAL.OLCRandomWrite, - GDAL.OLCFastSpatialFilter, - GDAL.OLCFastFeatureCount, - GDAL.OLCFastGetExtent, - GDAL.OLCCreateField, - GDAL.OLCDeleteField, - GDAL.OLCReorderFields, - GDAL.OLCAlterFieldDefn, - GDAL.OLCTransactions, - GDAL.OLCDeleteFeature, - GDAL.OLCFastSetNextByIndex, - GDAL.OLCStringsAsUTF8, - GDAL.OLCIgnoreFields, - GDAL.OLCCreateGeomField, - GDAL.OLCCurveGeometries, - GDAL.OLCMeasuredGeometries) - )::Dict{String, Bool} - return Dict{String, Bool}([ - c => testcapability(layer,c) for c in capabilities - ]) + layer::AbstractFeatureLayer, + capabilities = ( + GDAL.OLCRandomRead, + GDAL.OLCSequentialWrite, + GDAL.OLCRandomWrite, + GDAL.OLCFastSpatialFilter, + GDAL.OLCFastFeatureCount, + GDAL.OLCFastGetExtent, + GDAL.OLCCreateField, + GDAL.OLCDeleteField, + GDAL.OLCReorderFields, + GDAL.OLCAlterFieldDefn, + GDAL.OLCTransactions, + GDAL.OLCDeleteFeature, + GDAL.OLCFastSetNextByIndex, + GDAL.OLCStringsAsUTF8, + GDAL.OLCIgnoreFields, + GDAL.OLCCreateGeomField, + GDAL.OLCCurveGeometries, + GDAL.OLCMeasuredGeometries, + ), +)::Dict{String,Bool} + return Dict{String,Bool}([c => testcapability(layer, c) for c in capabilities]) end # TODO use syntax below once v0.4 support is dropped (not in Compat.jl) @@ -804,10 +780,10 @@ fields with not-null constraints, this is generally before creating any feature to the layer. """ function addfielddefn!( - layer::L, - field::AbstractFieldDefn, - approx::Bool = false - )::L where {L <: AbstractFeatureLayer} + layer::L, + field::AbstractFieldDefn, + approx::Bool = false, +)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_createfield(layer.ptr, field.ptr, approx) @ogrerr result "Failed to create new field" return layer @@ -844,10 +820,10 @@ fields with not-null constraints, this is generally before creating any feature to the layer. """ function addgeomdefn!( - layer::L, - field::AbstractGeomFieldDefn, - approx::Bool = false - )::L where {L <: AbstractFeatureLayer} + layer::L, + field::AbstractGeomFieldDefn, + approx::Bool = false, +)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_creategeomfield(layer.ptr, field.ptr, approx) # OGRERR_NONE on success. @ogrerr result "Failed to create new geometry field" @@ -1033,8 +1009,7 @@ Increment layer reference count. ### Returns The reference count after incrementing. """ -reference(layer::AbstractFeatureLayer)::Integer = - GDAL.ogr_l_reference(layer.ptr) +reference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_reference(layer.ptr) """ dereference(layer::AbstractFeatureLayer) @@ -1044,16 +1019,14 @@ Decrement layer reference count. ### Returns The reference count after decrementing. """ -dereference(layer::AbstractFeatureLayer)::Integer = - GDAL.ogr_l_dereference(layer.ptr) +dereference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_dereference(layer.ptr) """ nreference(layer::AbstractFeatureLayer) The current reference count for the layer object itself. """ -nreference(layer::AbstractFeatureLayer)::Integer = - GDAL.ogr_l_getrefcount(layer.ptr) +nreference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_getrefcount(layer.ptr) # """ # Flush pending changes to disk. @@ -1091,8 +1064,7 @@ nreference(layer::AbstractFeatureLayer)::Integer = The name of the FID column in the database, or \"\" if not supported. """ -fidcolumnname(layer::AbstractFeatureLayer)::String = - GDAL.ogr_l_getfidcolumn(layer.ptr) +fidcolumnname(layer::AbstractFeatureLayer)::String = GDAL.ogr_l_getfidcolumn(layer.ptr) """ geomcolumnname(layer::AbstractFeatureLayer) @@ -1122,10 +1094,7 @@ Besides field names of the layers, the following special fields can be passed: By default, no fields are ignored. """ -function setignoredfields!( - layer::L, - fieldnames - )::L where {L <: AbstractFeatureLayer} +function setignoredfields!(layer::L, fieldnames)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_setignoredfields(layer.ptr, fieldnames) # OGRERR_NONE if all field names have been resolved (even if the driver # does not support this method) diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index 08edd413..30b71279 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -27,12 +27,10 @@ function setname!(fielddefn::FieldDefn, name::AbstractString)::FieldDefn end "Fetch the name of this field." -getname(fielddefn::AbstractFieldDefn)::String = - GDAL.ogr_fld_getnameref(fielddefn.ptr) +getname(fielddefn::AbstractFieldDefn)::String = GDAL.ogr_fld_getnameref(fielddefn.ptr) "Fetch the type of this field." -gettype(fielddefn::AbstractFieldDefn)::OGRFieldType = - GDAL.ogr_fld_gettype(fielddefn.ptr) +gettype(fielddefn::AbstractFieldDefn)::OGRFieldType = GDAL.ogr_fld_gettype(fielddefn.ptr) "Set the type of this field." function settype!(fielddefn::FieldDefn, etype::OGRFieldType)::FieldDefn @@ -66,10 +64,7 @@ OGRFeatureDefn. * `fielddefn`: handle to the field definition to set type to. * `subtype`: the new field subtype. """ -function setsubtype!( - fielddefn::FieldDefn, - subtype::OGRFieldSubType - )::FieldDefn +function setsubtype!(fielddefn::FieldDefn, subtype::OGRFieldSubType)::FieldDefn GDAL.ogr_fld_setsubtype(fielddefn.ptr, subtype) return fielddefn end @@ -91,10 +86,7 @@ Set the justification for this field. Note: no driver is know to use the concept of field justification. """ -function setjustify!( - fielddefn::FieldDefn, - ejustify::OGRJustification - )::FieldDefn +function setjustify!(fielddefn::FieldDefn, ejustify::OGRJustification)::FieldDefn GDAL.ogr_fld_setjustify(fielddefn.ptr, ejustify) return fielddefn end @@ -107,8 +99,7 @@ Get the formatting width for this field. ### Returns the width, zero means no specified width. """ -getwidth(fielddefn::AbstractFieldDefn)::Integer = - GDAL.ogr_fld_getwidth(fielddefn.ptr) +getwidth(fielddefn::AbstractFieldDefn)::Integer = GDAL.ogr_fld_getwidth(fielddefn.ptr) """ setwidth!(fielddefn::FieldDefn, width::Integer) @@ -159,13 +150,13 @@ Set defining parameters for a field in one call. * `justify`: the formatting justification ([OJUndefined], OJLeft or OJRight) """ function setparams!( - fielddefn::FieldDefn, - name::AbstractString, - etype::OGRFieldType; - nwidth::Integer = 0, - nprecision::Integer = 0, - justify::OGRJustification = OJUndefined - )::FieldDefn + fielddefn::FieldDefn, + name::AbstractString, + etype::OGRFieldType; + nwidth::Integer = 0, + nprecision::Integer = 0, + justify::OGRJustification = OJUndefined, +)::FieldDefn GDAL.ogr_fld_set(fielddefn.ptr, name, etype, nwidth, nprecision, justify) return fielddefn end @@ -175,8 +166,7 @@ end Return whether this field should be omitted when fetching features. """ -isignored(fielddefn::AbstractFieldDefn)::Bool = - Bool(GDAL.ogr_fld_isignored(fielddefn.ptr)) +isignored(fielddefn::AbstractFieldDefn)::Bool = Bool(GDAL.ogr_fld_isignored(fielddefn.ptr)) """ setignored!(fielddefn::FieldDefn, ignore::Bool) @@ -255,7 +245,7 @@ datetime literal value, format should be 'YYYY/MM/DD HH:MM:SS[.sss]' Drivers that support writing DEFAULT clauses will advertize the GDAL_DCAP_DEFAULT_FIELDS driver metadata item. """ -function setdefault!(fielddefn::T, default)::T where {T <: AbstractFieldDefn} +function setdefault!(fielddefn::T, default)::T where {T<:AbstractFieldDefn} GDAL.ogr_fld_setdefault(fielddefn.ptr, default) return fielddefn end @@ -278,9 +268,9 @@ isdefaultdriverspecific(fielddefn::AbstractFieldDefn)::Bool = Create a new field geometry definition. """ function unsafe_creategeomdefn( - name::AbstractString, - etype::OGRwkbGeometryType - )::GeomFieldDefn + name::AbstractString, + etype::OGRwkbGeometryType, +)::GeomFieldDefn return GeomFieldDefn(GDAL.ogr_gfld_create(name, etype)) end @@ -305,18 +295,14 @@ function setname!(geomdefn::GeomFieldDefn, name::AbstractString)::GeomFieldDefn end "Fetch name of this field." -getname(geomdefn::AbstractGeomFieldDefn)::String = - GDAL.ogr_gfld_getnameref(geomdefn.ptr) +getname(geomdefn::AbstractGeomFieldDefn)::String = GDAL.ogr_gfld_getnameref(geomdefn.ptr) "Fetch geometry type of this field." gettype(geomdefn::AbstractGeomFieldDefn)::OGRwkbGeometryType = GDAL.ogr_gfld_gettype(geomdefn.ptr) "Set the geometry type of this field." -function settype!( - geomdefn::GeomFieldDefn, - etype::OGRwkbGeometryType - )::GeomFieldDefn +function settype!(geomdefn::GeomFieldDefn, etype::OGRwkbGeometryType)::GeomFieldDefn GDAL.ogr_gfld_settype(geomdefn.ptr, etype) return geomdefn end @@ -357,9 +343,9 @@ This function drops the reference of the previously set SRS object and acquires a new reference on the passed object (if non-NULL). """ function setspatialref!( - geomdefn::GeomFieldDefn, - spatialref::AbstractSpatialRef - )::GeomFieldDefn + geomdefn::GeomFieldDefn, + spatialref::AbstractSpatialRef, +)::GeomFieldDefn clonespatialref = clone(spatialref) GDAL.ogr_gfld_setspatialref(geomdefn.ptr, clonespatialref.ptr) geomdefn.spatialref = clonespatialref diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 5b755707..4ee4487e 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -10,7 +10,8 @@ binary (WKB) representation. """ function fromWKB(data)::IGeometry geom = Ref{GDAL.OGRGeometryH}() - result = @gdal(OGR_G_CreateFromWkb::GDAL.OGRErr, + result = @gdal( + OGR_G_CreateFromWkb::GDAL.OGRErr, data::Ptr{Cuchar}, C_NULL::GDAL.OGRSpatialReferenceH, geom::Ptr{GDAL.OGRGeometryH}, @@ -22,7 +23,8 @@ end function unsafe_fromWKB(data)::Geometry geom = Ref{GDAL.OGRGeometryH}() - result = @gdal(OGR_G_CreateFromWkb::GDAL.OGRErr, + result = @gdal( + OGR_G_CreateFromWkb::GDAL.OGRErr, data::Ptr{Cuchar}, C_NULL::GDAL.OGRSpatialReferenceH, geom::Ptr{GDAL.OGRGeometryH}, @@ -45,7 +47,8 @@ Create a geometry object of the appropriate type from its well known text """ function fromWKT(data::Vector{String})::IGeometry geom = Ref{GDAL.OGRGeometryH}() - result = @gdal(OGR_G_CreateFromWkt::GDAL.OGRErr, + result = @gdal( + OGR_G_CreateFromWkt::GDAL.OGRErr, data::StringList, C_NULL::GDAL.OGRSpatialReferenceH, geom::Ptr{GDAL.OGRGeometryH} @@ -56,7 +59,8 @@ end function unsafe_fromWKT(data::Vector{String})::Geometry geom = Ref{GDAL.OGRGeometryH}() - result = @gdal(OGR_G_CreateFromWkt::GDAL.OGRErr, + result = @gdal( + OGR_G_CreateFromWkt::GDAL.OGRErr, data::StringList, C_NULL::GDAL.OGRSpatialReferenceH, geom::Ptr{GDAL.OGRGeometryH} @@ -67,8 +71,7 @@ end fromWKT(data::String, args...)::IGeometry = fromWKT([data], args...) -unsafe_fromWKT(data::String, args...)::Geometry = - unsafe_fromWKT([data], args...) +unsafe_fromWKT(data::String, args...)::Geometry = unsafe_fromWKT([data], args...) """ Destroy geometry object. @@ -138,21 +141,19 @@ For that, OGRGeometry::getCurveGeometry() can be used. The passed in geometry is cloned and a new one returned. """ function forceto( - geom::AbstractGeometry, - targettype::OGRwkbGeometryType, - options = StringList(C_NULL) - )::IGeometry - return IGeometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, - options)) + geom::AbstractGeometry, + targettype::OGRwkbGeometryType, + options = StringList(C_NULL), +)::IGeometry + return IGeometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options)) end function unsafe_forceto( - geom::AbstractGeometry, - targettype::OGRwkbGeometryType, - options = StringList(C_NULL) - )::Geometry - return Geometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, - options)) + geom::AbstractGeometry, + targettype::OGRwkbGeometryType, + options = StringList(C_NULL), +)::Geometry + return Geometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options)) end """ @@ -174,8 +175,7 @@ Get the dimension of the coordinates in this geometry. ### Returns This will return 2 or 3. """ -getcoorddim(geom::AbstractGeometry)::Integer = - GDAL.ogr_g_getcoordinatedimension(geom.ptr) +getcoorddim(geom::AbstractGeometry)::Integer = GDAL.ogr_g_getcoordinatedimension(geom.ptr) """ setcoorddim!(geom::AbstractGeometry, dim::Integer) @@ -188,8 +188,8 @@ dimension of a geometry collection, a compound curve, a polygon, etc. will affect the children geometries. This will also remove the M dimension if present before this call. """ -function setcoorddim!(geom::G, dim::Integer)::G where {G <: AbstractGeometry} - GDAL.ogr_g_setcoordinatedimension(geom.ptr ,dim) +function setcoorddim!(geom::G, dim::Integer)::G where {G<:AbstractGeometry} + GDAL.ogr_g_setcoordinatedimension(geom.ptr, dim) return geom end @@ -226,7 +226,11 @@ function boundingbox(geom::AbstractGeometry)::IGeometry MinY, MaxY = coordinates.MinY, coordinates.MaxY # creates a CW closed ring polygon return createpolygon([ - [MaxY, MinX], [MaxY, MaxX], [MinY, MaxX], [MinY, MinX], [MaxY, MinX] + [MaxY, MinX], + [MaxY, MaxX], + [MinY, MaxX], + [MinY, MinX], + [MaxY, MinX], ]) end @@ -239,10 +243,7 @@ Convert a geometry well known binary format. * `geom`: handle on the geometry to convert to a well know binary data from. * `order`: One of wkbXDR or [wkbNDR] indicating MSB or LSB byte order resp. """ -function toWKB( - geom::AbstractGeometry, - order::OGRwkbByteOrder = wkbNDR - )::Vector{Cuchar} +function toWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = wkbNDR)::Vector{Cuchar} buffer = Vector{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttowkb(geom.ptr, order, buffer) @ogrerr result "Failed to export geometry to WKB" @@ -258,10 +259,7 @@ Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. * `geom`: handle on the geometry to convert to a well know binary data from. * `order`: One of wkbXDR or [wkbNDR] indicating MSB or LSB byte order resp. """ -function toISOWKB( - geom::AbstractGeometry, - order::OGRwkbByteOrder = wkbNDR - )::Vector{Cuchar} +function toISOWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = wkbNDR)::Vector{Cuchar} buffer = Array{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttoisowkb(geom.ptr, order, buffer) @ogrerr result "Failed to export geometry to ISO WKB" @@ -323,7 +321,7 @@ geomname(geom::AbstractGeometry)::String = GDAL.ogr_g_getgeometryname(geom.ptr) Convert geometry to strictly 2D. """ -function flattento2d!(geom::G)::G where {G <: AbstractGeometry} +function flattento2d!(geom::G)::G where {G<:AbstractGeometry} GDAL.ogr_g_flattento2d(geom.ptr) return geom end @@ -336,7 +334,7 @@ Force rings to be closed. If this geometry, or any contained geometries has polygon rings that are not closed, they will be closed by adding the starting point at the end. """ -function closerings!(geom::G)::G where {G <: AbstractGeometry} +function closerings!(geom::G)::G where {G<:AbstractGeometry} GDAL.ogr_g_closerings(geom.ptr) return geom end @@ -394,7 +392,7 @@ Convert a geometry into GeoJSON format. A GeoJSON fragment or NULL in case of error. """ toJSON(geom::AbstractGeometry; kwargs...)::String = - GDAL.ogr_g_exporttojsonex(geom.ptr, String["$k=$v" for (k,v) in kwargs]) + GDAL.ogr_g_exporttojsonex(geom.ptr, String["$k=$v" for (k, v) in kwargs]) toJSON(geom::AbstractGeometry, options::Vector{String})::String = GDAL.ogr_g_exporttojsonex(geom.ptr, options) @@ -404,11 +402,9 @@ toJSON(geom::AbstractGeometry, options::Vector{String})::String = Create a geometry object from its GeoJSON representation. """ -fromJSON(data::String)::IGeometry = - IGeometry(GDAL.ogr_g_creategeometryfromjson(data)) +fromJSON(data::String)::IGeometry = IGeometry(GDAL.ogr_g_creategeometryfromjson(data)) -unsafe_fromJSON(data::String)::Geometry = - Geometry(GDAL.ogr_g_creategeometryfromjson(data)) +unsafe_fromJSON(data::String)::Geometry = Geometry(GDAL.ogr_g_creategeometryfromjson(data)) # """ # Assign spatial reference to this object. @@ -469,10 +465,7 @@ Apply arbitrary coordinate transformation to geometry. * `geom`: handle on the geometry to apply the transform to. * `coordtransform`: handle on the transformation to apply. """ -function transform!( - geom::G, - coordtransform::CoordTransform - )::G where {G <: AbstractGeometry} +function transform!(geom::G, coordtransform::CoordTransform)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_transform(geom.ptr, coordtransform.ptr) @ogrerr result "Failed to transform geometry" return geom @@ -549,18 +542,18 @@ Return a Delaunay triangulation of the vertices of the geometry. will return a GEOMETRYCOLLECTION containing triangular POLYGONs. """ function delaunaytriangulation( - geom::AbstractGeometry, - tol::Real, - onlyedges::Bool - )::IGeometry + geom::AbstractGeometry, + tol::Real, + onlyedges::Bool, +)::IGeometry return IGeometry(GDAL.ogr_g_delaunaytriangulation(geom.ptr, tol, onlyedges)) end function unsafe_delaunaytriangulation( - geom::AbstractGeometry, - tol::Real, - onlyedges::Bool - )::Geometry + geom::AbstractGeometry, + tol::Real, + onlyedges::Bool, +)::Geometry return Geometry(GDAL.ogr_g_delaunaytriangulation(geom.ptr, tol, onlyedges)) end @@ -576,7 +569,7 @@ computation is performed in 2d only * `geom`: the geometry to segmentize * `maxlength`: the maximum distance between 2 points after segmentization """ -function segmentize!(geom::G, maxlength::Real)::G where {G <: AbstractGeometry} +function segmentize!(geom::G, maxlength::Real)::G where {G<:AbstractGeometry} GDAL.ogr_g_segmentize(geom.ptr, maxlength) return geom end @@ -657,11 +650,9 @@ Returns the boundary of the geometry. A new geometry object is created and returned containing the boundary of the geometry on which the method is invoked. """ -boundary(geom::AbstractGeometry)::IGeometry = - IGeometry(GDAL.ogr_g_boundary(geom.ptr)) +boundary(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_boundary(geom.ptr)) -unsafe_boundary(geom::AbstractGeometry)::Geometry = - Geometry(GDAL.ogr_g_boundary(geom.ptr)) +unsafe_boundary(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_boundary(geom.ptr)) """ convexhull(geom::AbstractGeometry) @@ -671,8 +662,7 @@ Returns the convex hull of the geometry. A new geometry object is created and returned containing the convex hull of the geometry on which the method is invoked. """ -convexhull(geom::AbstractGeometry)::IGeometry = - IGeometry(GDAL.ogr_g_convexhull(geom.ptr)) +convexhull(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_convexhull(geom.ptr)) unsafe_convexhull(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_convexhull(geom.ptr)) @@ -703,11 +693,7 @@ accuracy of the result. buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30)::IGeometry = IGeometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) -function unsafe_buffer( - geom::AbstractGeometry, - dist::Real, - quadsegs::Integer = 30 - )::Geometry +function unsafe_buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30)::Geometry return Geometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) end @@ -818,10 +804,7 @@ multipoint, linestring, geometrycollection such as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces (polygons). SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons). """ -function centroid!( - geom::AbstractGeometry, - centroid::G - )::G where {G <: AbstractGeometry} +function centroid!(geom::AbstractGeometry, centroid::G)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_centroid(geom.ptr, centroid.ptr) @ogrerr result "Failed to compute the geometry centroid" return centroid @@ -879,7 +862,7 @@ Clear geometry information. This restores the geometry to its initial state after construction, and before assignment of actual geometry. """ -function empty!(geom::G)::G where {G <: AbstractGeometry} +function empty!(geom::G)::G where {G<:AbstractGeometry} GDAL.ogr_g_empty(geom.ptr) return geom end @@ -922,8 +905,7 @@ reassembled Polygons: NULL will be returned if the input collection doesn't correspond to a MultiLinestring, or when reassembling Edges into Polygons is impossible due to topological inconsistencies. """ -polygonize(geom::AbstractGeometry)::IGeometry = - IGeometry(GDAL.ogr_g_polygonize(geom.ptr)) +polygonize(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_polygonize(geom.ptr)) unsafe_polygonize(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_polygonize(geom.ptr)) @@ -988,7 +970,7 @@ Fetch a point in line string or a point geometry, at index i. ### Parameters * `i`: the vertex to fetch, from 0 to getNumPoints()-1, zero for a point. """ -getpoint(geom::AbstractGeometry, i::Integer)::Tuple{Float64, Float64, Float64} = +getpoint(geom::AbstractGeometry, i::Integer)::Tuple{Float64,Float64,Float64} = getpoint!(geom, i, Ref{Float64}(), Ref{Float64}(), Ref{Float64}()) function getpoint!(geom::AbstractGeometry, i::Integer, x, y, z) @@ -1005,7 +987,7 @@ Set number of points in a geometry. * `geom`: the geometry. * `n`: the new number of points for geometry. """ -function setpointcount!(geom::G, n::Integer)::G where {G <: AbstractGeometry} +function setpointcount!(geom::G, n::Integer)::G where {G<:AbstractGeometry} GDAL.ogr_g_setpointcount(geom.ptr, n) return geom end @@ -1026,22 +1008,17 @@ Set the location of a vertex in a point or linestring geometry. function setpoint! end function setpoint!( - geom::G, - i::Integer, - x::Real, - y::Real, - z::Real - )::G where {G <: AbstractGeometry} + geom::G, + i::Integer, + x::Real, + y::Real, + z::Real, +)::G where {G<:AbstractGeometry} GDAL.ogr_g_setpoint(geom.ptr, i, x, y, z) return geom end -function setpoint!( - geom::G, - i::Integer, - x::Real, - y::Real - )::G where {G <: AbstractGeometry} +function setpoint!(geom::G, i::Integer, x::Real, y::Real)::G where {G<:AbstractGeometry} GDAL.ogr_g_setpoint_2d(geom.ptr, i, x, y) return geom end @@ -1060,17 +1037,12 @@ Add a point to a geometry (line string or point). """ function addpoint! end -function addpoint!( - geom::G, - x::Real, - y::Real, - z::Real - )::G where {G <: AbstractGeometry} +function addpoint!(geom::G, x::Real, y::Real, z::Real)::G where {G<:AbstractGeometry} GDAL.ogr_g_addpoint(geom.ptr, x, y, z) return geom end -function addpoint!(geom::G, x::Real, y::Real)::G where {G <: AbstractGeometry} +function addpoint!(geom::G, x::Real, y::Real)::G where {G<:AbstractGeometry} GDAL.ogr_g_addpoint_2d(geom.ptr, x, y) return geom end @@ -1184,9 +1156,9 @@ interior rings. * `subgeom`: geometry to add to the existing geometry. """ function addgeom!( - geomcontainer::G, - subgeom::AbstractGeometry - )::G where {G <: AbstractGeometry} + geomcontainer::G, + subgeom::AbstractGeometry, +)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_addgeometry(geomcontainer.ptr, subgeom.ptr) @ogrerr result "Failed to add geometry. The geometry type could be illegal" return geomcontainer @@ -1230,10 +1202,10 @@ Remove a geometry from an exiting geometry container. geometries in it. """ function removegeom!( - geom::G, - i::Integer, - todelete::Bool = true - )::G where {G <: AbstractGeometry} + geom::G, + i::Integer, + todelete::Bool = true, +)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_removegeometry(geom.ptr, i, todelete) @ogrerr result "Failed to remove geometry. The index could be out of range." return geom @@ -1250,10 +1222,7 @@ Remove all geometries from an exiting geometry container. The default is `true` as the existing geometry is considered to own the geometries in it. """ -function removeallgeoms!( - geom::G, - todelete::Bool = true - )::G where {G <: AbstractGeometry} +function removeallgeoms!(geom::G, todelete::Bool = true)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_removegeometry(geom.ptr, -1, todelete) @ogrerr result "Failed to remove all geometries." return geom @@ -1288,43 +1257,27 @@ MULTICURVE or MULTISURFACE in it, by approximating curve geometries. See OGRGeometryFactory::curveToLineString() for valid options. """ -function lineargeom( - geom::AbstractGeometry, - stepsize::Real = 0; - kwargs... - )::IGeometry - return lineargeom( - geom, - String["$k=$v" for (k, v) in kwargs], - stepsize - ) +function lineargeom(geom::AbstractGeometry, stepsize::Real = 0; kwargs...)::IGeometry + return lineargeom(geom, String["$k=$v" for (k, v) in kwargs], stepsize) end -function unsafe_lineargeom( - geom::AbstractGeometry, - stepsize::Real = 0; - kwargs... - )::Geometry - return unsafe_lineargeom( - geom, - String["$k=$v" for (k, v) in kwargs], - stepsize - ) +function unsafe_lineargeom(geom::AbstractGeometry, stepsize::Real = 0; kwargs...)::Geometry + return unsafe_lineargeom(geom, String["$k=$v" for (k, v) in kwargs], stepsize) end function lineargeom( - geom::AbstractGeometry, - options::Vector{String}, - stepsize::Real = 0 - )::IGeometry + geom::AbstractGeometry, + options::Vector{String}, + stepsize::Real = 0, +)::IGeometry return IGeometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) end function unsafe_lineargeom( - geom::AbstractGeometry, - options::Vector{String}, - stepsize::Real = 0 - )::Geometry + geom::AbstractGeometry, + options::Vector{String}, + stepsize::Real = 0, +)::Geometry return Geometry(GDAL.ogr_g_getlineargeometry(geom.ptr, stepsize, options)) end @@ -1364,27 +1317,25 @@ Build a ring from a bunch of arcs. points of the ring are the same. (defaults to `false`) """ function polygonfromedges( - lines::AbstractGeometry, - tol::Real; - besteffort::Bool = false, - autoclose::Bool = false - )::IGeometry + lines::AbstractGeometry, + tol::Real; + besteffort::Bool = false, + autoclose::Bool = false, +)::IGeometry perr = Ref{GDAL.OGRErr}() - result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, - tol, perr) + result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, tol, perr) @ogrerr perr[] "Failed to build polygon from edges." return IGeometry(result) end function unsafe_polygonfromedges( - lines::AbstractGeometry, - tol::Real; - besteffort::Bool = false, - autoclose::Bool = false - )::Geometry + lines::AbstractGeometry, + tol::Real; + besteffort::Bool = false, + autoclose::Bool = false, +)::Geometry perr = Ref{GDAL.OGRErr}() - result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, - tol, perr) + result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, tol, perr) @ogrerr perr[] "Failed to build polygon from edges." return Geometry(result) end @@ -1425,27 +1376,28 @@ Get flag to enable/disable returning non-linear geometries in the C API. """ getnonlineargeomflag()::Bool = Bool(GDAL.ogrgetnonlineargeometriesenabledflag()) -for (geom, wkbgeom) in ((:geomcollection, wkbGeometryCollection), - (:linestring, wkbLineString), - (:linearring, wkbLinearRing), - (:multilinestring, wkbMultiLineString), - (:multipoint, wkbMultiPoint), - (:multipolygon, wkbMultiPolygon), - (:multipolygon_noholes, wkbMultiPolygon), - (:point, wkbPoint), - (:polygon, wkbPolygon)) +for (geom, wkbgeom) in ( + (:geomcollection, wkbGeometryCollection), + (:linestring, wkbLineString), + (:linearring, wkbLinearRing), + (:multilinestring, wkbMultiLineString), + (:multipoint, wkbMultiPoint), + (:multipolygon, wkbMultiPolygon), + (:multipolygon_noholes, wkbMultiPolygon), + (:point, wkbPoint), + (:polygon, wkbPolygon), +) eval(quote $(Symbol("create$geom"))()::IGeometry = creategeom($wkbgeom) - $(Symbol("unsafe_create$geom"))()::Geometry = - unsafe_creategeom($wkbgeom) + $(Symbol("unsafe_create$geom"))()::Geometry = unsafe_creategeom($wkbgeom) end) end for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) for (args, typedargs) in ( - ((:x,:y), (:(x::Real),:(y::Real))), - ((:x,:y,:z), (:(x::Real),:(y::Real),:(z::Real))) - ) + ((:x, :y), (:(x::Real), :(y::Real))), + ((:x, :y, :z), (:(x::Real), :(y::Real), :(z::Real))), + ) eval(quote function $(Symbol("$(f)point"))($(typedargs...))::$rt geom = $(Symbol("$(f)point"))() @@ -1456,12 +1408,12 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end for (args, typedargs) in ( - ((:xs,:ys), (:(xs::Vector{Cdouble}), - :(ys::Vector{Cdouble}))), - ((:xs,:ys,:zs), (:(xs::Vector{Cdouble}), - :(ys::Vector{Cdouble}), - :(zs::Vector{Cdouble}))) - ) + ((:xs, :ys), (:(xs::Vector{Cdouble}), :(ys::Vector{Cdouble}))), + ( + (:xs, :ys, :zs), + (:(xs::Vector{Cdouble}), :(ys::Vector{Cdouble}), :(zs::Vector{Cdouble})), + ), + ) for geom in (:linestring, :linearring) eval(quote function $(Symbol("$f$geom"))($(typedargs...))::$rt @@ -1474,31 +1426,25 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end) end - for (geom,component) in ((:polygon, :linearring),) + for (geom, component) in ((:polygon, :linearring),) eval(quote function $(Symbol("$f$geom"))($(typedargs...))::$rt geom = $(Symbol("$f$geom"))() subgeom = $(Symbol("unsafe_create$component"))($(args...)) - result = GDAL.ogr_g_addgeometrydirectly( - geom.ptr, - subgeom.ptr - ) + result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) @ogrerr result "Failed to add $component." return geom end end) end - for (geom,component) in ((:multipoint, :point),) + for (geom, component) in ((:multipoint, :point),) eval(quote function $(Symbol("$f$geom"))($(typedargs...))::$rt geom = $(Symbol("$f$geom"))() for pt in zip($(args...)) subgeom = $(Symbol("unsafe_create$component"))(pt) - result = GDAL.ogr_g_addgeometrydirectly( - geom.ptr, - subgeom.ptr - ) + result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) @ogrerr result "Failed to add point." end return geom @@ -1507,9 +1453,7 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end end - for typeargs in (Vector{<:Real}, - Tuple{<:Real,<:Real}, - Tuple{<:Real,<:Real,<:Real}) + for typeargs in (Vector{<:Real}, Tuple{<:Real,<:Real}, Tuple{<:Real,<:Real,<:Real}) eval(quote function $(Symbol("$(f)point"))(coords::$typeargs)::$rt geom = $(Symbol("$(f)point"))() @@ -1519,9 +1463,11 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end) end - for typeargs in (Vector{Tuple{Cdouble,Cdouble}}, - Vector{Tuple{Cdouble,Cdouble,Cdouble}}, - Vector{Vector{Cdouble}}) + for typeargs in ( + Vector{Tuple{Cdouble,Cdouble}}, + Vector{Tuple{Cdouble,Cdouble,Cdouble}}, + Vector{Vector{Cdouble}}, + ) for geom in (:linestring, :linearring) eval(quote function $(Symbol("$f$geom"))(coords::$typeargs)::$rt @@ -1534,15 +1480,12 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end) end - for (geom,component) in ((:polygon, :linearring),) + for (geom, component) in ((:polygon, :linearring),) eval(quote function $(Symbol("$f$geom"))(coords::$typeargs)::$rt geom = $(Symbol("$f$geom"))() subgeom = $(Symbol("unsafe_create$component"))(coords) - result = GDAL.ogr_g_addgeometrydirectly( - geom.ptr, - subgeom.ptr - ) + result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) @ogrerr result "Failed to add $component." return geom end @@ -1550,34 +1493,43 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end end - for (variants,typeargs) in ( - (((:multipoint, :point),), - (Vector{Tuple{Cdouble,Cdouble}}, - Vector{Tuple{Cdouble,Cdouble,Cdouble}}, - Vector{Vector{Cdouble}})), - - (((:polygon, :linearring), - (:multilinestring, :linestring), - (:multipolygon_noholes, :polygon)), - (Vector{Vector{Tuple{Cdouble,Cdouble}}}, - Vector{Vector{Tuple{Cdouble,Cdouble,Cdouble}}}, - Vector{Vector{Vector{Cdouble}}})), - - (((:multipolygon, :polygon),), - (Vector{Vector{Vector{Tuple{Cdouble,Cdouble}}}}, - Vector{Vector{Vector{Tuple{Cdouble,Cdouble,Cdouble}}}}, - Vector{Vector{Vector{Vector{Cdouble}}}})) - ) + for (variants, typeargs) in ( + ( + ((:multipoint, :point),), + ( + Vector{Tuple{Cdouble,Cdouble}}, + Vector{Tuple{Cdouble,Cdouble,Cdouble}}, + Vector{Vector{Cdouble}}, + ), + ), + ( + ( + (:polygon, :linearring), + (:multilinestring, :linestring), + (:multipolygon_noholes, :polygon), + ), + ( + Vector{Vector{Tuple{Cdouble,Cdouble}}}, + Vector{Vector{Tuple{Cdouble,Cdouble,Cdouble}}}, + Vector{Vector{Vector{Cdouble}}}, + ), + ), + ( + ((:multipolygon, :polygon),), + ( + Vector{Vector{Vector{Tuple{Cdouble,Cdouble}}}}, + Vector{Vector{Vector{Tuple{Cdouble,Cdouble,Cdouble}}}}, + Vector{Vector{Vector{Vector{Cdouble}}}}, + ), + ), + ) for typearg in typeargs, (geom, component) in variants eval(quote function $(Symbol("$f$geom"))(coords::$typearg)::$rt geom = $(Symbol("$f$geom"))() for coord in coords subgeom = $(Symbol("unsafe_create$component"))(coord) - result = GDAL.ogr_g_addgeometrydirectly( - geom.ptr, - subgeom.ptr - ) + result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) @ogrerr result "Failed to add $component." end return geom diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index bda4582f..b348727f 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -9,9 +9,7 @@ OGRStyleMgr factory. ### Returns an handle to the new style manager object. """ -function unsafe_createstylemanager( - styletable::StyleTable = StyleTable() - )::StyleManager +function unsafe_createstylemanager(styletable::StyleTable = StyleTable())::StyleManager return StyleManager(GDAL.ogr_sm_create(styletable.ptr)) end @@ -82,10 +80,10 @@ Fetch a part (style tool) from the current style. OGRStyleToolH of the requested part (style tools) or NULL on error. """ function unsafe_getpart( - stylemanager::StyleManager, - id::Integer, - stylestring = C_NULL - )::StyleTool + stylemanager::StyleManager, + id::Integer, + stylestring = C_NULL, +)::StyleTool StyleTool(GDAL.ogr_sm_getpart(stylemanager.ptr, id, stylestring)) end @@ -119,10 +117,10 @@ Add a style to the current style table. `true` on success, `false` on error. """ function addstyle!( - stylemanager::StyleManager, - stylename::AbstractString, - stylestring::AbstractString - )::Bool + stylemanager::StyleManager, + stylename::AbstractString, + stylestring::AbstractString, +)::Bool return Bool(GDAL.ogr_sm_addstyle(stylemanager.ptr, stylename, stylestring)) end @@ -168,8 +166,7 @@ Determine type of Style Tool. the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2), OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the OGRStyleToolH is invalid. """ -gettype(styletool::StyleTool)::OGRSTClassId = - GDAL.ogr_st_gettype(styletool.ptr) +gettype(styletool::StyleTool)::OGRSTClassId = GDAL.ogr_st_gettype(styletool.ptr) """ getunit(styletool::StyleTool) @@ -182,8 +179,7 @@ Get Style Tool units. ### Returns the style tool units. """ -getunit(styletool::StyleTool)::OGRSTUnitId = - GDAL.ogr_st_getunit(styletool.ptr) +getunit(styletool::StyleTool)::OGRSTUnitId = GDAL.ogr_st_getunit(styletool.ptr) """ setunit!(styletool::StyleTool, newunit::OGRSTUnitId, scale::Real) @@ -195,11 +191,7 @@ Set Style Tool units. * `newunit`: the new unit. * `scale`: ground to paper scale factor. """ -function setunit!( - styletool::StyleTool, - newunit::OGRSTUnitId, - scale::Real - )::StyleTool +function setunit!(styletool::StyleTool, newunit::OGRSTUnitId, scale::Real)::StyleTool GDAL.ogr_st_setunit(styletool.ptr, newunit, scale) return styletool end @@ -224,8 +216,7 @@ the parameter value as a string and sets `nullflag`. asstring(styletool::StyleTool, id::Integer, nullflag::Ref{Cint})::String = GDAL.ogr_st_getparamstr(styletool.ptr, id, nullflag) -asstring(styletool::StyleTool, id::Integer)::String = - asstring(styletool, id, Ref{Cint}(0)) +asstring(styletool::StyleTool, id::Integer)::String = asstring(styletool, id, Ref{Cint}(0)) """ asint(styletool::StyleTool, id::Integer, nullflag = Ref{Cint}(0)) @@ -243,11 +234,7 @@ Get Style Tool parameter value as an integer. ### Returns the parameter value as an integer and sets `nullflag`. """ -function asint( - styletool::StyleTool, - id::Integer, - nullflag::Ref{Cint} = Ref{Cint}(0) - )::Int32 +function asint(styletool::StyleTool, id::Integer, nullflag::Ref{Cint} = Ref{Cint}(0))::Int32 return GDAL.ogr_st_getparamnum(styletool.ptr, id, nullflag) end @@ -268,10 +255,10 @@ Get Style Tool parameter value as a double. the parameter value as a double and sets `nullflag`. """ function asdouble( - styletool::StyleTool, - id::Integer, - nullflag::Ref{Cint} = Ref{Cint}(0) - )::Float64 + styletool::StyleTool, + id::Integer, + nullflag::Ref{Cint} = Ref{Cint}(0), +)::Float64 return GDAL.ogr_st_getparamdbl(styletool.ptr, id, nullflag) end @@ -289,29 +276,17 @@ Set Style Tool parameter value. """ function setparam! end -function setparam!( - styletool::StyleTool, - id::Integer, - value::AbstractString - )::StyleTool +function setparam!(styletool::StyleTool, id::Integer, value::AbstractString)::StyleTool GDAL.ogr_st_setparamstr(styletool.ptr, id, value) return styletool end -function setparam!( - styletool::StyleTool, - id::Integer, - value::Integer - )::StyleTool +function setparam!(styletool::StyleTool, id::Integer, value::Integer)::StyleTool GDAL.ogr_st_setparamnum(styletool.ptr, id, value) return styletool end -function setparam!( - styletool::StyleTool, - id::Integer, - value::Float64 - )::StyleTool +function setparam!(styletool::StyleTool, id::Integer, value::Float64)::StyleTool GDAL.ogr_st_setparamdbl(styletool.ptr, id, value) return styletool end @@ -327,8 +302,7 @@ Get the style string for this Style Tool. ### Returns the style string for this style tool or "" if the styletool is invalid. """ -getstylestring(styletool::StyleTool)::String = - GDAL.ogr_st_getstylestring(styletool.ptr) +getstylestring(styletool::StyleTool)::String = GDAL.ogr_st_getstylestring(styletool.ptr) """ toRGBA(styletool::StyleTool, color::AbstractString) @@ -342,16 +316,13 @@ Return the r,g,b,a components of a color encoded in #RRGGBB[AA] format. ### Returns (R,G,B,A) tuple of Cints. """ -function toRGBA( - styletool::StyleTool, - color::AbstractString - )::Tuple{Int32, Int32, Int32, Int32} +function toRGBA(styletool::StyleTool, color::AbstractString)::Tuple{Int32,Int32,Int32,Int32} red = Ref{Int32}(0) green = Ref{Int32}(0) blue = Ref{Int32}(0) alpha = Ref{Int32}(0) - result = Bool(GDAL.ogr_st_getrgbfromstring(styletool.ptr, color, red, green, - blue, alpha)) + result = + Bool(GDAL.ogr_st_getrgbfromstring(styletool.ptr, color, red, green, blue, alpha)) result || error("Error in getting RGBA from Styletool") return (red[], green[], blue[], alpha[]) end @@ -392,10 +363,10 @@ Add a new style in the table. `true` on success, `false` on error """ function addstyle!( - styletable::StyleTable, - stylename::AbstractString, - stylestring::AbstractString - )::Bool + styletable::StyleTable, + stylename::AbstractString, + stylestring::AbstractString, +)::Bool return Bool(GDAL.ogr_stbl_addstyle(styletable.ptr, stylename, stylestring)) end @@ -468,8 +439,7 @@ Get the next style string from the table. ### Returns the next style string or NULL on error. """ -nextstyle(styletable::StyleTable)::String = - GDAL.ogr_stbl_getnextstyle(styletable.ptr) +nextstyle(styletable::StyleTable)::String = GDAL.ogr_stbl_getnextstyle(styletable.ptr) """ laststyle(styletable::StyleTable) @@ -482,5 +452,4 @@ Get the style name of the last style string fetched with OGR_STBL_GetNextStyle. ### Returns the Name of the last style string or NULL on error. """ -laststyle(styletable::StyleTable)::String = - GDAL.ogr_stbl_getlaststylename(styletable.ptr) +laststyle(styletable::StyleTable)::String = GDAL.ogr_stbl_getlaststylename(styletable.ptr) diff --git a/src/raster/array.jl b/src/raster/array.jl index 79eb8c57..69f00f2e 100644 --- a/src/raster/array.jl +++ b/src/raster/array.jl @@ -21,32 +21,44 @@ us to be able to index into it like we would an array. Constructing a RasterDataset will error if the raster bands do not have all the same size and a common element data type. """ -struct RasterDataset{T, DS <: AbstractDataset} <: AbstractDiskArray{T,3} +struct RasterDataset{T,DS<:AbstractDataset} <: AbstractDiskArray{T,3} ds::DS size::Tuple{Int,Int,Int} end -function RasterDataset( - ds::AbstractDataset - )::RasterDataset{pixeltype(ds), typeof(ds)} +function RasterDataset(ds::AbstractDataset)::RasterDataset{pixeltype(ds),typeof(ds)} if iszero(nraster(ds)) throw(ArgumentError("The Dataset does not contain any raster bands")) end s = _common_size(ds) - return RasterDataset{pixeltype(ds), typeof(ds)}(ds, s) + return RasterDataset{pixeltype(ds),typeof(ds)}(ds, s) end # Forward a few functions # Here we try to include all functions that are relevant # for raster-like datasets. -for f in (:getgeotransform, :nraster, :getband, :getproj, :width, :height, - :destroy, :getdriver, :filelist, :listcapability, :ngcp, :copy, - :unsafe_copy, :write, :testcapability, :setproj!, :buildoverviews!, - :metadata, :metadatadomainlist) - eval(:( - $(f)(x::RasterDataset, args...; kwargs...) = - $(f)(x.ds, args...; kwargs...) - )) +for f in ( + :getgeotransform, + :nraster, + :getband, + :getproj, + :width, + :height, + :destroy, + :getdriver, + :filelist, + :listcapability, + :ngcp, + :copy, + :unsafe_copy, + :write, + :testcapability, + :setproj!, + :buildoverviews!, + :metadata, + :metadatadomainlist, +) + eval(:($(f)(x::RasterDataset, args...; kwargs...) = $(f)(x.ds, args...; kwargs...))) end # Here we need to special-case, to avoid a method ambiguity @@ -56,28 +68,28 @@ end # Here we need to special-case, because source and dest might be rasters function copywholeraster!( - source::RasterDataset, - dest::D; - kwargs... - )::D where {D <: AbstractDataset} + source::RasterDataset, + dest::D; + kwargs..., +)::D where {D<:AbstractDataset} copywholeraster!(source.ds, dest; kwargs...) return dest end function copywholeraster!( - source::RasterDataset, - dest::RasterDataset; - kwargs... - )::RasterDataset + source::RasterDataset, + dest::RasterDataset; + kwargs..., +)::RasterDataset copywholeraster!(source, dest.ds; kwargs...) return dest end function copywholeraster!( - source::AbstractDataset, - dest::RasterDataset; - kwargs... - )::RasterDataset + source::AbstractDataset, + dest::RasterDataset; + kwargs..., +)::RasterDataset copywholeraster!(source, dest.ds; kwargs...) return dest end @@ -96,9 +108,11 @@ function _common_size(ds::AbstractDataset) end s = unique(allsizes) if length(s) != 1 - throw(DimensionMismatch( - "Can not coerce bands to single dataset, different sizes found" - )) + throw( + DimensionMismatch( + "Can not coerce bands to single dataset, different sizes found", + ), + ) end return Int.((s[1]..., nr)) end @@ -115,19 +129,17 @@ function returns a `RasterDataset`, which is a subtype of `AbstractDiskArray{T,3}`, so that users can operate on the array using direct indexing. """ -readraster(s::String; kwargs...)::RasterDataset = - RasterDataset(read(s; kwargs...)) +readraster(s::String; kwargs...)::RasterDataset = RasterDataset(read(s; kwargs...)) function DiskArrays.eachchunk(ds::RasterDataset)::DiskArrays.GridChunks subchunks = DiskArrays.eachchunk(getband(ds, 1)) - return DiskArrays.GridChunks(ds,(subchunks.chunksize..., 1)) + return DiskArrays.GridChunks(ds, (subchunks.chunksize..., 1)) end DiskArrays.haschunks(::RasterDataset)::DiskArrays.Chunked = DiskArrays.Chunked() -DiskArrays.haschunks(::AbstractRasterBand)::DiskArrays.Chunked = - DiskArrays.Chunked() +DiskArrays.haschunks(::AbstractRasterBand)::DiskArrays.Chunked = DiskArrays.Chunked() -Base.size(band::AbstractRasterBand)::Tuple{T, T} where {T <: Integer} = +Base.size(band::AbstractRasterBand)::Tuple{T,T} where {T<:Integer} = (width(band), height(band)) function DiskArrays.eachchunk(band::AbstractRasterBand)::DiskArrays.GridChunks @@ -137,11 +149,11 @@ function DiskArrays.eachchunk(band::AbstractRasterBand)::DiskArrays.GridChunks end function DiskArrays.readblock!( - band::AbstractRasterBand, - buffer::T, - x::AbstractUnitRange, - y::AbstractUnitRange - )::T where {T <: Any} + band::AbstractRasterBand, + buffer::T, + x::AbstractUnitRange, + y::AbstractUnitRange, +)::T where {T<:Any} xoffset, yoffset = first(x) - 1, first(y) - 1 xsize, ysize = length(x), length(y) read!(band, buffer, xoffset, yoffset, xsize, ysize) @@ -149,11 +161,11 @@ function DiskArrays.readblock!( end function DiskArrays.writeblock!( - band::AbstractRasterBand, - buffer::T, - x::AbstractUnitRange, - y::AbstractUnitRange - )::T where {T <: Any} + band::AbstractRasterBand, + buffer::T, + x::AbstractUnitRange, + y::AbstractUnitRange, +)::T where {T<:Any} xoffset, yoffset = first(x) - 1, first(y) - 1 xsize, ysize = length(x), length(y) write!(band, buffer, xoffset, yoffset, xsize, ysize) @@ -166,12 +178,12 @@ end Base.size(dataset::RasterDataset)::Tuple{Int,Int,Int} = dataset.size function DiskArrays.readblock!( - dataset::RasterDataset, - buffer::T, - x::AbstractUnitRange, - y::AbstractUnitRange, - z::AbstractUnitRange - )::T where {T <: Any} + dataset::RasterDataset, + buffer::T, + x::AbstractUnitRange, + y::AbstractUnitRange, + z::AbstractUnitRange, +)::T where {T<:Any} buffer2 = Array(buffer) DiskArrays.readblock!(dataset::RasterDataset, buffer2, x, y, z) buffer .= buffer2 @@ -179,12 +191,12 @@ function DiskArrays.readblock!( end function DiskArrays.readblock!( - dataset::RasterDataset, - buffer::T, - x::AbstractUnitRange, - y::AbstractUnitRange, - z::AbstractUnitRange - )::T where {T <: Array} + dataset::RasterDataset, + buffer::T, + x::AbstractUnitRange, + y::AbstractUnitRange, + z::AbstractUnitRange, +)::T where {T<:Array} xoffset, yoffset = first.((x, y)) .- 1 xsize, ysize = length.((x, y)) read!(dataset.ds, buffer, Cint.(z), xoffset, yoffset, xsize, ysize) @@ -192,17 +204,17 @@ function DiskArrays.readblock!( end function DiskArrays.writeblock!( - dataset::RasterDataset, - buffer::T, - x::AbstractUnitRange, - y::AbstractUnitRange, - bands::AbstractUnitRange - )::T where {T <: Any} + dataset::RasterDataset, + buffer::T, + x::AbstractUnitRange, + y::AbstractUnitRange, + bands::AbstractUnitRange, +)::T where {T<:Any} xoffset, yoffset = first.((x, y)) .- 1 - xsize, ysize= length.((x, y)) - indices = [Cint(i) for i in bands] + xsize, ysize = length.((x, y)) + indices = [Cint(i) for i in bands] write!(dataset.ds, buffer, indices, xoffset, yoffset, xsize, ysize) return buffer end -Base.Array(dataset::RasterDataset) = dataset[:,:,:] +Base.Array(dataset::RasterDataset) = dataset[:, :, :] diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index 7b6bb0f3..e428efdf 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -34,5 +34,4 @@ Fetch palette interpretation. ### Returns palette interpretation enumeration value, usually `GPI_RGB`. """ -paletteinterp(ct::ColorTable)::GDALPaletteInterp = - GDAL.gdalgetpaletteinterpretation(ct.ptr) +paletteinterp(ct::ColorTable)::GDALPaletteInterp = GDAL.gdalgetpaletteinterpretation(ct.ptr) diff --git a/src/raster/images.jl b/src/raster/images.jl index 7701bff4..ba96e187 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -1,8 +1,4 @@ -function imread( - colortable::ColorTable, - dataset::AbstractDataset, - indices - ) +function imread(colortable::ColorTable, dataset::AbstractDataset, indices) palette = getcolortable(getband(dataset, indices[1])) do ct paletteinterp(ct) end @@ -20,44 +16,51 @@ function imread( end function imread( - colortype::Type{<:ColorTypes.Colorant}, - dataset::AbstractDataset, - indices::NTuple{1, <:Integer} + colortype::Type{<:ColorTypes.Colorant}, + dataset::AbstractDataset, + indices::NTuple{1,<:Integer}, +) + return ImageCore.PermutedDimsArray( + ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, indices[1]))), + (2, 1), ) - return ImageCore.PermutedDimsArray(ImageCore.colorview(colortype, - ImageCore.normedview(read(dataset, indices[1])) - ), (2,1)) end function imread( - colortype::Type{<:ColorTypes.Colorant}, - dataset::AbstractDataset, - indices::NTuple{3,<:Integer} + colortype::Type{<:ColorTypes.Colorant}, + dataset::AbstractDataset, + indices::NTuple{3,<:Integer}, +) + return ImageCore.PermutedDimsArray( + ImageCore.colorview( + colortype, + ImageCore.normedview(read(dataset, indices[1])), + ImageCore.normedview(read(dataset, indices[2])), + ImageCore.normedview(read(dataset, indices[3])), + ), + (2, 1), ) - return ImageCore.PermutedDimsArray(ImageCore.colorview(colortype, - ImageCore.normedview(read(dataset, indices[1])), - ImageCore.normedview(read(dataset, indices[2])), - ImageCore.normedview(read(dataset, indices[3])) - ), (2,1)) end function imread( - colortype::Type{<:ColorTypes.Colorant}, - dataset::Dataset, - indices::NTuple{4,<:Integer} + colortype::Type{<:ColorTypes.Colorant}, + dataset::Dataset, + indices::NTuple{4,<:Integer}, +) + return ImageCore.PermutedDimsArray( + ImageCore.colorview( + colortype, + ImageCore.normedview(read(dataset, indices[1])), + ImageCore.normedview(read(dataset, indices[2])), + ImageCore.normedview(read(dataset, indices[3])), + ImageCore.normedview(read(dataset, indices[4])), + ), + (2, 1), ) - return ImageCore.PermutedDimsArray(ImageCore.colorview(colortype, - ImageCore.normedview(read(dataset, indices[1])), - ImageCore.normedview(read(dataset, indices[2])), - ImageCore.normedview(read(dataset, indices[3])), - ImageCore.normedview(read(dataset, indices[4])) - ), (2,1)) end function imread(dataset::AbstractDataset, indices) - gci = unique(GDALColorInterp[ - getcolorinterp(getband(dataset, i)) for i in indices - ]) + gci = unique(GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices]) gciorder = sort(gci) return if gciorder == [GCI_GrayIndex] imread(ColorTypes.Gray, dataset, Tuple(indices[sortperm(gci)])) diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 81f0520f..05c36ecd 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -3,16 +3,14 @@ Construct empty table. """ -unsafe_createRAT()::RasterAttrTable = - RasterAttrTable(GDAL.gdalcreaterasterattributetable()) +unsafe_createRAT()::RasterAttrTable = RasterAttrTable(GDAL.gdalcreaterasterattributetable()) """ unsafe_createRAT(ct::ColorTable) Construct table from an existing colortable. """ -unsafe_createRAT(ct::ColorTable)::RasterAttrTable = - initializeRAT!(unsafe_createRAT(), ct) +unsafe_createRAT(ct::ColorTable)::RasterAttrTable = initializeRAT!(unsafe_createRAT(), ct) "Destroys a RAT." function destroy(rat::RasterAttrTable)::Nothing @@ -39,8 +37,7 @@ Fetch name of indicated column. ### Returns the column name or an empty string for invalid column numbers. """ -columnname(rat::RasterAttrTable, i::Integer)::String = - GDAL.gdalratgetnameofcol(rat.ptr, i) +columnname(rat::RasterAttrTable, i::Integer)::String = GDAL.gdalratgetnameofcol(rat.ptr, i) """ columnusage(rat::RasterAttrTable, i::Integer) @@ -146,31 +143,31 @@ loss of precision. function setvalue! end function setvalue!( - rat::RasterAttrTable, - row::Integer, - col::Integer, - val::AbstractString - )::RasterAttrTable + rat::RasterAttrTable, + row::Integer, + col::Integer, + val::AbstractString, +)::RasterAttrTable GDAL.gdalratsetvalueasstring(rat.ptr, row, col, val) return rat end function setvalue!( - rat::RasterAttrTable, - row::Integer, - col::Integer, - val::Integer - )::RasterAttrTable + rat::RasterAttrTable, + row::Integer, + col::Integer, + val::Integer, +)::RasterAttrTable GDAL.gdalratsetvalueasint(rat.ptr, row, col, val) return rat end function setvalue!( - rat::RasterAttrTable, - row::Integer, - col::Integer, - val::Float64 - )::RasterAttrTable + rat::RasterAttrTable, + row::Integer, + col::Integer, + val::Float64, +)::RasterAttrTable GDAL.gdalratsetvalueasdouble(rat.ptr, row, col, val) return rat end @@ -204,43 +201,40 @@ Read or Write a block of data to/from the Attribute Table. function attributeio! end function attributeio!( - rat::RasterAttrTable, - access::GDALRWFlag, - col::Integer, - startrow::Integer, - nrows::Integer, - data::Vector{Float64} - )::Vector{Float64} - result = GDAL.gdalratvaluesioasdouble(rat.ptr, access, col, startrow, nrows, - data) + rat::RasterAttrTable, + access::GDALRWFlag, + col::Integer, + startrow::Integer, + nrows::Integer, + data::Vector{Float64}, +)::Vector{Float64} + result = GDAL.gdalratvaluesioasdouble(rat.ptr, access, col, startrow, nrows, data) @cplerr result "Failed to $access at column $col starting at $startrow" return data end function attributeio!( - rat::RasterAttrTable, - access::GDALRWFlag, - col::Integer, - startrow::Integer, - nrows::Integer, - data::Vector{Cint} - )::Vector{Cint} - result = GDAL.gdalratvaluesioasinteger(rat.ptr, access, col, startrow, - nrows, data) + rat::RasterAttrTable, + access::GDALRWFlag, + col::Integer, + startrow::Integer, + nrows::Integer, + data::Vector{Cint}, +)::Vector{Cint} + result = GDAL.gdalratvaluesioasinteger(rat.ptr, access, col, startrow, nrows, data) @cplerr result "Failed to $access at column $col starting at $startrow" return data end function attributeio!( - rat::RasterAttrTable, - access::GDALRWFlag, - col::Integer, - startrow::Integer, - nrows::Integer, - data::Vector{T} - )::Vector{T} where T <: AbstractString - result = GDAL.gdalratvaluesioasstring(rat.ptr, access, col, startrow, nrows, - data) + rat::RasterAttrTable, + access::GDALRWFlag, + col::Integer, + startrow::Integer, + nrows::Integer, + data::Vector{T}, +)::Vector{T} where {T<:AbstractString} + result = GDAL.gdalratvaluesioasstring(rat.ptr, access, col, startrow, nrows, data) @cplerr result "Failed to $access at column $col starting at $startrow" return data end @@ -271,11 +265,11 @@ created as the last column, can will be column (field) \"GetColumnCount()-1\" after CreateColumn() has completed successfully. """ function createcolumn!( - rat::RasterAttrTable, - name::AbstractString, - fieldtype::GDALRATFieldType, - fieldusage::GDALRATFieldUsage - )::RasterAttrTable + rat::RasterAttrTable, + name::AbstractString, + fieldtype::GDALRATFieldType, + fieldusage::GDALRATFieldUsage, +)::RasterAttrTable result = GDAL.gdalratcreatecolumn(rat.ptr, name, fieldtype, fieldusage) @cplerr result "Failed to create column $name" return rat @@ -295,10 +289,10 @@ the table. * `binsize` the width of each category (in pixel value units). """ function setlinearbinning!( - rat::RasterAttrTable, - row0min::Real, - binsize::Real - )::RasterAttrTable + rat::RasterAttrTable, + row0min::Real, + binsize::Real, +)::RasterAttrTable result = GDAL.gdalratsetlinearbinning(rat.ptr, row0min, binsize) @cplerr result "Fail to set linear binning: r0min=$row0min, width=$binsize" return rat @@ -313,7 +307,7 @@ Get linear binning information. * `row0min` the lower bound (pixel value) of the first category. * `binsize` the width of each category (in pixel value units). """ -function getlinearbinning(rat::RasterAttrTable)::Tuple{Cdouble, Cdouble} +function getlinearbinning(rat::RasterAttrTable)::Tuple{Cdouble,Cdouble} row0min = Ref{Cdouble}() binsize = Ref{Cdouble}() result = GDAL.gdalratgetlinearbinning(rat.ptr, row0min, binsize) @@ -336,10 +330,7 @@ The raster attribute table must be empty before calling `initializeRAT!()`. The Value fields are set based on the implicit assumption with color tables that entry 0 applies to pixel value 0, 1 to 1, etc. """ -function initializeRAT!( - rat::RasterAttrTable, - colortable::ColorTable - )::RasterAttrTable +function initializeRAT!(rat::RasterAttrTable, colortable::ColorTable)::RasterAttrTable result = GDAL.gdalratinitializefromcolortable(rat.ptr, colortable.ptr) @cplerr result "Failed to initialize RAT from color table" return rat diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 393d4787..07782f56 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -28,7 +28,9 @@ meaning that right and bottom edge blocks may be incomplete. See `ReadBlock()` for an example of code dealing with these issues. """ function blocksize(band::AbstractRasterBand)::Vector{Cint} - xy = Vector{Cint}(undef, 2); x = pointer(xy); y = x + sizeof(Cint) + xy = Vector{Cint}(undef, 2) + x = pointer(xy) + y = x + sizeof(Cint) GDAL.gdalgetblocksize(band.ptr, x, y) return xy end @@ -38,7 +40,7 @@ end Fetch the pixel data type for this band. """ -function pixeltype(band::AbstractRasterBand{T})::DataType where {T <: Any} +function pixeltype(band::AbstractRasterBand{T})::DataType where {T<:Any} return T end @@ -61,8 +63,7 @@ height(band::AbstractRasterBand)::Integer = GDAL.gdalgetrasterbandysize(band.ptr Return the access flag (e.g. `OF_READONLY` or `OF_UPDATE`) for this band. """ -accessflag(band::AbstractRasterBand)::GDALAccess = - GDAL.gdalgetrasteraccess(band.ptr) +accessflag(band::AbstractRasterBand)::GDALAccess = GDAL.gdalgetrasteraccess(band.ptr) """ indexof(band::AbstractRasterBand) @@ -82,8 +83,7 @@ Fetch the handle to its dataset handle, or `NULL` if this cannot be determined. Note that some `RasterBand`s are not considered to be a part of a dataset, such as overviews or other "freestanding" bands. """ -getdataset(band::AbstractRasterBand)::Dataset = - Dataset(GDAL.gdalgetbanddataset(band.ptr)) +getdataset(band::AbstractRasterBand)::Dataset = Dataset(GDAL.gdalgetbanddataset(band.ptr)) # ↑ GDAL wrapper checks null by default, but it is a valid result in this case """ @@ -92,8 +92,7 @@ getdataset(band::AbstractRasterBand)::Dataset = Return a name for the units of this raster's values. For instance, it might be "m" for an elevation model in meters, or "ft" for feet. """ -getunittype(band::AbstractRasterBand)::String = - GDAL.gdalgetrasterunittype(band.ptr) +getunittype(band::AbstractRasterBand)::String = GDAL.gdalgetrasterunittype(band.ptr) """ setunittype!(band::AbstractRasterBand, unitstring::AbstractString) @@ -104,10 +103,7 @@ Values should be one of \"\" (the default indicating it is unknown), \"m\" indicating meters, or \"ft\" indicating feet, though other nonstandard values are allowed. """ -function setunittype!( - band::T, - unitstring::AbstractString - )::T where {T <: AbstractRasterBand} +function setunittype!(band::T, unitstring::AbstractString)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrasterunittype(band.ptr, unitstring) @cplerr result "Failed to set unit type" return band @@ -126,15 +122,14 @@ elevations in `GUInt16` bands with a precision of 0.1, starting from -100. For file formats that don't know this intrinsically, a value of 0 is returned. """ -getoffset(band::AbstractRasterBand)::Real = - GDAL.gdalgetrasteroffset(band.ptr, C_NULL) +getoffset(band::AbstractRasterBand)::Real = GDAL.gdalgetrasteroffset(band.ptr, C_NULL) """ setoffset!(band::AbstractRasterBand, value::Real) Set scaling offset. """ -function setoffset!(band::T, value::Real)::T where {T <: AbstractRasterBand} +function setoffset!(band::T, value::Real)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrasteroffset(band.ptr, value) @cplerr result "Failed to set scaling offset." return band @@ -154,15 +149,14 @@ and starting from -100. For file formats that don't know this intrinsically a value of one is returned. """ -getscale(band::AbstractRasterBand)::Real = - GDAL.gdalgetrasterscale(band.ptr, C_NULL) +getscale(band::AbstractRasterBand)::Real = GDAL.gdalgetrasterscale(band.ptr, C_NULL) """ setscale!(band::AbstractRasterBand, ratio::Real) Set scaling ratio. """ -function setscale!(band::T, ratio::Real)::T where {T <: AbstractRasterBand} +function setscale!(band::T, ratio::Real)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrasterscale(band.ptr, ratio) @cplerr result "Failed to set scaling ratio" return band @@ -181,7 +175,7 @@ not be displayed, nor contribute to analysis operations. ### Returns the nodata value for this band or `nothing`. """ -function getnodatavalue(band::AbstractRasterBand)::Union{Cint, Nothing} +function getnodatavalue(band::AbstractRasterBand)::Union{Cint,Nothing} # ### Parameters # * `pbSuccess` pointer to a boolean to use to indicate if a value is # actually associated with this layer. May be `NULL` (default). @@ -199,16 +193,13 @@ end Set the no data value for this band. """ -function setnodatavalue!( - band::T, - value::Real - )::T where {T <: AbstractRasterBand} +function setnodatavalue!(band::T, value::Real)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrasternodatavalue(band.ptr, value) @cplerr result "Could not set nodatavalue" return band end -function deletenodatavalue!(band::T)::T where {T <: AbstractRasterBand} +function deletenodatavalue!(band::T)::T where {T<:AbstractRasterBand} result = GDAL.gdaldeleterasternodatavalue(band.ptr) @cplerr result "Could not delete nodatavalue" return band @@ -219,16 +210,14 @@ end Fetch the minimum value for this band. """ -minimum(band::AbstractRasterBand)::Real = - GDAL.gdalgetrasterminimum(band.ptr, C_NULL) +minimum(band::AbstractRasterBand)::Real = GDAL.gdalgetrasterminimum(band.ptr, C_NULL) """ maximum(band::AbstractRasterBand) Fetch the maximum value for this band. """ -maximum(band::AbstractRasterBand)::Real = - GDAL.gdalgetrastermaximum(band.ptr, C_NULL) +maximum(band::AbstractRasterBand)::Real = GDAL.gdalgetrastermaximum(band.ptr, C_NULL) """ getdefaultRAT(band::AbstractRasterBand) @@ -249,10 +238,7 @@ Associates a default RAT with the band. If not implemented for the format a CPLE_NotSupported error will be issued. If successful a copy of the RAT is made, the original remains owned by the caller. """ -function setdefaultRAT!( - band::T, - rat::RasterAttrTable - )::T where {T <: AbstractRasterBand} +function setdefaultRAT!(band::T, rat::RasterAttrTable)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetdefaultrat(band.ptr, rat.ptr) @cplerr result "Failed to set default raster attribute table" return band @@ -283,14 +269,19 @@ More options may be supported in the future. * `progressdata` callback data for progress function. """ function copywholeraster!( - source::T, - dest::AbstractRasterBand; - options = StringList(C_NULL), - progressdata = C_NULL, - progressfunc::Function = GDAL.gdaldummyprogress - )::T where {T <: AbstractRasterBand} - result = GDAL.gdalrasterbandcopywholeraster(source.ptr, dest.ptr, options, - @cplprogress(progressfunc), progressdata) + source::T, + dest::AbstractRasterBand; + options = StringList(C_NULL), + progressdata = C_NULL, + progressfunc::Function = GDAL.gdaldummyprogress, +)::T where {T<:AbstractRasterBand} + result = GDAL.gdalrasterbandcopywholeraster( + source.ptr, + dest.ptr, + options, + @cplprogress(progressfunc), + progressdata, + ) @cplerr result "Failed to copy whole raster" return source end @@ -300,8 +291,7 @@ end Return the number of overview layers available, zero if none. """ -noverview(band::AbstractRasterBand)::Integer = - GDAL.gdalgetoverviewcount(band.ptr) +noverview(band::AbstractRasterBand)::Integer = GDAL.gdalgetoverviewcount(band.ptr) """ getoverview(band::IRasterBand, i::Integer) @@ -328,7 +318,7 @@ overviews have enough samples. function sampleoverview(band::IRasterBand, nsamples::Integer)::IRasterBand return IRasterBand( GDAL.gdalgetrastersampleoverviewex(band.ptr, UInt64(nsamples)), - ownedby = band.ownedby + ownedby = band.ownedby, ) end @@ -348,10 +338,7 @@ getcolorinterp(band::AbstractRasterBand)::GDALColorInterp = Set color interpretation of a band. """ -function setcolorinterp!( - band::T, - color::GDALColorInterp - )::T where {T <: AbstractRasterBand} +function setcolorinterp!(band::T, color::GDALColorInterp)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercolorinterpretation(band.ptr, color) @cplerr result "Failed to set color interpretation" return band @@ -380,16 +367,13 @@ owned by the caller after the call. ### Parameters * `colortable` color table to apply (where supported). """ -function setcolortable!( - band::T, - colortable::ColorTable - )::T where {T <: AbstractRasterBand} +function setcolortable!(band::T, colortable::ColorTable)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercolortable(band.ptr, colortable.ptr) @cplwarn result "CPLError $(result): action is unsupported by the driver" return band end -function clearcolortable!(band::T)::T where {T <: AbstractRasterBand} +function clearcolortable!(band::T)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercolortable(band.ptr, C_NULL) @cplwarn result "CPLError $(result): action is unsupported by the driver" return band @@ -425,21 +409,20 @@ considered as the nodata value and not each value of the triplet independantly per band. """ function regenerateoverviews!( - band::T, - overviewbands::Vector{<:AbstractRasterBand}, - resampling::AbstractString = "NEAREST", - # progressfunc::Function = GDAL.gdaldummyprogress, - progressdata = C_NULL - )::T where {T <: AbstractRasterBand} - cfunc = @cfunction(GDAL.gdaldummyprogress, Cint, - (Cdouble, Cstring, Ptr{Cvoid})) + band::T, + overviewbands::Vector{<:AbstractRasterBand}, + resampling::AbstractString = "NEAREST", + # progressfunc::Function = GDAL.gdaldummyprogress, + progressdata = C_NULL, +)::T where {T<:AbstractRasterBand} + cfunc = @cfunction(GDAL.gdaldummyprogress, Cint, (Cdouble, Cstring, Ptr{Cvoid})) result = GDAL.gdalregenerateoverviews( band.ptr, length(overviewbands), [band.ptr for band in overviewbands], resampling, cfunc, - progressdata + progressdata, ) @cplerr result "Failed to regenerate overviews" return band @@ -476,10 +459,7 @@ getcategorynames(band::AbstractRasterBand)::Vector{String} = Set the category names for this band. """ -function setcategorynames!( - band::T, - names::Vector{String} - )::T where {T <: AbstractRasterBand} +function setcategorynames!(band::T, names::Vector{String})::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercategorynames(band.ptr, names) @cplerr result "Failed to set category names for this band" return band @@ -513,10 +493,10 @@ allows the imaginary component of a complex constant value to be specified. * `imagvalue`: Imaginary component of fill value, defaults to zero """ function fillraster!( - band::T, - realvalue::Real, - imagvalue::Real = 0 - )::T where {T <: AbstractRasterBand} + band::T, + realvalue::Real, + imagvalue::Real = 0, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalfillraster(band.ptr, realvalue, imagvalue) @cplerr result "Failed to fill raster band" return band @@ -618,14 +598,11 @@ named tuple with the following fields: A named tuple with unpacked mask flags """ function maskflaginfo( - band::AbstractRasterBand - )::NamedTuple{ - (:all_valid, :per_dataset, :alpha, :nodata), - NTuple{4, Bool} - } + band::AbstractRasterBand, +)::NamedTuple{(:all_valid, :per_dataset, :alpha, :nodata),NTuple{4,Bool}} flags = maskflags(band) return ( - all_valid = !iszero(flags & 0x01), + all_valid = !iszero(flags & 0x01), per_dataset = !iszero(flags & 0x02), alpha = !iszero(flags & 0x04), nodata = !iszero(flags & 0x08), @@ -650,10 +627,7 @@ invalidated by `CreateMaskBand()`. So you have to call `GetMaskBand()` again. See also: http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask """ -function createmaskband!( - band::T, - nflags::Integer - )::T where {T <: AbstractRasterBand} +function createmaskband!(band::T, nflags::Integer)::T where {T<:AbstractRasterBand} result = GDAL.gdalcreatemaskband(band.ptr, nflags) @cplerr result "Failed to create mask band" return band diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 6fbc7144..0b45401a 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -66,51 +66,75 @@ boundaries\" as returned by `blocksize()`, or use the `readblock!()` and function rasterio! end function rasterio!( - dataset::AbstractDataset, - buffer::T, + dataset::AbstractDataset, + buffer::T, + bands, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, +)::T where {T<:Array{<:Any,3}} + rasterio!( + dataset, + buffer, bands, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0, - )::T where {T <: Array{<:Any, 3}} - rasterio!(dataset, buffer, bands, 0, 0, size(buffer, 1), size(buffer, 2), - access, pxspace, linespace, bandspace) + 0, + 0, + size(buffer, 1), + size(buffer, 2), + access, + pxspace, + linespace, + bandspace, + ) return buffer end function rasterio!( - dataset::AbstractDataset, - buffer::Array{T, 3}, + dataset::AbstractDataset, + buffer::Array{T,3}, + bands, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, +)::Array{T,3} where {T<:Any} + xsize = cols[end] - cols[1] + 1 + xsize < 0 && error("invalid window width") + ysize = rows[end] - rows[1] + 1 + ysize < 0 && error("invalid window height") + rasterio!( + dataset, + buffer, bands, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0, - )::Array{T, 3} where {T <: Any} - xsize = cols[end] - cols[1] + 1; xsize < 0 && error("invalid window width") - ysize = rows[end] - rows[1] + 1; ysize < 0 && error("invalid window height") - rasterio!(dataset, buffer, bands, cols[1] - 1, rows[1] - 1, xsize, ysize, - access, pxspace, linespace, bandspace) + cols[1] - 1, + rows[1] - 1, + xsize, + ysize, + access, + pxspace, + linespace, + bandspace, + ) return buffer end function rasterio!( - dataset::AbstractDataset, - buffer::Array{T, 3}, - bands, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - bandspace::Integer = 0, - extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL) - )::Array{T, 3} where {T <: Any} + dataset::AbstractDataset, + buffer::Array{T,3}, + bands, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + bandspace::Integer = 0, + extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL), +)::Array{T,3} where {T<:Any} # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg # structure with additional arguments to specify resampling and # progress callback, or `NULL` for default behaviour. The @@ -122,53 +146,88 @@ function rasterio!( nband = length(bands) bands = isa(bands, Vector{Cint}) ? bands : Cint.(collect(bands)) @assert nband == zbsize - result = GDAL.gdaldatasetrasterioex(dataset.ptr, access, xoffset, yoffset, - xsize, ysize, pointer(buffer), xbsize, ybsize, convert(GDALDataType, T), - nband, pointer(bands), pxspace, linespace, bandspace, extraargs) + result = GDAL.gdaldatasetrasterioex( + dataset.ptr, + access, + xoffset, + yoffset, + xsize, + ysize, + pointer(buffer), + xbsize, + ybsize, + convert(GDALDataType, T), + nband, + pointer(bands), + pxspace, + linespace, + bandspace, + extraargs, + ) @cplerr result "Access in DatasetRasterIO failed." return buffer end function rasterio!( - rasterband::AbstractRasterBand, - buffer::T, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - )::T where {T <: Matrix{<:Any}} - rasterio!(rasterband, buffer, 0, 0, width(rasterband), height(rasterband), - access, pxspace, linespace) + rasterband::AbstractRasterBand, + buffer::T, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, +)::T where {T<:Matrix{<:Any}} + rasterio!( + rasterband, + buffer, + 0, + 0, + width(rasterband), + height(rasterband), + access, + pxspace, + linespace, + ) return buffer end function rasterio!( - rasterband::AbstractRasterBand, - buffer::T, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - )::T where {T <: Matrix{<:Any}} - xsize = length(cols); xsize < 1 && error("invalid window width") - ysize = length(rows); ysize < 1 && error("invalid window height") - rasterio!(rasterband, buffer, cols[1] - 1, rows[1] - 1, xsize, ysize, - access, pxspace, linespace) + rasterband::AbstractRasterBand, + buffer::T, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, +)::T where {T<:Matrix{<:Any}} + xsize = length(cols) + xsize < 1 && error("invalid window width") + ysize = length(rows) + ysize < 1 && error("invalid window height") + rasterio!( + rasterband, + buffer, + cols[1] - 1, + rows[1] - 1, + xsize, + ysize, + access, + pxspace, + linespace, + ) return buffer end function rasterio!( - rasterband::AbstractRasterBand, - buffer::Matrix{T}, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, - access::GDALRWFlag = GF_Read, - pxspace::Integer = 0, - linespace::Integer = 0, - extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL), - )::Matrix{T} where {T <: Any} + rasterband::AbstractRasterBand, + buffer::Matrix{T}, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, + access::GDALRWFlag = GF_Read, + pxspace::Integer = 0, + linespace::Integer = 0, + extraargs = Ptr{GDAL.GDALRasterIOExtraArg}(C_NULL), +)::Matrix{T} where {T<:Any} # `psExtraArg` (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg # structure with additional arguments to specify resampling and # progress callback, or `NULL` for default behaviour. The @@ -177,39 +236,48 @@ function rasterio!( # `CUBIC`, `CUBICSPLINE`, `LANCZOS`, `AVERAGE` or `MODE`. (rasterband == C_NULL) && error("Can't read NULL rasterband") xbsize, ybsize = size(buffer) - result = GDAL.gdalrasterioex(rasterband.ptr, access, xoffset, yoffset, - xsize, ysize, pointer(buffer), xbsize, ybsize, convert(GDALDataType, T), - pxspace, linespace, extraargs) + result = GDAL.gdalrasterioex( + rasterband.ptr, + access, + xoffset, + yoffset, + xsize, + ysize, + pointer(buffer), + xbsize, + ybsize, + convert(GDALDataType, T), + pxspace, + linespace, + extraargs, + ) @cplerr result "Access in RasterIO failed." return buffer end -function read!( - rb::AbstractRasterBand, - buffer::T - )::T where {T <: Matrix{<:Any}} +function read!(rb::AbstractRasterBand, buffer::T)::T where {T<:Matrix{<:Any}} rasterio!(rb, buffer, GF_Read) return buffer end function read!( - rb::AbstractRasterBand, - buffer::T, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::T where {T <: Matrix{<:Any}} + rb::AbstractRasterBand, + buffer::T, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::T where {T<:Matrix{<:Any}} rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize) return buffer end function read!( - rb::AbstractRasterBand, - buffer::T, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} - )::T where {T <: Matrix{<:Any}} + rb::AbstractRasterBand, + buffer::T, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +)::T where {T<:Matrix{<:Any}} rasterio!(rb, buffer, rows, cols) return buffer end @@ -218,71 +286,60 @@ read(rb::AbstractRasterBand) = rasterio!(rb, Array{pixeltype(rb)}(undef, width(rb), height(rb))) function read( - rb::AbstractRasterBand, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::Matrix{pixeltype(rb)} + rb::AbstractRasterBand, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::Matrix{pixeltype(rb)} buffer = Matrix{pixeltype(rb)}(undef, xsize, ysize) rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize) return buffer end function read( - rb::AbstractRasterBand, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} - )::Matrix{pixeltype(rb)} + rb::AbstractRasterBand, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +)::Matrix{pixeltype(rb)} buffer = Matrix{pixeltype(rb)}(undef, length(cols), length(rows)) rasterio!(rb, buffer, rows, cols) return buffer end function write!( - rb::AbstractRasterBand, - buffer::T, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::T where {T <: Matrix{<:Any}} + rb::AbstractRasterBand, + buffer::T, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::T where {T<:Matrix{<:Any}} rasterio!(rb, buffer, xoffset, yoffset, xsize, ysize, GF_Write) return buffer end function write!( - rb::AbstractRasterBand, - buffer::T, - rows::UnitRange{<:Integer} = 1:height(rb), - cols::UnitRange{<:Integer} = 1:width(rb), - )::T where {T <: Matrix{<:Any}} + rb::AbstractRasterBand, + buffer::T, + rows::UnitRange{<:Integer} = 1:height(rb), + cols::UnitRange{<:Integer} = 1:width(rb), +)::T where {T<:Matrix{<:Any}} rasterio!(rb, buffer, rows, cols, GF_Write) return buffer end -function read!( - dataset::AbstractDataset, - buffer::T, - i::Integer - )::T where {T <: Matrix{<:Any}} +function read!(dataset::AbstractDataset, buffer::T, i::Integer)::T where {T<:Matrix{<:Any}} read!(getband(dataset, i), buffer) return buffer end -function read!( - dataset::AbstractDataset, - buffer::T, - indices - )::T where {T <: Array{<:Any, 3}} +function read!(dataset::AbstractDataset, buffer::T, indices)::T where {T<:Array{<:Any,3}} rasterio!(dataset, buffer, indices, GF_Read) return buffer end -function read!( - dataset::AbstractDataset, - buffer::T - )::T where {T <: Array{<:Any, 3}} +function read!(dataset::AbstractDataset, buffer::T)::T where {T<:Array{<:Any,3}} nband = nraster(dataset) @assert size(buffer, 3) == nband rasterio!(dataset, buffer, collect(Cint, 1:nband), GF_Read) @@ -290,80 +347,77 @@ function read!( end function read!( - dataset::AbstractDataset, - buffer::T, - i::Integer, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::T where {T <: Matrix{<:Any}} + dataset::AbstractDataset, + buffer::T, + i::Integer, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::T where {T<:Matrix{<:Any}} read!(getband(dataset, i), buffer, xoffset, yoffset, xsize, ysize) return buffer end function read!( - dataset::AbstractDataset, - buffer::T, - indices, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::T where {T <: Array{<:Any, 3}} + dataset::AbstractDataset, + buffer::T, + indices, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::T where {T<:Array{<:Any,3}} rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize) return buffer end function read!( - dataset::AbstractDataset, - buffer::T, - i::Integer, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} - )::T where {T <: Matrix{<:Any}} + dataset::AbstractDataset, + buffer::T, + i::Integer, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +)::T where {T<:Matrix{<:Any}} read!(getband(dataset, i), buffer, rows, cols) return buffer end function read!( - dataset::AbstractDataset, - buffer::T, - indices, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} - )::T where {T <: Array{<:Any, 3}} + dataset::AbstractDataset, + buffer::T, + indices, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +)::T where {T<:Array{<:Any,3}} rasterio!(dataset, buffer, indices, rows, cols) return buffer end read(dataset::AbstractDataset, i::Integer) = read(getband(dataset, i)) -function read( - dataset::AbstractDataset, - indices - )::Array{pixeltype(dataset), 3} - buffer = Array{pixeltype(dataset)}(undef, - width(dataset), height(dataset), length(indices)) +function read(dataset::AbstractDataset, indices)::Array{pixeltype(dataset),3} + buffer = + Array{pixeltype(dataset)}(undef, width(dataset), height(dataset), length(indices)) rasterio!(dataset, buffer, indices) return buffer end -function read(dataset::AbstractDataset)::Array{pixeltype(dataset), 3} - buffer = Array{pixeltype(dataset)}(undef, width(dataset), - height(dataset), nraster(dataset)) +function read(dataset::AbstractDataset)::Array{pixeltype(dataset),3} + buffer = + Array{pixeltype(dataset)}(undef, width(dataset), height(dataset), nraster(dataset)) read!(dataset, buffer) return buffer end function read( - dataset::AbstractDataset, - i::Integer, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::Matrix{pixeltype(dataset)} + dataset::AbstractDataset, + i::Integer, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::Matrix{pixeltype(dataset)} band = getband(dataset, i) buffer = Matrix{pixeltype(band)}(undef, xsize, ysize) read!(dataset, buffer, i, xoffset, yoffset, xsize, ysize) @@ -371,86 +425,83 @@ function read( end function read( - dataset::AbstractDataset, - indices, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::Array{pixeltype(dataset), 3} - buffer = Array{pixeltype(dataset)}(undef, - xsize, ysize, length(indices)) + dataset::AbstractDataset, + indices, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::Array{pixeltype(dataset),3} + buffer = Array{pixeltype(dataset)}(undef, xsize, ysize, length(indices)) rasterio!(dataset, buffer, indices, xsize, ysize, xoffset, yoffset) return buffer end function read( - dataset::AbstractDataset, - i::Integer, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} - )::Matrix{pixeltype(dataset)} + dataset::AbstractDataset, + i::Integer, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +)::Matrix{pixeltype(dataset)} buffer = read(getband(dataset, i), rows, cols) return buffer end function read( - dataset::AbstractDataset, - indices, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer} - )::Array{pixeltype(dataset), 3} - buffer = Array{pixeltype(dataset), 3}(undef, - length(cols), length(rows), length(indices)) + dataset::AbstractDataset, + indices, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +)::Array{pixeltype(dataset),3} + buffer = Array{pixeltype(dataset),3}(undef, length(cols), length(rows), length(indices)) rasterio!(dataset, buffer, indices, rows, cols) return buffer end function write!( - dataset::T, - buffer::Matrix{<:Any}, - i::Integer, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::T where {T <: AbstractDataset} + dataset::T, + buffer::Matrix{<:Any}, + i::Integer, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::T where {T<:AbstractDataset} write!(getband(dataset, i), buffer, xoffset, yoffset, xsize, ysize) return dataset end function write!( - dataset::T, - buffer::Array{<:Any, 3}, - indices, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer - )::T where {T <: AbstractDataset} - rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize, - GF_Write) + dataset::T, + buffer::Array{<:Any,3}, + indices, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +)::T where {T<:AbstractDataset} + rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize, GF_Write) return dataset end function write!( - dataset::T, - buffer::Matrix{<:Any}, - i::Integer, - rows::UnitRange{<:Integer} = 1:height(getband(dataset, i)), - cols::UnitRange{<:Integer} = 1:width(getband(dataset, i)), - )::T where {T <: AbstractDataset} + dataset::T, + buffer::Matrix{<:Any}, + i::Integer, + rows::UnitRange{<:Integer} = 1:height(getband(dataset, i)), + cols::UnitRange{<:Integer} = 1:width(getband(dataset, i)), +)::T where {T<:AbstractDataset} write!(getband(dataset, i), buffer, rows, cols) return dataset end function write!( - dataset::T, - buffer::Array{<:Any, 3}, - indices, - rows::UnitRange{<:Integer} = 1:height(dataset), - cols::UnitRange{<:Integer} = 1:width(dataset), - )::T where {T <: AbstractDataset} + dataset::T, + buffer::Array{<:Any,3}, + indices, + rows::UnitRange{<:Integer} = 1:height(dataset), + cols::UnitRange{<:Integer} = 1:width(dataset), +)::T where {T<:AbstractDataset} rasterio!(dataset, buffer, indices, rows, cols, GF_Write) return dataset end @@ -475,11 +526,11 @@ access use RasterIO(). GetRasterDataType(). """ function readblock!( - rb::AbstractRasterBand, - xoffset::Integer, - yoffset::Integer, - buffer::T - )::T where {T <: Any} + rb::AbstractRasterBand, + xoffset::Integer, + yoffset::Integer, + buffer::T, +)::T where {T<:Any} result = GDAL.gdalreadblock(rb.ptr, xoffset, yoffset, buffer) @cplerr result "Failed to read block at ($xoffset,$yoffset)" return buffer @@ -505,11 +556,11 @@ access use RasterIO(). GetRasterDataType(). """ function writeblock!( - rb::T, - xoffset::Integer, - yoffset::Integer, - buffer - )::T where {T <: AbstractRasterBand} + rb::T, + xoffset::Integer, + yoffset::Integer, + buffer, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalwriteblock(rb.ptr, xoffset, yoffset, buffer) @cplerr result "Failed to write block at ($xoffset, $yoffset)" return rb diff --git a/src/spatialref.jl b/src/spatialref.jl index 28cb63f1..faef8360 100644 --- a/src/spatialref.jl +++ b/src/spatialref.jl @@ -22,41 +22,32 @@ Import a coordinate reference system from a `GeoFormat` into the spatial ref. """ function importCRS! end -function importCRS!(spref::T, x::GFT.EPSG)::T where {T <: AbstractSpatialRef} +function importCRS!(spref::T, x::GFT.EPSG)::T where {T<:AbstractSpatialRef} importEPSG!(spref, GFT.val(x)) return spref end -function importCRS!( - spref::T, - x::GFT.AbstractWellKnownText - )::T where {T <: AbstractSpatialRef} +function importCRS!(spref::T, x::GFT.AbstractWellKnownText)::T where {T<:AbstractSpatialRef} importWKT!(spref, GFT.val(x)) return spref end -function importCRS!( - spref::T, - x::GFT.ESRIWellKnownText - )::T where {T <: AbstractSpatialRef} +function importCRS!(spref::T, x::GFT.ESRIWellKnownText)::T where {T<:AbstractSpatialRef} importESRI!(spref, GFT.val(x)) return spref end -function importCRS!( - spref::T, - x::GFT.ProjString - )::T where {T <: AbstractSpatialRef} +function importCRS!(spref::T, x::GFT.ProjString)::T where {T<:AbstractSpatialRef} importPROJ4!(spref, GFT.val(x)) return spref end -function importCRS!(spref::T, x::GFT.GML)::T where {T <: AbstractSpatialRef} +function importCRS!(spref::T, x::GFT.GML)::T where {T<:AbstractSpatialRef} importXML!(spref, GFT.val(x)) return spref end -function importCRS!(spref::T, x::GFT.KML)::T where {T <: AbstractSpatialRef} +function importCRS!(spref::T, x::GFT.KML)::T where {T<:AbstractSpatialRef} importCRS!(spref, GFT.EPSG(4326)) return spref end @@ -93,80 +84,72 @@ julia> ArchGDAL.reproject( ``` """ function reproject( - coord::T, - sourcecrs::GFT.GeoFormat, - targetcrs::Nothing; - kwargs... - )::T where {T <: Any} + coord::T, + sourcecrs::GFT.GeoFormat, + targetcrs::Nothing; + kwargs..., +)::T where {T<:Any} return coord end # These should be better integrated with geometry packages or follow a standard -const ReprojectCoord = Union{ - <:NTuple{2,<:Number}, - <:NTuple{3,<:Number}, - AbstractVector{<:Number} -} +const ReprojectCoord = + Union{<:NTuple{2,<:Number},<:NTuple{3,<:Number},AbstractVector{<:Number}} # Vector/Tuple coordinate(s) function reproject( - coord::ReprojectCoord, - sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; - kwargs... - ) + coord::ReprojectCoord, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs..., +) return GeoInterface.coordinates( - reproject(createpoint(coord...), sourcecrs, targetcrs; kwargs...) + reproject(createpoint(coord...), sourcecrs, targetcrs; kwargs...), ) end function reproject( - coords::AbstractArray{<:ReprojectCoord}, - sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; - kwargs... - ) + coords::AbstractArray{<:ReprojectCoord}, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs..., +) return GeoInterface.coordinates.( - reproject( - [createpoint(c...) for c in coords], - sourcecrs, - targetcrs; - kwargs... - ) + reproject([createpoint(c...) for c in coords], sourcecrs, targetcrs; kwargs...), ) end # GeoFormat function reproject( - geom::GFT.GeoFormat, - sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; - kwargs... - ) + geom::GFT.GeoFormat, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs..., +) return convert( typeof(geom), - reproject(convert(Geometry, geom), sourcecrs, targetcrs; kwargs...) + reproject(convert(Geometry, geom), sourcecrs, targetcrs; kwargs...), ) end # Geometries function reproject( - geom::AbstractGeometry, - sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; - kwargs... - ) + geom::AbstractGeometry, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs..., +) return crs2transform(sourcecrs, targetcrs; kwargs...) do transform transform!(geom, transform) end end function reproject( - geoms::AbstractArray{<:AbstractGeometry}, - sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; - kwargs... - ) + geoms::AbstractArray{<:AbstractGeometry}, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs..., +) return crs2transform(sourcecrs, targetcrs; kwargs...) do transform transform!.(geoms, Ref(transform)) end @@ -183,11 +166,11 @@ a coordinate reference system. `kwargs` are passed through to `importCRS`. """ function crs2transform( - f::Function, - sourcecrs::GFT.GeoFormat, - targetcrs::GFT.GeoFormat; - kwargs... - ) + f::Function, + sourcecrs::GFT.GeoFormat, + targetcrs::GFT.GeoFormat; + kwargs..., +) return importCRS(sourcecrs; kwargs...) do sourcecrs_ref importCRS(targetcrs; kwargs...) do targetcrs_ref createcoordtrans(sourcecrs_ref, targetcrs_ref) do transform @@ -213,19 +196,11 @@ newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) = unsafe_newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) = maybesetaxisorder!(SpatialRef(GDAL.osrnewspatialreference(wkt)), order) -function maybesetaxisorder!( - spref::T, - order::Symbol - )::T where {T <: AbstractSpatialRef} +function maybesetaxisorder!(spref::T, order::Symbol)::T where {T<:AbstractSpatialRef} if order == :trad - GDAL.osrsetaxismappingstrategy( - spref.ptr, - GDAL.OAMS_TRADITIONAL_GIS_ORDER - ) + GDAL.osrsetaxismappingstrategy(spref.ptr, GDAL.OAMS_TRADITIONAL_GIS_ORDER) elseif order != :compliant - throw(ArgumentError( - "order $order is not supported. Use :trad or :compliant" - )) + throw(ArgumentError("order $order is not supported. Use :trad or :compliant")) end return spref end @@ -282,7 +257,7 @@ These support files are normally searched for in /usr/local/share/gdal or in the directory identified by the GDAL_DATA configuration option. See CPLFindFile() for details. """ -function importEPSG!(spref::T, code::Integer)::T where {T <: AbstractSpatialRef} +function importEPSG!(spref::T, code::Integer)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromepsg(spref.ptr, code) @ogrerr result "Failed to initialize SRS based on EPSG" return spref @@ -316,10 +291,7 @@ are also a few projected coordinate systems that use northing/easting order contrary to typical GIS use). See `importFromEPSG()` for more details on operation of this method. """ -function importEPSGA!( - spref::T, - code::Integer - )::T where {T <: AbstractSpatialRef} +function importEPSGA!(spref::T, code::Integer)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromepsga(spref.ptr, code) @ogrerr result "Failed to initializ SRS based on EPSGA" return spref @@ -358,10 +330,7 @@ contents of the passed WKT string. Only as much of the input string as needed to construct this SRS is consumed from the input string, and the input string pointer is then updated to point to the remaining (unused) input. """ -function importWKT!( - spref::T, - wktstr::AbstractString - )::T where {T <: AbstractSpatialRef} +function importWKT!(spref::T, wktstr::AbstractString)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromwkt(spref.ptr, [wktstr]) @ogrerr result "Failed to initialize SRS based on WKT string" return spref @@ -377,10 +346,9 @@ Create SRS from its WKT string. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importWKT(wktstr::AbstractString; kwargs...)::ISpatialRef = - newspatialref(wktstr; kwargs...) +importWKT(wktstr::AbstractString; kwargs...)::ISpatialRef = newspatialref(wktstr; kwargs...) -unsafe_importWKT(wktstr::AbstractString; kwargs...)::SpatialRef = +unsafe_importWKT(wktstr::AbstractString; kwargs...)::SpatialRef = unsafe_newspatialref(wktstr; kwargs...) """ @@ -405,10 +373,7 @@ back to PROJ.4 format\". For example: `\"+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext\"` """ -function importPROJ4!( - spref::T, - projstr::AbstractString - )::T where {T <: AbstractSpatialRef} +function importPROJ4!(spref::T, projstr::AbstractString)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromproj4(spref.ptr, projstr) @ogrerr result "Failed to initialize SRS based on PROJ4 string" return spref @@ -452,10 +417,7 @@ At this time there is no equivalent `exportToESRI()` method. Writing old style and `exportToWkt()` methods can be used to generate output suitable to write to new style (Arc 8) .prj files. """ -function importESRI!( - spref::T, - esristr::AbstractString - )::T where {T <: AbstractSpatialRef} +function importESRI!(spref::T, esristr::AbstractString)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromesri(spref.ptr, [esristr]) @ogrerr result "Failed to initialize SRS based on ESRI string" return spref @@ -480,10 +442,7 @@ unsafe_importESRI(esristr::AbstractString; kwargs...)::SpatialRef = Import SRS from XML format (GML only currently). """ -function importXML!( - spref::T, - xmlstr::AbstractString - )::T where {T <: AbstractSpatialRef} +function importXML!(spref::T, xmlstr::AbstractString)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromxml(spref.ptr, xmlstr) @ogrerr result "Failed to initialize SRS based on XML string" return spref @@ -516,10 +475,7 @@ Set spatial reference from a URL. This method will download the spatial reference at a given URL and feed it into SetFromUserInput for you. """ -function importURL!( - spref::T, - url::AbstractString - )::T where {T <: AbstractSpatialRef} +function importURL!(spref::T, url::AbstractString)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromurl(spref.ptr, url) @ogrerr result "Failed to initialize SRS from URL" return spref @@ -538,10 +494,10 @@ SetFromUserInput for you. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importURL(url::AbstractString; kwargs...)::ISpatialRef = +importURL(url::AbstractString; kwargs...)::ISpatialRef = importURL!(newspatialref(; kwargs...), url) -unsafe_importURL(url::AbstractString; kwargs...)::SpatialRef = +unsafe_importURL(url::AbstractString; kwargs...)::SpatialRef = importURL!(unsafe_newspatialref(; kwargs...), url) """ @@ -623,7 +579,7 @@ closely map onto the ESRI concept of WKT format. This includes renaming a variety of projections and arguments, and stripping out nodes note recognised by ESRI (like AUTHORITY and AXIS). """ -function morphtoESRI!(spref::T)::T where {T <: AbstractSpatialRef} +function morphtoESRI!(spref::T)::T where {T<:AbstractSpatialRef} result = GDAL.osrmorphtoesri(spref.ptr) @ogrerr result "Failed to convert in place to ESRI WKT format" return spref @@ -657,7 +613,7 @@ of the following (`TOWGS84` recommended for proper datum shift calculations) `importFromEPSG(n)`, using `EPSG` code `n` corresponding to the existing `GEOGCS`. Does not impact `PROJCS` values. """ -function morphfromESRI!(spref::T)::T where {T <: AbstractSpatialRef} +function morphfromESRI!(spref::T)::T where {T<:AbstractSpatialRef} result = GDAL.osrmorphfromesri(spref.ptr) @ogrerr result "Failed to convert in place from ESRI WKT format" return spref @@ -679,19 +635,16 @@ the value otherwise the zeroth child will be assigned the value. out if you just want to force creation of the intermediate path. """ function setattrvalue!( - spref::T, - path::AbstractString, - value::AbstractString - )::T where {T <: AbstractSpatialRef} + spref::T, + path::AbstractString, + value::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrsetattrvalue(spref.ptr, path, value) @ogrerr result "Failed to set attribute path to value" return spref end -function setattrvalue!( - spref::T, - path::AbstractString - )::T where {T <: AbstractSpatialRef} +function setattrvalue!(spref::T, path::AbstractString)::T where {T<:AbstractSpatialRef} result = GDAL.osrsetattrvalue(spref.ptr, path, C_NULL) @ogrerr result "Failed to set attribute path" return spref @@ -715,10 +668,10 @@ Returns the requested value, or `nothing` if it fails for any reason. """ function getattrvalue( - spref::AbstractSpatialRef, - name::AbstractString, - i::Integer - )::Union{String, Nothing} + spref::AbstractSpatialRef, + name::AbstractString, + i::Integer, +)::Union{String,Nothing} return GDAL.osrgetattrvalue(spref.ptr, name, i) end @@ -736,11 +689,10 @@ Create transformation object. NULL on failure or a ready to use transformation object. """ function unsafe_createcoordtrans( - source::AbstractSpatialRef, - target::AbstractSpatialRef - )::CoordTransform - return CoordTransform(GDAL.octnewcoordinatetransformation(source.ptr, - target.ptr)) + source::AbstractSpatialRef, + target::AbstractSpatialRef, +)::CoordTransform + return CoordTransform(GDAL.octnewcoordinatetransformation(source.ptr, target.ptr)) end "OGRCoordinateTransformation destructor." @@ -764,16 +716,23 @@ Transform points from source to destination space. `true` on success, or `false` if some or all points fail to transform. """ function transform!( - xvertices::Vector{Cdouble}, - yvertices::Vector{Cdouble}, - zvertices::Vector{Cdouble}, - obj::CoordTransform - )::Bool + xvertices::Vector{Cdouble}, + yvertices::Vector{Cdouble}, + zvertices::Vector{Cdouble}, + obj::CoordTransform, +)::Bool # The method TransformEx() allows extended success information to be # captured indicating which points failed to transform. n = length(xvertices) @assert length(yvertices) == n @assert length(zvertices) == n - return Bool(GDAL.octtransform(obj.ptr, n, pointer(xvertices), - pointer(yvertices), pointer(zvertices))) + return Bool( + GDAL.octtransform( + obj.ptr, + n, + pointer(xvertices), + pointer(yvertices), + pointer(zvertices), + ), + ) end diff --git a/src/tables.jl b/src/tables.jl index 884e4c61..6f6a9c12 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -3,29 +3,23 @@ A tabular representation of a `FeatureLayer` Every row is a `Feature` consisting of Geometry and attributes. """ -struct Table{T <: AbstractFeatureLayer} +struct Table{T<:AbstractFeatureLayer} layer::T end function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema - field_names, geom_names, featuredefn, fielddefns = - schema_names(layerdefn(layer)) + field_names, geom_names, featuredefn, fielddefns = schema_names(layerdefn(layer)) ngeom = ArchGDAL.ngeom(featuredefn) - geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) - field_types = ( - convert(DataType, gettype(fielddefn)) for fielddefn in fielddefns - ) - geom_types = (IGeometry for i in 1:ngeom) - Tables.Schema( - (field_names..., geom_names...), - (field_types..., geom_types...) - ) + geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i = 0:ngeom-1) + field_types = (convert(DataType, gettype(fielddefn)) for fielddefn in fielddefns) + geom_types = (IGeometry for i = 1:ngeom) + Tables.Schema((field_names..., geom_names...), (field_types..., geom_types...)) end Tables.istable(::Type{<:Table})::Bool = true Tables.rowaccess(::Type{<:Table})::Bool = true -function Tables.rows(t::Table{T})::T where {T <: AbstractFeatureLayer} +function Tables.rows(t::Table{T})::T where {T<:AbstractFeatureLayer} return t.layer end @@ -51,20 +45,16 @@ function Tables.getcolumn(row::Feature, name::Symbol) return nothing end -function Tables.columnnames( - row::Feature - )::NTuple{Int64(nfield(row) + ngeom(row)), Symbol} +function Tables.columnnames(row::Feature)::NTuple{Int64(nfield(row) + ngeom(row)),Symbol} field_names, geom_names = schema_names(getfeaturedefn(row)) return (field_names..., geom_names...) end function schema_names(featuredefn::IFeatureDefnView) - fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(featuredefn)-1) + fielddefns = (getfielddefn(featuredefn, i) for i = 0:nfield(featuredefn)-1) field_names = (Symbol(getname(fielddefn)) for fielddefn in fielddefns) - geom_names = ( - Symbol(getname(getgeomdefn(featuredefn, i - 1))) - for i in 1:ngeom(featuredefn) - ) + geom_names = + (Symbol(getname(getgeomdefn(featuredefn, i - 1))) for i = 1:ngeom(featuredefn)) return (field_names, geom_names, featuredefn, fielddefns) end diff --git a/src/types.jl b/src/types.jl index b517ce5c..1f7fdbe4 100644 --- a/src/types.jl +++ b/src/types.jl @@ -2,28 +2,28 @@ import DiskArrays: AbstractDiskArray import Base.convert abstract type AbstractGeometry <: GeoInterface.AbstractGeometry end - # needs to have a `ptr::GDAL.OGRGeometryH` attribute +# needs to have a `ptr::GDAL.OGRGeometryH` attribute abstract type AbstractSpatialRef end - # needs to have a `ptr::GDAL.OGRSpatialReferenceH` attribute +# needs to have a `ptr::GDAL.OGRSpatialReferenceH` attribute abstract type AbstractDataset end - # needs to have a `ptr::GDAL.GDALDatasetH` attribute +# needs to have a `ptr::GDAL.GDALDatasetH` attribute abstract type AbstractFeatureDefn end - # needs to have a `ptr::GDAL.OGRFeatureDefnH` attribute +# needs to have a `ptr::GDAL.OGRFeatureDefnH` attribute abstract type AbstractFeatureLayer end - # needs to have a `ptr::GDAL.OGRLayerH` attribute +# needs to have a `ptr::GDAL.OGRLayerH` attribute abstract type AbstractFieldDefn end - # needs to have a `ptr::GDAL.OGRFieldDefnH` attribute +# needs to have a `ptr::GDAL.OGRFieldDefnH` attribute abstract type AbstractGeomFieldDefn end - # needs to have a `ptr::GDAL.OGRGeomFieldDefnH` attribute +# needs to have a `ptr::GDAL.OGRGeomFieldDefnH` attribute abstract type AbstractRasterBand{T} <: AbstractDiskArray{T,2} end - # needs to have a `ptr::GDAL.GDALRasterBandH` attribute +# needs to have a `ptr::GDAL.GDALRasterBandH` attribute mutable struct CoordTransform ptr::GDAL.OGRCoordinateTransformationH @@ -72,9 +72,9 @@ mutable struct GeomFieldDefn <: AbstractGeomFieldDefn spatialref::AbstractSpatialRef function GeomFieldDefn( - ptr::GDAL.OGRGeomFieldDefnH = C_NULL; - spatialref::AbstractSpatialRef = SpatialRef() - ) + ptr::GDAL.OGRGeomFieldDefnH = C_NULL; + spatialref::AbstractSpatialRef = SpatialRef(), + ) return new(ptr, spatialref) end end @@ -119,10 +119,10 @@ mutable struct IFeatureLayer <: AbstractFeatureLayer spatialref::AbstractSpatialRef function IFeatureLayer( - ptr::GDAL.OGRLayerH = C_NULL; - ownedby::AbstractDataset = Dataset(), - spatialref::AbstractSpatialRef = SpatialRef() - ) + ptr::GDAL.OGRLayerH = C_NULL; + ownedby::AbstractDataset = Dataset(), + spatialref::AbstractSpatialRef = SpatialRef(), + ) layer = new(ptr, ownedby, spatialref) finalizer(destroy, layer) return layer @@ -163,9 +163,9 @@ mutable struct IRasterBand{T} <: AbstractRasterBand{T} ownedby::AbstractDataset function IRasterBand{T}( - ptr::GDAL.GDALRasterBandH = C_NULL; - ownedby::AbstractDataset = Dataset() - )::IRasterBand{T} where T + ptr::GDAL.GDALRasterBandH = C_NULL; + ownedby::AbstractDataset = Dataset(), + )::IRasterBand{T} where {T} rasterband = new(ptr, ownedby) finalizer(destroy, rasterband) return rasterband @@ -173,9 +173,9 @@ mutable struct IRasterBand{T} <: AbstractRasterBand{T} end function IRasterBand( - ptr::GDAL.GDALRasterBandH; - ownedby = Dataset() - )::IRasterBand{pixeltype(ptr)} + ptr::GDAL.GDALRasterBandH; + ownedby = Dataset(), +)::IRasterBand{pixeltype(ptr)} return IRasterBand{pixeltype(ptr)}(ptr, ownedby = ownedby) end @@ -215,259 +215,307 @@ mutable struct ColorTable ptr::GDAL.GDALColorTableH end -eval(@convert(GDALDataType::GDAL.GDALDataType, - GDT_Unknown::GDAL.GDT_Unknown, - GDT_Byte::GDAL.GDT_Byte, - GDT_UInt16::GDAL.GDT_UInt16, - GDT_Int16::GDAL.GDT_Int16, - GDT_UInt32::GDAL.GDT_UInt32, - GDT_Int32::GDAL.GDT_Int32, - GDT_Float32::GDAL.GDT_Float32, - GDT_Float64::GDAL.GDT_Float64, - GDT_CInt16::GDAL.GDT_CInt16, - GDT_CInt32::GDAL.GDT_CInt32, - GDT_CFloat32::GDAL.GDT_CFloat32, - GDT_CFloat64::GDAL.GDT_CFloat64, - GDT_TypeCount::GDAL.GDT_TypeCount, -)) - -eval(@convert(GDALDataType::ImageCore.Normed, - GDT_Byte::ImageCore.N0f8, - GDT_UInt16::ImageCore.N0f16, - GDT_UInt32::ImageCore.N0f32, -)) - -eval(@convert(GDALDataType::DataType, - GDT_Unknown::Any, - GDT_Byte::UInt8, - GDT_UInt16::UInt16, - GDT_Int16::Int16, - GDT_UInt32::UInt32, - GDT_Int32::Int32, - GDT_Float32::Float32, - GDT_Float64::Float64, -)) - -eval(@convert(OGRFieldType::GDAL.OGRFieldType, - OFTInteger::GDAL.OFTInteger, - OFTIntegerList::GDAL.OFTIntegerList, - OFTReal::GDAL.OFTReal, - OFTRealList::GDAL.OFTRealList, - OFTString::GDAL.OFTString, - OFTStringList::GDAL.OFTStringList, - OFTWideString::GDAL.OFTWideString, - OFTWideStringList::GDAL.OFTWideStringList, - OFTBinary::GDAL.OFTBinary, - OFTDate::GDAL.OFTDate, - OFTTime::GDAL.OFTTime, - OFTDateTime::GDAL.OFTDateTime, - OFTInteger64::GDAL.OFTInteger64, - OFTInteger64List::GDAL.OFTInteger64List, -)) - -eval(@convert(OGRFieldType::DataType, - OFTInteger::Int32, - OFTIntegerList::Vector{Int32}, - OFTReal::Float64, - OFTRealList::Vector{Float64}, - OFTString::String, - OFTStringList::Vector{String}, - OFTWideString::Nothing, - OFTWideStringList::Nothing, - OFTBinary::Vector{UInt8}, - OFTDate::Dates.Date, - OFTTime::Dates.Time, - OFTDateTime::Dates.DateTime, - OFTInteger64::Int64, - OFTInteger64List::Vector{Int64}, -)) - -eval(@convert(OGRFieldSubType::GDAL.OGRFieldSubType, - OFSTNone::GDAL.OFSTNone, - OFSTBoolean::GDAL.OFSTBoolean, - OFSTInt16::GDAL.OFSTInt16, - OFSTFloat32::GDAL.OFSTFloat32, - OFSTJSON::GDAL.OFSTJSON, -)) - -eval(@convert(OGRFieldSubType::DataType, - OFSTNone::Nothing, - OFSTBoolean::Bool, - OFSTInt16::Int16, - OFSTFloat32::Float32, - OFSTJSON::String, -)) - -eval(@convert(OGRJustification::GDAL.OGRJustification, - OJUndefined::GDAL.OJUndefined, - OJLeft::GDAL.OJLeft, - OJRight::GDAL.OJRight, -)) - -eval(@convert(GDALRATFieldType::GDAL.GDALRATFieldType, - GFT_Integer::GDAL.GFT_Integer, - GFT_Real::GDAL.GFT_Real, - GFT_String::GDAL.GFT_String, -)) - -eval(@convert(GDALRATFieldUsage::GDAL.GDALRATFieldUsage, - GFU_Generic::GDAL.GFU_Generic, - GFU_PixelCount::GDAL.GFU_PixelCount, - GFU_Name::GDAL.GFU_Name, - GFU_Min::GDAL.GFU_Min, - GFU_Max::GDAL.GFU_Max, - GFU_MinMax::GDAL.GFU_MinMax, - GFU_Red::GDAL.GFU_Red, - GFU_Green::GDAL.GFU_Green, - GFU_Blue::GDAL.GFU_Blue, - GFU_Alpha::GDAL.GFU_Alpha, - GFU_RedMin::GDAL.GFU_RedMin, - GFU_GreenMin::GDAL.GFU_GreenMin, - GFU_BlueMin::GDAL.GFU_BlueMin, - GFU_AlphaMin::GDAL.GFU_AlphaMin, - GFU_RedMax::GDAL.GFU_RedMax, - GFU_GreenMax::GDAL.GFU_GreenMax, - GFU_BlueMax::GDAL.GFU_BlueMax, - GFU_AlphaMax::GDAL.GFU_AlphaMax, - GFU_MaxCount::GDAL.GFU_MaxCount, -)) - -eval(@convert(GDALAccess::GDAL.GDALAccess, - GA_ReadOnly::GDAL.GA_ReadOnly, - GA_Update::GDAL.GA_Update, -)) - -eval(@convert(GDALRWFlag::GDAL.GDALRWFlag, - GF_Read::GDAL.GF_Read, - GF_Write::GDAL.GF_Write, -)) - -eval(@convert(GDALPaletteInterp::GDAL.GDALPaletteInterp, - GPI_Gray::GDAL.GPI_Gray, - GPI_RGB::GDAL.GPI_RGB, - GPI_CMYK::GDAL.GPI_CMYK, - GPI_HLS::GDAL.GPI_HLS, -)) - -eval(@convert(GDALColorInterp::GDAL.GDALColorInterp, - GCI_Undefined::GDAL.GCI_Undefined, - GCI_GrayIndex::GDAL.GCI_GrayIndex, - GCI_PaletteIndex::GDAL.GCI_PaletteIndex, - GCI_RedBand::GDAL.GCI_RedBand, - GCI_GreenBand::GDAL.GCI_GreenBand, - GCI_BlueBand::GDAL.GCI_BlueBand, - GCI_AlphaBand::GDAL.GCI_AlphaBand, - GCI_HueBand::GDAL.GCI_HueBand, - GCI_SaturationBand::GDAL.GCI_SaturationBand, - GCI_LightnessBand::GDAL.GCI_LightnessBand, - GCI_CyanBand::GDAL.GCI_CyanBand, - GCI_MagentaBand::GDAL.GCI_MagentaBand, - GCI_YellowBand::GDAL.GCI_YellowBand, - GCI_BlackBand::GDAL.GCI_BlackBand, - GCI_YCbCr_YBand::GDAL.GCI_YCbCr_YBand, - GCI_YCbCr_CbBand::GDAL.GCI_YCbCr_CbBand, - GCI_YCbCr_CrBand::GDAL.GCI_YCbCr_CrBand, -)) - -eval(@convert(GDALAsyncStatusType::GDAL.GDALAsyncStatusType, - GARIO_PENDING::GDAL.GARIO_PENDING, - GARIO_UPDATE::GDAL.GARIO_UPDATE, - GARIO_ERROR::GDAL.GARIO_ERROR, - GARIO_COMPLETE::GDAL.GARIO_COMPLETE, - GARIO_TypeCount::GDAL.GARIO_TypeCount, -)) - -eval(@convert(OGRSTClassId::GDAL.OGRSTClassId, - OGRSTCNone::GDAL.OGRSTCNone, - OGRSTCPen::GDAL.OGRSTCPen, - OGRSTCBrush::GDAL.OGRSTCBrush, - OGRSTCSymbol::GDAL.OGRSTCSymbol, - OGRSTCLabel::GDAL.OGRSTCLabel, - OGRSTCVector::GDAL.OGRSTCVector, -)) - -eval(@convert(OGRSTUnitId::GDAL.OGRSTUnitId, - OGRSTUGround::GDAL.OGRSTUGround, - OGRSTUPixel::GDAL.OGRSTUPixel, - OGRSTUPoints::GDAL.OGRSTUPoints, - OGRSTUMM::GDAL.OGRSTUMM, - OGRSTUCM::GDAL.OGRSTUCM, - OGRSTUInches::GDAL.OGRSTUInches, -)) - -eval(@convert(OGRwkbGeometryType::GDAL.OGRwkbGeometryType, - wkbUnknown::GDAL.wkbUnknown, - wkbPoint::GDAL.wkbPoint, - wkbLineString::GDAL.wkbLineString, - wkbPolygon::GDAL.wkbPolygon, - wkbMultiPoint::GDAL.wkbMultiPoint, - wkbMultiLineString::GDAL.wkbMultiLineString, - wkbMultiPolygon::GDAL.wkbMultiPolygon, - wkbGeometryCollection::GDAL.wkbGeometryCollection, - wkbCircularString::GDAL.wkbCircularString, - wkbCompoundCurve::GDAL.wkbCompoundCurve, - wkbCurvePolygon::GDAL.wkbCurvePolygon, - wkbMultiCurve::GDAL.wkbMultiCurve, - wkbMultiSurface::GDAL.wkbMultiSurface, - wkbCurve::GDAL.wkbCurve, - wkbSurface::GDAL.wkbSurface, - wkbPolyhedralSurface::GDAL.wkbPolyhedralSurface, - wkbTIN::GDAL.wkbTIN, - wkbTriangle::GDAL.wkbTriangle, - wkbNone::GDAL.wkbNone, - wkbLinearRing::GDAL.wkbLinearRing, - wkbCircularStringZ::GDAL.wkbCircularStringZ, - wkbCompoundCurveZ::GDAL.wkbCompoundCurveZ, - wkbCurvePolygonZ::GDAL.wkbCurvePolygonZ, - wkbMultiCurveZ::GDAL.wkbMultiCurveZ, - wkbMultiSurfaceZ::GDAL.wkbMultiSurfaceZ, - wkbCurveZ::GDAL.wkbCurveZ, - wkbSurfaceZ::GDAL.wkbSurfaceZ, - wkbPolyhedralSurfaceZ::GDAL.wkbPolyhedralSurfaceZ, - wkbTINZ::GDAL.wkbTINZ, - wkbTriangleZ::GDAL.wkbTriangleZ, - wkbPointM::GDAL.wkbPointM, - wkbLineStringM::GDAL.wkbLineStringM, - wkbPolygonM::GDAL.wkbPolygonM, - wkbMultiPointM::GDAL.wkbMultiPointM, - wkbMultiLineStringM::GDAL.wkbMultiLineStringM, - wkbMultiPolygonM::GDAL.wkbMultiPolygonM, - wkbGeometryCollectionM::GDAL.wkbGeometryCollectionM, - wkbCircularStringM::GDAL.wkbCircularStringM, - wkbCompoundCurveM::GDAL.wkbCompoundCurveM, - wkbCurvePolygonM::GDAL.wkbCurvePolygonM, - wkbMultiCurveM::GDAL.wkbMultiCurveM, - wkbMultiSurfaceM::GDAL.wkbMultiSurfaceM, - wkbCurveM::GDAL.wkbCurveM, - wkbSurfaceM::GDAL.wkbSurfaceM, - wkbPolyhedralSurfaceM::GDAL.wkbPolyhedralSurfaceM, - wkbTINM::GDAL.wkbTINM, - wkbTriangleM::GDAL.wkbTriangleM, - wkbPointZM::GDAL.wkbPointZM, - wkbLineStringZM::GDAL.wkbLineStringZM, - wkbPolygonZM::GDAL.wkbPolygonZM, - wkbMultiPointZM::GDAL.wkbMultiPointZM, - wkbMultiLineStringZM::GDAL.wkbMultiLineStringZM, - wkbMultiPolygonZM::GDAL.wkbMultiPolygonZM, - wkbGeometryCollectionZM::GDAL.wkbGeometryCollectionZM, - wkbCircularStringZM::GDAL.wkbCircularStringZM, - wkbCompoundCurveZM::GDAL.wkbCompoundCurveZM, - wkbCurvePolygonZM::GDAL.wkbCurvePolygonZM, - wkbMultiCurveZM::GDAL.wkbMultiCurveZM, - wkbMultiSurfaceZM::GDAL.wkbMultiSurfaceZM, - wkbCurveZM::GDAL.wkbCurveZM, - wkbSurfaceZM::GDAL.wkbSurfaceZM, - wkbPolyhedralSurfaceZM::GDAL.wkbPolyhedralSurfaceZM, - wkbTINZM::GDAL.wkbTINZM, - wkbTriangleZM::GDAL.wkbTriangleZM, - wkbPoint25D::GDAL.wkbPoint25D, - wkbLineString25D::GDAL.wkbLineString25D, - wkbPolygon25D::GDAL.wkbPolygon25D, - wkbMultiPoint25D::GDAL.wkbMultiPoint25D, - wkbMultiLineString25D::GDAL.wkbMultiLineString25D, - wkbMultiPolygon25D::GDAL.wkbMultiPolygon25D, - wkbGeometryCollection25D::GDAL.wkbGeometryCollection25D, -)) +eval( + @convert( + GDALDataType::GDAL.GDALDataType, + GDT_Unknown::GDAL.GDT_Unknown, + GDT_Byte::GDAL.GDT_Byte, + GDT_UInt16::GDAL.GDT_UInt16, + GDT_Int16::GDAL.GDT_Int16, + GDT_UInt32::GDAL.GDT_UInt32, + GDT_Int32::GDAL.GDT_Int32, + GDT_Float32::GDAL.GDT_Float32, + GDT_Float64::GDAL.GDT_Float64, + GDT_CInt16::GDAL.GDT_CInt16, + GDT_CInt32::GDAL.GDT_CInt32, + GDT_CFloat32::GDAL.GDT_CFloat32, + GDT_CFloat64::GDAL.GDT_CFloat64, + GDT_TypeCount::GDAL.GDT_TypeCount, + ) +) + +eval( + @convert( + GDALDataType::ImageCore.Normed, + GDT_Byte::ImageCore.N0f8, + GDT_UInt16::ImageCore.N0f16, + GDT_UInt32::ImageCore.N0f32, + ) +) + +eval( + @convert( + GDALDataType::DataType, + GDT_Unknown::Any, + GDT_Byte::UInt8, + GDT_UInt16::UInt16, + GDT_Int16::Int16, + GDT_UInt32::UInt32, + GDT_Int32::Int32, + GDT_Float32::Float32, + GDT_Float64::Float64, + ) +) + +eval( + @convert( + OGRFieldType::GDAL.OGRFieldType, + OFTInteger::GDAL.OFTInteger, + OFTIntegerList::GDAL.OFTIntegerList, + OFTReal::GDAL.OFTReal, + OFTRealList::GDAL.OFTRealList, + OFTString::GDAL.OFTString, + OFTStringList::GDAL.OFTStringList, + OFTWideString::GDAL.OFTWideString, + OFTWideStringList::GDAL.OFTWideStringList, + OFTBinary::GDAL.OFTBinary, + OFTDate::GDAL.OFTDate, + OFTTime::GDAL.OFTTime, + OFTDateTime::GDAL.OFTDateTime, + OFTInteger64::GDAL.OFTInteger64, + OFTInteger64List::GDAL.OFTInteger64List, + ) +) + +eval( + @convert( + OGRFieldType::DataType, + OFTInteger::Int32, + OFTIntegerList::Vector{Int32}, + OFTReal::Float64, + OFTRealList::Vector{Float64}, + OFTString::String, + OFTStringList::Vector{String}, + OFTWideString::Nothing, + OFTWideStringList::Nothing, + OFTBinary::Vector{UInt8}, + OFTDate::Dates.Date, + OFTTime::Dates.Time, + OFTDateTime::Dates.DateTime, + OFTInteger64::Int64, + OFTInteger64List::Vector{Int64}, + ) +) + +eval( + @convert( + OGRFieldSubType::GDAL.OGRFieldSubType, + OFSTNone::GDAL.OFSTNone, + OFSTBoolean::GDAL.OFSTBoolean, + OFSTInt16::GDAL.OFSTInt16, + OFSTFloat32::GDAL.OFSTFloat32, + OFSTJSON::GDAL.OFSTJSON, + ) +) + +eval( + @convert( + OGRFieldSubType::DataType, + OFSTNone::Nothing, + OFSTBoolean::Bool, + OFSTInt16::Int16, + OFSTFloat32::Float32, + OFSTJSON::String, + ) +) + +eval( + @convert( + OGRJustification::GDAL.OGRJustification, + OJUndefined::GDAL.OJUndefined, + OJLeft::GDAL.OJLeft, + OJRight::GDAL.OJRight, + ) +) + +eval( + @convert( + GDALRATFieldType::GDAL.GDALRATFieldType, + GFT_Integer::GDAL.GFT_Integer, + GFT_Real::GDAL.GFT_Real, + GFT_String::GDAL.GFT_String, + ) +) + +eval( + @convert( + GDALRATFieldUsage::GDAL.GDALRATFieldUsage, + GFU_Generic::GDAL.GFU_Generic, + GFU_PixelCount::GDAL.GFU_PixelCount, + GFU_Name::GDAL.GFU_Name, + GFU_Min::GDAL.GFU_Min, + GFU_Max::GDAL.GFU_Max, + GFU_MinMax::GDAL.GFU_MinMax, + GFU_Red::GDAL.GFU_Red, + GFU_Green::GDAL.GFU_Green, + GFU_Blue::GDAL.GFU_Blue, + GFU_Alpha::GDAL.GFU_Alpha, + GFU_RedMin::GDAL.GFU_RedMin, + GFU_GreenMin::GDAL.GFU_GreenMin, + GFU_BlueMin::GDAL.GFU_BlueMin, + GFU_AlphaMin::GDAL.GFU_AlphaMin, + GFU_RedMax::GDAL.GFU_RedMax, + GFU_GreenMax::GDAL.GFU_GreenMax, + GFU_BlueMax::GDAL.GFU_BlueMax, + GFU_AlphaMax::GDAL.GFU_AlphaMax, + GFU_MaxCount::GDAL.GFU_MaxCount, + ) +) + +eval( + @convert( + GDALAccess::GDAL.GDALAccess, + GA_ReadOnly::GDAL.GA_ReadOnly, + GA_Update::GDAL.GA_Update, + ) +) + +eval(@convert(GDALRWFlag::GDAL.GDALRWFlag, GF_Read::GDAL.GF_Read, GF_Write::GDAL.GF_Write,)) + +eval( + @convert( + GDALPaletteInterp::GDAL.GDALPaletteInterp, + GPI_Gray::GDAL.GPI_Gray, + GPI_RGB::GDAL.GPI_RGB, + GPI_CMYK::GDAL.GPI_CMYK, + GPI_HLS::GDAL.GPI_HLS, + ) +) + +eval( + @convert( + GDALColorInterp::GDAL.GDALColorInterp, + GCI_Undefined::GDAL.GCI_Undefined, + GCI_GrayIndex::GDAL.GCI_GrayIndex, + GCI_PaletteIndex::GDAL.GCI_PaletteIndex, + GCI_RedBand::GDAL.GCI_RedBand, + GCI_GreenBand::GDAL.GCI_GreenBand, + GCI_BlueBand::GDAL.GCI_BlueBand, + GCI_AlphaBand::GDAL.GCI_AlphaBand, + GCI_HueBand::GDAL.GCI_HueBand, + GCI_SaturationBand::GDAL.GCI_SaturationBand, + GCI_LightnessBand::GDAL.GCI_LightnessBand, + GCI_CyanBand::GDAL.GCI_CyanBand, + GCI_MagentaBand::GDAL.GCI_MagentaBand, + GCI_YellowBand::GDAL.GCI_YellowBand, + GCI_BlackBand::GDAL.GCI_BlackBand, + GCI_YCbCr_YBand::GDAL.GCI_YCbCr_YBand, + GCI_YCbCr_CbBand::GDAL.GCI_YCbCr_CbBand, + GCI_YCbCr_CrBand::GDAL.GCI_YCbCr_CrBand, + ) +) + +eval( + @convert( + GDALAsyncStatusType::GDAL.GDALAsyncStatusType, + GARIO_PENDING::GDAL.GARIO_PENDING, + GARIO_UPDATE::GDAL.GARIO_UPDATE, + GARIO_ERROR::GDAL.GARIO_ERROR, + GARIO_COMPLETE::GDAL.GARIO_COMPLETE, + GARIO_TypeCount::GDAL.GARIO_TypeCount, + ) +) + +eval( + @convert( + OGRSTClassId::GDAL.OGRSTClassId, + OGRSTCNone::GDAL.OGRSTCNone, + OGRSTCPen::GDAL.OGRSTCPen, + OGRSTCBrush::GDAL.OGRSTCBrush, + OGRSTCSymbol::GDAL.OGRSTCSymbol, + OGRSTCLabel::GDAL.OGRSTCLabel, + OGRSTCVector::GDAL.OGRSTCVector, + ) +) + +eval( + @convert( + OGRSTUnitId::GDAL.OGRSTUnitId, + OGRSTUGround::GDAL.OGRSTUGround, + OGRSTUPixel::GDAL.OGRSTUPixel, + OGRSTUPoints::GDAL.OGRSTUPoints, + OGRSTUMM::GDAL.OGRSTUMM, + OGRSTUCM::GDAL.OGRSTUCM, + OGRSTUInches::GDAL.OGRSTUInches, + ) +) + +eval( + @convert( + OGRwkbGeometryType::GDAL.OGRwkbGeometryType, + wkbUnknown::GDAL.wkbUnknown, + wkbPoint::GDAL.wkbPoint, + wkbLineString::GDAL.wkbLineString, + wkbPolygon::GDAL.wkbPolygon, + wkbMultiPoint::GDAL.wkbMultiPoint, + wkbMultiLineString::GDAL.wkbMultiLineString, + wkbMultiPolygon::GDAL.wkbMultiPolygon, + wkbGeometryCollection::GDAL.wkbGeometryCollection, + wkbCircularString::GDAL.wkbCircularString, + wkbCompoundCurve::GDAL.wkbCompoundCurve, + wkbCurvePolygon::GDAL.wkbCurvePolygon, + wkbMultiCurve::GDAL.wkbMultiCurve, + wkbMultiSurface::GDAL.wkbMultiSurface, + wkbCurve::GDAL.wkbCurve, + wkbSurface::GDAL.wkbSurface, + wkbPolyhedralSurface::GDAL.wkbPolyhedralSurface, + wkbTIN::GDAL.wkbTIN, + wkbTriangle::GDAL.wkbTriangle, + wkbNone::GDAL.wkbNone, + wkbLinearRing::GDAL.wkbLinearRing, + wkbCircularStringZ::GDAL.wkbCircularStringZ, + wkbCompoundCurveZ::GDAL.wkbCompoundCurveZ, + wkbCurvePolygonZ::GDAL.wkbCurvePolygonZ, + wkbMultiCurveZ::GDAL.wkbMultiCurveZ, + wkbMultiSurfaceZ::GDAL.wkbMultiSurfaceZ, + wkbCurveZ::GDAL.wkbCurveZ, + wkbSurfaceZ::GDAL.wkbSurfaceZ, + wkbPolyhedralSurfaceZ::GDAL.wkbPolyhedralSurfaceZ, + wkbTINZ::GDAL.wkbTINZ, + wkbTriangleZ::GDAL.wkbTriangleZ, + wkbPointM::GDAL.wkbPointM, + wkbLineStringM::GDAL.wkbLineStringM, + wkbPolygonM::GDAL.wkbPolygonM, + wkbMultiPointM::GDAL.wkbMultiPointM, + wkbMultiLineStringM::GDAL.wkbMultiLineStringM, + wkbMultiPolygonM::GDAL.wkbMultiPolygonM, + wkbGeometryCollectionM::GDAL.wkbGeometryCollectionM, + wkbCircularStringM::GDAL.wkbCircularStringM, + wkbCompoundCurveM::GDAL.wkbCompoundCurveM, + wkbCurvePolygonM::GDAL.wkbCurvePolygonM, + wkbMultiCurveM::GDAL.wkbMultiCurveM, + wkbMultiSurfaceM::GDAL.wkbMultiSurfaceM, + wkbCurveM::GDAL.wkbCurveM, + wkbSurfaceM::GDAL.wkbSurfaceM, + wkbPolyhedralSurfaceM::GDAL.wkbPolyhedralSurfaceM, + wkbTINM::GDAL.wkbTINM, + wkbTriangleM::GDAL.wkbTriangleM, + wkbPointZM::GDAL.wkbPointZM, + wkbLineStringZM::GDAL.wkbLineStringZM, + wkbPolygonZM::GDAL.wkbPolygonZM, + wkbMultiPointZM::GDAL.wkbMultiPointZM, + wkbMultiLineStringZM::GDAL.wkbMultiLineStringZM, + wkbMultiPolygonZM::GDAL.wkbMultiPolygonZM, + wkbGeometryCollectionZM::GDAL.wkbGeometryCollectionZM, + wkbCircularStringZM::GDAL.wkbCircularStringZM, + wkbCompoundCurveZM::GDAL.wkbCompoundCurveZM, + wkbCurvePolygonZM::GDAL.wkbCurvePolygonZM, + wkbMultiCurveZM::GDAL.wkbMultiCurveZM, + wkbMultiSurfaceZM::GDAL.wkbMultiSurfaceZM, + wkbCurveZM::GDAL.wkbCurveZM, + wkbSurfaceZM::GDAL.wkbSurfaceZM, + wkbPolyhedralSurfaceZM::GDAL.wkbPolyhedralSurfaceZM, + wkbTINZM::GDAL.wkbTINZM, + wkbTriangleZM::GDAL.wkbTriangleZM, + wkbPoint25D::GDAL.wkbPoint25D, + wkbLineString25D::GDAL.wkbLineString25D, + wkbPolygon25D::GDAL.wkbPolygon25D, + wkbMultiPoint25D::GDAL.wkbMultiPoint25D, + wkbMultiLineString25D::GDAL.wkbMultiLineString25D, + wkbMultiPolygon25D::GDAL.wkbMultiPolygon25D, + wkbGeometryCollection25D::GDAL.wkbGeometryCollection25D, + ) +) function basetype(gt::OGRwkbGeometryType)::OGRwkbGeometryType wkbGeomType = convert(GDAL.OGRwkbGeometryType, gt) @@ -476,10 +524,13 @@ function basetype(gt::OGRwkbGeometryType)::OGRwkbGeometryType return GDAL.OGRwkbGeometryType(wkbGeomType) end -eval(@convert(OGRwkbByteOrder::GDAL.OGRwkbByteOrder, - wkbXDR::GDAL.wkbXDR, - wkbNDR::GDAL.wkbNDR, -)) +eval( + @convert( + OGRwkbByteOrder::GDAL.OGRwkbByteOrder, + wkbXDR::GDAL.wkbXDR, + wkbNDR::GDAL.wkbNDR, + ) +) import Base.| @@ -510,8 +561,7 @@ typename(dt::GDALDataType)::String = GDAL.gdalgetdatatypename(dt) Returns GDAL data type by symbolic name. """ -gettype(name::AbstractString)::GDALDataType = - GDAL.gdalgetdatatypebyname(name) +gettype(name::AbstractString)::GDALDataType = GDAL.gdalgetdatatypebyname(name) """ typeunion(dt1::GDALDataType, dt2::GDALDataType) @@ -526,16 +576,14 @@ typeunion(dt1::GDALDataType, dt2::GDALDataType)::GDALDataType = `true` if `dtype` is one of `GDT_{CInt16|CInt32|CFloat32|CFloat64}.` """ -iscomplex(dtype::GDALDataType)::Bool = - Bool(GDAL.gdaldatatypeiscomplex(dtype)) +iscomplex(dtype::GDALDataType)::Bool = Bool(GDAL.gdaldatatypeiscomplex(dtype)) """ getname(dtype::GDALAsyncStatusType) Get name of AsyncStatus data type. """ -getname(dtype::GDALAsyncStatusType)::String = - GDAL.gdalgetasyncstatustypename(dtype) +getname(dtype::GDALAsyncStatusType)::String = GDAL.gdalgetasyncstatustypename(dtype) """ asyncstatustype(name::AbstractString) @@ -550,8 +598,7 @@ asyncstatustype(name::AbstractString)::GDALAsyncStatusType = Return name (string) corresponding to color interpretation. """ -getname(obj::GDALColorInterp)::String = - GDAL.gdalgetcolorinterpretationname(obj) +getname(obj::GDALColorInterp)::String = GDAL.gdalgetcolorinterpretationname(obj) """ colorinterp(name::AbstractString) @@ -566,8 +613,7 @@ colorinterp(name::AbstractString)::GDALColorInterp = Get name of palette interpretation. """ -getname(obj::GDALPaletteInterp)::String = - GDAL.gdalgetpaletteinterpretationname(obj) +getname(obj::GDALPaletteInterp)::String = GDAL.gdalgetpaletteinterpretationname(obj) """ getname(obj::OGRFieldType) diff --git a/src/utilities.jl b/src/utilities.jl index 210c0f8c..7235ec6d 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -32,10 +32,10 @@ Convert raster data between different formats. The output dataset. """ function unsafe_gdaltranslate( - dataset::Dataset, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + dataset::Dataset, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdaltranslateoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdaltranslate(dest, dataset.ptr, options, usage_error) @@ -57,14 +57,20 @@ Image reprojection and warping function. The output dataset. """ function unsafe_gdalwarp( - datasets::Vector{Dataset}, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + datasets::Vector{Dataset}, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdalwarpappoptionsnew(options, C_NULL) usage_error = Ref{Cint}() - result = GDAL.gdalwarp(dest, C_NULL, - length(datasets), [ds.ptr for ds in datasets], options, usage_error) + result = GDAL.gdalwarp( + dest, + C_NULL, + length(datasets), + [ds.ptr for ds in datasets], + options, + usage_error, + ) GDAL.gdalwarpappoptionsfree(options) return Dataset(result) end @@ -83,14 +89,20 @@ Convert vector data between file formats. The output dataset. """ function unsafe_gdalvectortranslate( - datasets::Vector{Dataset}, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + datasets::Vector{Dataset}, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdalvectortranslateoptionsnew(options, C_NULL) usage_error = Ref{Cint}() - result = GDAL.gdalvectortranslate(dest, C_NULL, length(datasets), - [ds.ptr for ds in datasets], options, usage_error) + result = GDAL.gdalvectortranslate( + dest, + C_NULL, + length(datasets), + [ds.ptr for ds in datasets], + options, + usage_error, + ) GDAL.gdalvectortranslateoptionsfree(options) return Dataset(result) end @@ -115,19 +127,25 @@ Tools to analyze and visualize DEMs. The output dataset. """ function unsafe_gdaldem( - dataset::Dataset, - processing::String, - options = String[]; - dest = "/vsimem/tmp", - colorfile = C_NULL - )::Dataset + dataset::Dataset, + processing::String, + options = String[]; + dest = "/vsimem/tmp", + colorfile = C_NULL, +)::Dataset if processing == "color-relief" @assert colorfile != C_NULL end options = GDAL.gdaldemprocessingoptionsnew(options, C_NULL) usage_error = Ref{Cint}() - result = GDAL.gdaldemprocessing(dest, dataset.ptr, processing, colorfile, - options, usage_error) + result = GDAL.gdaldemprocessing( + dest, + dataset.ptr, + processing, + colorfile, + options, + usage_error, + ) GDAL.gdaldemprocessingoptionsfree(options) return Dataset(result) end @@ -146,10 +164,10 @@ Convert nearly black/white borders to exact value. The output dataset. """ function unsafe_gdalnearblack( - dataset::Dataset, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + dataset::Dataset, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdalnearblackoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalnearblack(dest, C_NULL, dataset.ptr, options, usage_error) @@ -171,10 +189,10 @@ Create a raster from the scattered data. The output dataset. """ function unsafe_gdalgrid( - dataset::Dataset, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + dataset::Dataset, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdalgridoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalgrid(dest, dataset.ptr, options, usage_error) @@ -196,10 +214,10 @@ Burn vector geometries into a raster. The output dataset. """ function unsafe_gdalrasterize( - dataset::Dataset, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + dataset::Dataset, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdalrasterizeoptionsnew(options, C_NULL) usage_error = Ref{Cint}() result = GDAL.gdalrasterize(dest, C_NULL, dataset.ptr, options, usage_error) @@ -221,14 +239,20 @@ Build a VRT from a list of datasets. The output dataset. """ function unsafe_gdalbuildvrt( - datasets::Vector{Dataset}, - options = String[]; - dest = "/vsimem/tmp" - )::Dataset + datasets::Vector{Dataset}, + options = String[]; + dest = "/vsimem/tmp", +)::Dataset options = GDAL.gdalbuildvrtoptionsnew(options, C_NULL) usage_error = Ref{Cint}() - result = GDAL.gdalbuildvrt(dest, length(datasets), - [ds.ptr for ds in datasets], C_NULL, options, usage_error) + result = GDAL.gdalbuildvrt( + dest, + length(datasets), + [ds.ptr for ds in datasets], + C_NULL, + options, + usage_error, + ) GDAL.gdalbuildvrtoptionsfree(options) return Dataset(result) end diff --git a/src/utils.jl b/src/utils.jl index 2203e9a9..324ca719 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -25,22 +25,18 @@ macro convert(args...) @assert args[1].head == :(::) type1 = esc(args[1].args[1]) type2 = esc(args[1].args[2]) - forward_map = Expr[ - Expr(:tuple, esc.(a.args)...) for a in args[2:end] - ] - reverse_map = Expr[ - Expr(:tuple, esc.(reverse(a.args))...) for a in args[2:end] - ] + forward_map = Expr[Expr(:tuple, esc.(a.args)...) for a in args[2:end]] + reverse_map = Expr[Expr(:tuple, esc.(reverse(a.args))...) for a in args[2:end]] quote function Base.convert(::Type{$type2}, ft::$type1) - fwd = Dict{$type1, $type2}(Tuple{$type1, $type2}[$(forward_map...)]) + fwd = Dict{$type1,$type2}(Tuple{$type1,$type2}[$(forward_map...)]) return get(fwd, ft) do error("Unknown type: $ft") end end function Base.convert(::Type{$type1}, ft::$type2) - rev = Dict{$type2, $type1}(Tuple{$type2, $type1}[$(reverse_map...)]) + rev = Dict{$type2,$type1}(Tuple{$type2,$type1}[$(reverse_map...)]) return get(rev, ft) do error("Unknown type: $ft") end @@ -55,7 +51,9 @@ macro gdal(args...) returntype = args[1].args[2] argtypes = Expr(:tuple, [esc(a.args[2]) for a in args[2:end]]...) args = [esc(a.args[1]) for a in args[2:end]] - return quote ccall($fhead, $returntype, $argtypes, $(args...)) end + return quote + ccall($fhead, $returntype, $argtypes, $(args...)) + end end macro ogrerr(code, message) @@ -83,7 +81,7 @@ macro cplwarn(code, message) end macro cplprogress(progressfunc) - @cfunction($(esc(progressfunc)),Cint,(Cdouble,Cstring,Ptr{Cvoid})) + @cfunction($(esc(progressfunc)), Cint, (Cdouble, Cstring, Ptr{Cvoid})) end # """ @@ -110,8 +108,7 @@ end Fetch list of (non-empty) metadata domains. """ -metadatadomainlist(obj)::Vector{String} = - GDAL.gdalgetmetadatadomainlist(obj.ptr) +metadatadomainlist(obj)::Vector{String} = GDAL.gdalgetmetadatadomainlist(obj.ptr) """ metadata(obj; domain::AbstractString = "") @@ -133,11 +130,7 @@ Fetch single metadata item. ### Returns The metadata item on success, or an empty string on failure. """ -function metadataitem( - obj, - name::AbstractString; - domain::AbstractString = "" - )::String +function metadataitem(obj, name::AbstractString; domain::AbstractString = "")::String item = GDAL.gdalgetmetadataitem(obj.ptr, name, domain) return isnothing(item) ? "" : item end @@ -196,10 +189,7 @@ it in environment variables. the value associated to the key, or the default value if not found. """ function getconfigoption(option::AbstractString, default = C_NULL)::String - result = @gdal(CPLGetConfigOption::Cstring, - option::Cstring, - default::Cstring - ) + result = @gdal(CPLGetConfigOption::Cstring, option::Cstring, default::Cstring) return (result == C_NULL) ? "" : unsafe_string(result) end @@ -243,9 +233,7 @@ end Same as `getconfigoption()` but with settings from `setthreadconfigoption()`. """ function getthreadconfigoption(option::AbstractString, default = C_NULL)::String - result = @gdal(CPLGetThreadLocalConfigOption::Cstring, - option::Cstring, - default::Cstring - ) + result = + @gdal(CPLGetThreadLocalConfigOption::Cstring, option::Cstring, default::Cstring) return (result == C_NULL) ? "" : unsafe_string(result) end diff --git a/test/remotefiles.jl b/test/remotefiles.jl index 9264d352..be67cead 100644 --- a/test/remotefiles.jl +++ b/test/remotefiles.jl @@ -20,30 +20,102 @@ julia> open(filepath/filename) do f ``` """ remotefiles = [ - ("data/multi_geom.csv", "00520017658b66ff21e40cbf553672fa8e280cddae6e7a5d1f8bd36bcd521770"), - ("data/missing_testcase.csv", "d49ba446aae9ef334350b64c876b4de652f28595fdecf78bea4e16af4033f7c6"), - ("data/point.geojson", "8744593479054a67c784322e0c198bfa880c9388b39a2ddd4c56726944711bd9"), - ("data/color_relief.txt", "f44feef9b8529b3ff9cb64de4d01a3107f99aad7822a0a2d91055e44a915c267"), - ("data/utmsmall.tif", "f40dae6e8b5e18f3648e9f095e22a0d7027014bb463418d32f732c3756d8c54f"), - ("gdalworkshop/world.tif", "b376dc8af62f9894b5050a6a9273ac0763ae2990b556910d35d4a8f4753278bb"), - ("ospy/data1/sites.dbf", "7df95edea06c46418287ae3430887f44f9116b29715783f7d1a11b2b931d6e7d"), - ("ospy/data1/sites.prj", "81fb1a246728609a446b25b0df9ede41c3e7b6a133ce78f10edbd2647fc38ce1"), - ("ospy/data1/sites.sbn", "198d9d695f3e7a0a0ac0ebfd6afbe044b78db3e685fffd241a32396e8b341ed3"), - ("ospy/data1/sites.sbx", "49bbe1942b899d52cf1d1b01ea10bd481ec40bdc4c94ff866aece5e81f2261f6"), - ("ospy/data1/sites.shp", "69af5a6184053f0b71f266dc54c944f1ec02013fb66dbb33412d8b1976d5ea2b"), - ("ospy/data1/sites.shx", "1f3da459ccb151958743171e41e6a01810b2a007305d55666e01d680da7bbf08"), - ("ospy/data2/ut_counties.txt", "06585b736091f5bbc62eb040918b1693b2716f550ab306026732e1dfa6cd49a7"), - ("ospy/data3/cache_towns.dbf", "2344b5195e1a7cbc141f38d6f3214f04c0d43058309b162e877fca755cd1d9fa"), - ("ospy/data3/cache_towns.sbn", "217e938eb0bec1cdccf26d87e5127d395d68b5d660bc1ecc1d7ec7b3f052f4e3"), - ("ospy/data3/cache_towns.sbx", "e027b3f67bbb60fc9cf67ab6f430b286fd8a1eaa6c344edaa7da4327485ee9f2"), - ("ospy/data3/cache_towns.shp", "635998f789d349d80368cb105e7e0d61f95cc6eecd36b34bf005d8c7e966fedb"), - ("ospy/data3/cache_towns.shx", "0cafc504b829a3da2c0363074f775266f9e1f6aaaf1e066b8a613d5862f313b7"), - ("ospy/data4/aster.img", "2423205bdf820b1c2a3f03862664d84ea4b5b899c57ed33afd8962664e80a298"), - ("ospy/data4/aster.rrd", "18e038aabe8fd92b0d12cd4f324bb2e0368343e20cc41e5411a6d038108a25cf"), - ("ospy/data5/doq1.img", "70b8e641c52367107654962e81977be65402aa3c46736a07cb512ce960203bb7"), - ("ospy/data5/doq1.rrd", "f9f2fe57d789977090ec0c31e465052161886e79a4c4e10805b5e7ab28c06177"), - ("ospy/data5/doq2.img", "1e1d744f17e6a3b97dd9b7d8705133c72ff162613bae43ad94417c54e6aced5d"), - ("ospy/data5/doq2.rrd", "8274dad00b27e008e5ada62afb1025b0e6e2ef2d2ff2642487ecaee64befd914"), + ( + "data/multi_geom.csv", + "00520017658b66ff21e40cbf553672fa8e280cddae6e7a5d1f8bd36bcd521770", + ), + ( + "data/missing_testcase.csv", + "d49ba446aae9ef334350b64c876b4de652f28595fdecf78bea4e16af4033f7c6", + ), + ( + "data/point.geojson", + "8744593479054a67c784322e0c198bfa880c9388b39a2ddd4c56726944711bd9", + ), + ( + "data/color_relief.txt", + "f44feef9b8529b3ff9cb64de4d01a3107f99aad7822a0a2d91055e44a915c267", + ), + ( + "data/utmsmall.tif", + "f40dae6e8b5e18f3648e9f095e22a0d7027014bb463418d32f732c3756d8c54f", + ), + ( + "gdalworkshop/world.tif", + "b376dc8af62f9894b5050a6a9273ac0763ae2990b556910d35d4a8f4753278bb", + ), + ( + "ospy/data1/sites.dbf", + "7df95edea06c46418287ae3430887f44f9116b29715783f7d1a11b2b931d6e7d", + ), + ( + "ospy/data1/sites.prj", + "81fb1a246728609a446b25b0df9ede41c3e7b6a133ce78f10edbd2647fc38ce1", + ), + ( + "ospy/data1/sites.sbn", + "198d9d695f3e7a0a0ac0ebfd6afbe044b78db3e685fffd241a32396e8b341ed3", + ), + ( + "ospy/data1/sites.sbx", + "49bbe1942b899d52cf1d1b01ea10bd481ec40bdc4c94ff866aece5e81f2261f6", + ), + ( + "ospy/data1/sites.shp", + "69af5a6184053f0b71f266dc54c944f1ec02013fb66dbb33412d8b1976d5ea2b", + ), + ( + "ospy/data1/sites.shx", + "1f3da459ccb151958743171e41e6a01810b2a007305d55666e01d680da7bbf08", + ), + ( + "ospy/data2/ut_counties.txt", + "06585b736091f5bbc62eb040918b1693b2716f550ab306026732e1dfa6cd49a7", + ), + ( + "ospy/data3/cache_towns.dbf", + "2344b5195e1a7cbc141f38d6f3214f04c0d43058309b162e877fca755cd1d9fa", + ), + ( + "ospy/data3/cache_towns.sbn", + "217e938eb0bec1cdccf26d87e5127d395d68b5d660bc1ecc1d7ec7b3f052f4e3", + ), + ( + "ospy/data3/cache_towns.sbx", + "e027b3f67bbb60fc9cf67ab6f430b286fd8a1eaa6c344edaa7da4327485ee9f2", + ), + ( + "ospy/data3/cache_towns.shp", + "635998f789d349d80368cb105e7e0d61f95cc6eecd36b34bf005d8c7e966fedb", + ), + ( + "ospy/data3/cache_towns.shx", + "0cafc504b829a3da2c0363074f775266f9e1f6aaaf1e066b8a613d5862f313b7", + ), + ( + "ospy/data4/aster.img", + "2423205bdf820b1c2a3f03862664d84ea4b5b899c57ed33afd8962664e80a298", + ), + ( + "ospy/data4/aster.rrd", + "18e038aabe8fd92b0d12cd4f324bb2e0368343e20cc41e5411a6d038108a25cf", + ), + ( + "ospy/data5/doq1.img", + "70b8e641c52367107654962e81977be65402aa3c46736a07cb512ce960203bb7", + ), + ( + "ospy/data5/doq1.rrd", + "f9f2fe57d789977090ec0c31e465052161886e79a4c4e10805b5e7ab28c06177", + ), + ( + "ospy/data5/doq2.img", + "1e1d744f17e6a3b97dd9b7d8705133c72ff162613bae43ad94417c54e6aced5d", + ), + ( + "ospy/data5/doq2.rrd", + "8274dad00b27e008e5ada62afb1025b0e6e2ef2d2ff2642487ecaee64befd914", + ), ] for (f, sha) in remotefiles @@ -53,5 +125,5 @@ for (f, sha) in remotefiles # download the file if it is not there or if it has a different checksum currfile = normpath(joinpath(testdatadir, f)) url = REPO_URL * f * "?raw=true" - PlatformEngines.download_verify(url, sha, currfile; force=true) + PlatformEngines.download_verify(url, sha, currfile; force = true) end diff --git a/test/test_array.jl b/test/test_array.jl index 69578183..54675160 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -1,174 +1,176 @@ using Test using DiskArrays: eachchunk, haschunks, Chunked, GridChunks, readblock! -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_array.jl" begin -@testset "RasterDataset Type" begin - AG.readraster("ospy/data4/aster.img") do ds - @testset "Test forwarded methods" begin - @test ds isa AG.RasterDataset{UInt8} - @test AG.getgeotransform(ds) == [419976.5, 15.0, 0.0, 4.6624225e6, 0.0, -15.0] - @test AG.nraster(ds) == 3 - @test AG.getband(ds,1) isa AG.AbstractRasterBand - @test startswith(AG.getproj(ds),"PROJCS") - @test AG.width(ds)==5665 - @test AG.height(ds)==5033 - @test AG.getdriver(ds) isa AG.Driver - @test splitpath(AG.filelist(ds)[1]) == ["ospy", "data4", "aster.img"] - @test splitpath(AG.filelist(ds)[2]) == ["ospy", "data4", "aster.rrd"] - @test AG.listcapability(ds) isa Dict - @test AG.ngcp(ds)==0 - @test AG.write(ds,tempname()) == nothing - @test AG.testcapability(ds,"ODsCCreateLayer") == false - end - @testset "DiskArray chunk interface" begin - b = AG.getband(ds,1) - @test eachchunk(ds) == GridChunks(size(ds),(64,64,1)) - @test eachchunk(b) == GridChunks(size(b),(64,64)) - @test haschunks(ds) == Chunked() - @test haschunks(b) == Chunked() - end - @testset "Reading into non-arrays" begin - data1 = view(zeros(3,3,3), 1:3, 1:3, 1:3) - readblock!(ds, data1, 1:3, 1:3, 1:3) - @test data1 == ds[1:3,1:3,1:3] + @testset "RasterDataset Type" begin + AG.readraster("ospy/data4/aster.img") do ds + @testset "Test forwarded methods" begin + @test ds isa AG.RasterDataset{UInt8} + @test AG.getgeotransform(ds) == + [419976.5, 15.0, 0.0, 4.6624225e6, 0.0, -15.0] + @test AG.nraster(ds) == 3 + @test AG.getband(ds, 1) isa AG.AbstractRasterBand + @test startswith(AG.getproj(ds), "PROJCS") + @test AG.width(ds) == 5665 + @test AG.height(ds) == 5033 + @test AG.getdriver(ds) isa AG.Driver + @test splitpath(AG.filelist(ds)[1]) == ["ospy", "data4", "aster.img"] + @test splitpath(AG.filelist(ds)[2]) == ["ospy", "data4", "aster.rrd"] + @test AG.listcapability(ds) isa Dict + @test AG.ngcp(ds) == 0 + @test AG.write(ds, tempname()) == nothing + @test AG.testcapability(ds, "ODsCCreateLayer") == false + end + @testset "DiskArray chunk interface" begin + b = AG.getband(ds, 1) + @test eachchunk(ds) == GridChunks(size(ds), (64, 64, 1)) + @test eachchunk(b) == GridChunks(size(b), (64, 64)) + @test haschunks(ds) == Chunked() + @test haschunks(b) == Chunked() + end + @testset "Reading into non-arrays" begin + data1 = view(zeros(3, 3, 3), 1:3, 1:3, 1:3) + readblock!(ds, data1, 1:3, 1:3, 1:3) + @test data1 == ds[1:3, 1:3, 1:3] + end end end -end -@testset "Test Array getindex" begin - AG.readraster("ospy/data4/aster.img") do ds - @testset "Dataset indexing" begin - @testset "dims dropped correctly" begin - @test typeof(ds[:, :, :]) <: Array{UInt8,3} - @test typeof(ds[:, :, 1]) <: Array{UInt8,2} - @test typeof(ds[:, 1, 1]) <: Array{UInt8,1} - @test typeof(ds[1, 1, 1]) <: UInt8 - end - @testset "range indexing" begin - buffer = ds[1:AG.width(ds), 1:AG.height(ds), 1:1] - @test typeof(buffer) <: Array{UInt8,3} - total = sum(buffer) - count = sum(buffer .> 0) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "colon indexing" begin - buffer = ds[:, :, 1] - total = sum(buffer) - count = sum(buffer .> 0) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "int indexing" begin - @test ds[755, 2107, 1] == 0xff - end - end - @testset "RasterBand indexing" begin - band = AG.getband(ds, 1) - @testset "dims dropped correctly" begin - @test typeof(band[:, :]) <: Array{UInt8,2} - @test typeof(band[:, 1]) <: Array{UInt8,1} - @test typeof(band[1, 1]) <: UInt8 - end - @testset "range indexing" begin - buffer = band[1:AG.width(band), 1:AG.height(band)] - @test typeof(buffer) <: Array{UInt8,2} - total = sum(buffer) - count = sum(buffer .> 0) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(band) * AG.width(band)) ≈ 47.55674749653172 - end - @testset "colon indexing" begin - buffer = band[:, :] - total = sum(buffer) - count = sum(buffer .> 0) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(band) * AG.width(band)) ≈ 47.55674749653172 + @testset "Test Array getindex" begin + AG.readraster("ospy/data4/aster.img") do ds + @testset "Dataset indexing" begin + @testset "dims dropped correctly" begin + @test typeof(ds[:, :, :]) <: Array{UInt8,3} + @test typeof(ds[:, :, 1]) <: Array{UInt8,2} + @test typeof(ds[:, 1, 1]) <: Array{UInt8,1} + @test typeof(ds[1, 1, 1]) <: UInt8 + end + @testset "range indexing" begin + buffer = ds[1:AG.width(ds), 1:AG.height(ds), 1:1] + @test typeof(buffer) <: Array{UInt8,3} + total = sum(buffer) + count = sum(buffer .> 0) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end + @testset "colon indexing" begin + buffer = ds[:, :, 1] + total = sum(buffer) + count = sum(buffer .> 0) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end + @testset "int indexing" begin + @test ds[755, 2107, 1] == 0xff + end end - @testset "int indexing" begin - @test band[755, 2107] == 0xff + @testset "RasterBand indexing" begin + band = AG.getband(ds, 1) + @testset "dims dropped correctly" begin + @test typeof(band[:, :]) <: Array{UInt8,2} + @test typeof(band[:, 1]) <: Array{UInt8,1} + @test typeof(band[1, 1]) <: UInt8 + end + @testset "range indexing" begin + buffer = band[1:AG.width(band), 1:AG.height(band)] + @test typeof(buffer) <: Array{UInt8,2} + total = sum(buffer) + count = sum(buffer .> 0) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(band) * AG.width(band)) ≈ 47.55674749653172 + end + @testset "colon indexing" begin + buffer = band[:, :] + total = sum(buffer) + count = sum(buffer .> 0) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(band) * AG.width(band)) ≈ 47.55674749653172 + end + @testset "int indexing" begin + @test band[755, 2107] == 0xff + end end end end -end -cp("ospy/data4/aster.img", "ospy/data4/aster_write.img"; force=true) + cp("ospy/data4/aster.img", "ospy/data4/aster_write.img"; force = true) -@testset "Test Array setindex" begin - AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_UPDATE) do ds - @testset "Dataset setindex" begin - @test ds[755, 2107, 1] == 0xff - ds[755, 2107, 1] = 0x00 - @test ds[755, 2107, 1] == 0x00 - ds[755:755, 2107:2107, 1:1] = reshape([0x01], 1, 1, 1) - @test ds[755, 2107, 1] == 0x01 - ds[755:755, 2107:2107, 1] = reshape([0x02], 1, 1) - @test ds[755, 2107, 1] == 0x02 - ds[755:755, 2107, 1] = [0x03] - @test ds[755, 2107, 1] == 0x03 - end - @testset "RasterBand setindex" begin - band = AG.getband(ds, 1) - band[755:755, 2107] = [0x00] - @test band[755, 2107] == 0x00 - band[755, 2107] = 0x01 - @test band[755, 2107] == 0x01 - band[755:755, 2107:2107] = reshape([0xff], 1, 1) - @test band[755, 2107] == 0xff - buffer = band[:, :] - band[:, :] = buffer .* 0x00 - @test sum(band[:, :]) == 0x00 - band[:, 1:500] = buffer[:, 1:500] - band[:, 501:end] = buffer[:, 501:end] - @test sum(buffer) / sum(buffer .> 0) ≈ 76.33891347095299 - @test_throws DimensionMismatch band[:, 501:end] = [1, 2, 3] + @testset "Test Array setindex" begin + AG.readraster("ospy/data4/aster_write.img"; flags = AG.OF_UPDATE) do ds + @testset "Dataset setindex" begin + @test ds[755, 2107, 1] == 0xff + ds[755, 2107, 1] = 0x00 + @test ds[755, 2107, 1] == 0x00 + ds[755:755, 2107:2107, 1:1] = reshape([0x01], 1, 1, 1) + @test ds[755, 2107, 1] == 0x01 + ds[755:755, 2107:2107, 1] = reshape([0x02], 1, 1) + @test ds[755, 2107, 1] == 0x02 + ds[755:755, 2107, 1] = [0x03] + @test ds[755, 2107, 1] == 0x03 + end + @testset "RasterBand setindex" begin + band = AG.getband(ds, 1) + band[755:755, 2107] = [0x00] + @test band[755, 2107] == 0x00 + band[755, 2107] = 0x01 + @test band[755, 2107] == 0x01 + band[755:755, 2107:2107] = reshape([0xff], 1, 1) + @test band[755, 2107] == 0xff + buffer = band[:, :] + band[:, :] = buffer .* 0x00 + @test sum(band[:, :]) == 0x00 + band[:, 1:500] = buffer[:, 1:500] + band[:, 501:end] = buffer[:, 501:end] + @test sum(buffer) / sum(buffer .> 0) ≈ 76.33891347095299 + @test_throws DimensionMismatch band[:, 501:end] = [1, 2, 3] + end end end -end -@testset "Test Array constructor" begin - AG.readraster("ospy/data4/aster_write.img"; flags=AG.OF_UPDATE) do ds - @test sprint(print, ds) == """ - GDAL Dataset (Driver: HFA/Erdas Imagine Images (.img)) - File(s): - ospy/data4/aster_write.img + @testset "Test Array constructor" begin + AG.readraster("ospy/data4/aster_write.img"; flags = AG.OF_UPDATE) do ds + @test sprint(print, ds) == """ + GDAL Dataset (Driver: HFA/Erdas Imagine Images (.img)) + File(s): + ospy/data4/aster_write.img - Dataset (width x height): 5665 x 5033 (pixels) - Number of raster bands: 3 - [GA_Update] Band 1 (Undefined): 5665 x 5033 (UInt8) - [GA_Update] Band 2 (Undefined): 5665 x 5033 (UInt8) - [GA_Update] Band 3 (Undefined): 5665 x 5033 (UInt8) - """ - buffer = Array(ds) - typeof(buffer) <: Array{UInt8,3} - total = sum(buffer[:, :, 1:1]) - count = sum(buffer[:, :, 1:1] .> 0) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + Dataset (width x height): 5665 x 5033 (pixels) + Number of raster bands: 3 + [GA_Update] Band 1 (Undefined): 5665 x 5033 (UInt8) + [GA_Update] Band 2 (Undefined): 5665 x 5033 (UInt8) + [GA_Update] Band 3 (Undefined): 5665 x 5033 (UInt8) + """ + buffer = Array(ds) + typeof(buffer) <: Array{UInt8,3} + total = sum(buffer[:, :, 1:1]) + count = sum(buffer[:, :, 1:1] .> 0) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - AG.copy(ds) do copy1 - @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) - @test typeof(AG.copywholeraster!(AG.RasterDataset(copy1), ds)) == typeof(ds) - @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) + AG.copy(ds) do copy1 + @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) + @test typeof(AG.copywholeraster!(AG.RasterDataset(copy1), ds)) == typeof(ds) + @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) + end end - end - AG.create( + AG.create( AG.getdriver("MEM"), width = 2, height = 2, nbands = 0, dtype = UInt8, ) do dataset - @test_throws ArgumentError AG.RasterDataset(dataset) - @test_throws DimensionMismatch AG._common_size(dataset) + @test_throws ArgumentError AG.RasterDataset(dataset) + @test_throws DimensionMismatch AG._common_size(dataset) + end end -end end diff --git a/test/test_convert.jl b/test/test_convert.jl index c925eda3..660277d8 100644 --- a/test/test_convert.jl +++ b/test/test_convert.jl @@ -1,40 +1,46 @@ using Test -import ArchGDAL; const AG = ArchGDAL -import GeoFormatTypes; const GFT = GeoFormatTypes +import ArchGDAL; +const AG = ArchGDAL; +import GeoFormatTypes; +const GFT = GeoFormatTypes; @testset "test_convert.jl" begin -# Tests high level convert methods -@testset "convert point format" begin - point = AG.createpoint(100, 70) - json = convert(GFT.GeoJSON, point) - @test sprint(print, convert(AG.IGeometry, json)) == - "Geometry: POINT (100 70)" - kml = convert(GFT.KML, point) - gml = convert(GFT.GML, point) - wkb = convert(GFT.WellKnownBinary, point) - wkt = convert(GFT.WellKnownText, point) - @test json.val == AG.toJSON(point) - @test kml.val == AG.toKML(point) - @test gml.val == AG.toGML(point) - @test wkb.val == AG.toWKB(point) - @test wkt.val == AG.toWKT(point) - @test convert(GFT.GeoJSON, json) == - convert(GFT.GeoJSON, wkb) == - convert(GFT.GeoJSON, wkt) == - convert(GFT.GeoJSON, gml) == - json - @test convert(GFT.KML, gml) == convert(GFT.KML, wkt) -end + # Tests high level convert methods + @testset "convert point format" begin + point = AG.createpoint(100, 70) + json = convert(GFT.GeoJSON, point) + @test sprint(print, convert(AG.IGeometry, json)) == "Geometry: POINT (100 70)" + kml = convert(GFT.KML, point) + gml = convert(GFT.GML, point) + wkb = convert(GFT.WellKnownBinary, point) + wkt = convert(GFT.WellKnownText, point) + @test json.val == AG.toJSON(point) + @test kml.val == AG.toKML(point) + @test gml.val == AG.toGML(point) + @test wkb.val == AG.toWKB(point) + @test wkt.val == AG.toWKT(point) + @test convert(GFT.GeoJSON, json) == + convert(GFT.GeoJSON, wkb) == + convert(GFT.GeoJSON, wkt) == + convert(GFT.GeoJSON, gml) == + json + @test convert(GFT.KML, gml) == convert(GFT.KML, wkt) + end -@testset "convert crs format" begin - proj4326 = GFT.ProjString("+proj=longlat +datum=WGS84 +no_defs") - @test convert(GFT.ProjString, GFT.CRS(), - convert(GFT.WellKnownText, GFT.CRS(), - convert(GFT.ESRIWellKnownText, GFT.CRS(), - GFT.EPSG(4326)))) == proj4326 - @test convert(GFT.CoordSys, GFT.CRS(), proj4326) isa GFT.CoordSys - @test convert(GFT.GML, GFT.CRS(), proj4326) isa GeoFormatTypes.GML -end + @testset "convert crs format" begin + proj4326 = GFT.ProjString("+proj=longlat +datum=WGS84 +no_defs") + @test convert( + GFT.ProjString, + GFT.CRS(), + convert( + GFT.WellKnownText, + GFT.CRS(), + convert(GFT.ESRIWellKnownText, GFT.CRS(), GFT.EPSG(4326)), + ), + ) == proj4326 + @test convert(GFT.CoordSys, GFT.CRS(), proj4326) isa GFT.CoordSys + @test convert(GFT.GML, GFT.CRS(), proj4326) isa GeoFormatTypes.GML + end end diff --git a/test/test_cookbook_geometry.jl b/test/test_cookbook_geometry.jl index 78f000a3..971ed5f8 100644 --- a/test/test_cookbook_geometry.jl +++ b/test/test_cookbook_geometry.jl @@ -1,148 +1,159 @@ # adapted from http://pcjericks.github.io/py-gdalogr-cookbook/geometry.html using Test import GeoInterface -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_cookbook_geometry.jl" begin -@testset "Create a Point" begin + @testset "Create a Point" begin - x, y = 1198054.34, 648493.09 - wktpoint = "POINT (1198054.34 648493.09)" + x, y = 1198054.34, 648493.09 + wktpoint = "POINT (1198054.34 648493.09)" - # Method 1 - AG.createpoint(x, y) do point - @test AG.toWKT(point) == wktpoint - end - AG.createpoint((x, y)) do point - @test AG.toWKT(point) == wktpoint - end + # Method 1 + AG.createpoint(x, y) do point + @test AG.toWKT(point) == wktpoint + end + AG.createpoint((x, y)) do point + @test AG.toWKT(point) == wktpoint + end - # Method 2 - AG.createpoint() do point - AG.addpoint!(point, x, y) - @test AG.toWKT(point) == wktpoint - end + # Method 2 + AG.createpoint() do point + AG.addpoint!(point, x, y) + @test AG.toWKT(point) == wktpoint + end - # Method 3 - AG.creategeom(AG.wkbPoint) do point + # Method 3 + AG.creategeom(AG.wkbPoint) do point + AG.addpoint!(point, x, y) + @test AG.toWKT(point) == wktpoint + end + + # Method 4 + point = AG.creategeom(AG.wkbPoint) AG.addpoint!(point, x, y) @test AG.toWKT(point) == wktpoint - end - # Method 4 - point = AG.creategeom(AG.wkbPoint) - AG.addpoint!(point, x, y) - @test AG.toWKT(point) == wktpoint - - # Method 5 - @test AG.toWKT(AG.createpoint(x, y)) == wktpoint -end + # Method 5 + @test AG.toWKT(AG.createpoint(x, y)) == wktpoint + end + + @testset "Create a LineString" begin + # Method 1 + wktline = + "LINESTRING (1116651.43937912 637392.696988746," * + "1188804.01084985 652655.740953707,1226730.36252036 634155.081602239,1281307.30760719 636467.664021172)" + AG.createlinestring([ + (1116651.439379124, 637392.6969887456), + (1188804.0108498496, 652655.7409537067), + (1226730.3625203592, 634155.0816022386), + (1281307.30760719, 636467.6640211721), + ]) do line + @test AG.toWKT(line) == wktline + end -@testset "Create a LineString" begin - # Method 1 - wktline = "LINESTRING (1116651.43937912 637392.696988746," * - "1188804.01084985 652655.740953707,1226730.36252036 634155.081602239,1281307.30760719 636467.664021172)" - AG.createlinestring([(1116651.439379124, 637392.6969887456), - (1188804.0108498496, 652655.7409537067), - (1226730.3625203592, 634155.0816022386), - (1281307.30760719, 636467.6640211721)]) do line - @test AG.toWKT(line) == wktline - end + # Method 2 + AG.createlinestring() do line + AG.addpoint!(line, 1116651.439379124, 637392.6969887456) + AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) + AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) + AG.addpoint!(line, 1281307.30760719, 636467.6640211721) + @test AG.toWKT(line) == wktline + end - # Method 2 - AG.createlinestring() do line - AG.addpoint!(line, 1116651.439379124, 637392.6969887456) - AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) - AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) - AG.addpoint!(line, 1281307.30760719, 636467.6640211721) - @test AG.toWKT(line) == wktline - end + # Method 3 + AG.creategeom(AG.wkbLineString) do line + AG.addpoint!(line, 1116651.439379124, 637392.6969887456) + AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) + AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) + AG.addpoint!(line, 1281307.30760719, 636467.6640211721) + @test AG.toWKT(line) == wktline + end - # Method 3 - AG.creategeom(AG.wkbLineString) do line - AG.addpoint!(line, 1116651.439379124, 637392.6969887456) + # Method 4 + line = AG.creategeom(AG.wkbLineString) + AG.addpoint!(line, 1116651.439379124, 637392.6969887456) AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) - AG.addpoint!(line, 1281307.30760719, 636467.6640211721) + AG.addpoint!(line, 1281307.30760719, 636467.6640211721) @test AG.toWKT(line) == wktline - end - - # Method 4 - line = AG.creategeom(AG.wkbLineString) - AG.addpoint!(line, 1116651.439379124, 637392.6969887456) - AG.addpoint!(line, 1188804.0108498496, 652655.7409537067) - AG.addpoint!(line, 1226730.3625203592, 634155.0816022386) - AG.addpoint!(line, 1281307.30760719, 636467.6640211721) - @test AG.toWKT(line) == wktline - - # Method 5 - @test AG.toWKT(AG.createlinestring([ - (1116651.439379124, 637392.6969887456), - (1188804.0108498496, 652655.7409537067), - (1226730.3625203592, 634155.0816022386), - (1281307.30760719, 636467.6640211721) - ])) == wktline -end - -@testset "Create a Polygon" begin - wktpoly = "POLYGON ((1179091.16469033 712782.883845978,1161053.02182265 667456.268434881," * - "1214704.9339419 641092.828859039,1228580.42845551 682719.312399842," * - "1218405.0658122 721108.180554139,1179091.16469033 712782.883845978))" - - # Method 1 - AG.createpolygon([(1179091.1646903288, 712782.8838459781), - (1161053.0218226474, 667456.2684348812), - (1214704.933941905, 641092.8288590391), - (1228580.428455506, 682719.3123998424), - (1218405.0658121984, 721108.1805541387), - (1179091.1646903288, 712782.8838459781)]) do poly - @test AG.toWKT(poly) == wktpoly - end - - # Method 2 - AG.createpolygon() do poly - ring = AG.createlinearring( - [(1179091.1646903288, 712782.8838459781), - (1161053.0218226474, 667456.2684348812), - (1214704.933941905, 641092.8288590391), - (1228580.428455506, 682719.3123998424), - (1218405.0658121984, 721108.1805541387), - (1179091.1646903288, 712782.8838459781)]) - AG.addgeom!(poly, ring) - end + # Method 5 + @test AG.toWKT( + AG.createlinestring([ + (1116651.439379124, 637392.6969887456), + (1188804.0108498496, 652655.7409537067), + (1226730.3625203592, 634155.0816022386), + (1281307.30760719, 636467.6640211721), + ]), + ) == wktline + end + + @testset "Create a Polygon" begin + + wktpoly = + "POLYGON ((1179091.16469033 712782.883845978,1161053.02182265 667456.268434881," * + "1214704.9339419 641092.828859039,1228580.42845551 682719.312399842," * + "1218405.0658122 721108.180554139,1179091.16469033 712782.883845978))" + + # Method 1 + AG.createpolygon([ + (1179091.1646903288, 712782.8838459781), + (1161053.0218226474, 667456.2684348812), + (1214704.933941905, 641092.8288590391), + (1228580.428455506, 682719.3123998424), + (1218405.0658121984, 721108.1805541387), + (1179091.1646903288, 712782.8838459781), + ]) do poly + @test AG.toWKT(poly) == wktpoly + end - AG.createlinearring( - [(1179091.1646903288, 712782.8838459781), - (1161053.0218226474, 667456.2684348812), - (1214704.933941905, 641092.8288590391), - (1228580.428455506, 682719.3123998424), - (1218405.0658121984, 721108.1805541387), - (1179091.1646903288, 712782.8838459781)]) do ring + # Method 2 AG.createpolygon() do poly + ring = AG.createlinearring([ + (1179091.1646903288, 712782.8838459781), + (1161053.0218226474, 667456.2684348812), + (1214704.933941905, 641092.8288590391), + (1228580.428455506, 682719.3123998424), + (1218405.0658121984, 721108.1805541387), + (1179091.1646903288, 712782.8838459781), + ]) AG.addgeom!(poly, ring) - @test AG.toWKT(poly) == wktpoly end - end - # Method 3 - AG.creategeom(AG.wkbLinearRing) do ring - AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) - AG.addpoint!(ring, 1161053.0218226474, 667456.2684348812) - AG.addpoint!(ring, 1214704.933941905, 641092.8288590391) - AG.addpoint!(ring, 1228580.428455506, 682719.3123998424) - AG.addpoint!(ring, 1218405.0658121984, 721108.1805541387) - AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) + AG.createlinearring([ + (1179091.1646903288, 712782.8838459781), + (1161053.0218226474, 667456.2684348812), + (1214704.933941905, 641092.8288590391), + (1228580.428455506, 682719.3123998424), + (1218405.0658121984, 721108.1805541387), + (1179091.1646903288, 712782.8838459781), + ]) do ring + AG.createpolygon() do poly + AG.addgeom!(poly, ring) + @test AG.toWKT(poly) == wktpoly + end + end - AG.creategeom(AG.wkbPolygon) do poly - AG.addgeom!(poly, ring) - @test AG.toWKT(poly) == wktpoly + # Method 3 + AG.creategeom(AG.wkbLinearRing) do ring + AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) + AG.addpoint!(ring, 1161053.0218226474, 667456.2684348812) + AG.addpoint!(ring, 1214704.933941905, 641092.8288590391) + AG.addpoint!(ring, 1228580.428455506, 682719.3123998424) + AG.addpoint!(ring, 1218405.0658121984, 721108.1805541387) + AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) + + AG.creategeom(AG.wkbPolygon) do poly + AG.addgeom!(poly, ring) + @test AG.toWKT(poly) == wktpoly + end end - end - # Method 4 - ring = AG.creategeom(AG.wkbLinearRing) + # Method 4 + ring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) AG.addpoint!(ring, 1161053.0218226474, 667456.2684348812) AG.addpoint!(ring, 1214704.933941905, 641092.8288590391) @@ -150,149 +161,176 @@ end AG.addpoint!(ring, 1218405.0658121984, 721108.1805541387) AG.addpoint!(ring, 1179091.1646903288, 712782.8838459781) - poly = AG.creategeom(AG.wkbPolygon) - AG.addgeom!(poly, ring) - @test AG.toWKT(poly) == wktpoly - - @test AG.toWKT(AG.createpolygon([ - (1179091.1646903288, 712782.8838459781), - (1161053.0218226474, 667456.2684348812), - (1214704.933941905, 641092.8288590391), - (1228580.428455506, 682719.3123998424), - (1218405.0658121984, 721108.1805541387), - (1179091.1646903288, 712782.8838459781) - ])) == wktpoly -end - -@testset "Create a Polygon with holes" begin - - wktpoly = "POLYGON ((1154115.27456585 686419.444270136,1154115.27456585 653118.257437493," * - "1165678.18666051 653118.257437493,1165678.18666051 686419.444270136," * - "1154115.27456585 686419.444270136)," * - "(1149490.10972798 691044.609108003,1149490.10972798 648030.57611584," * - "1191579.10975257 648030.57611584,1191579.10975257 691044.609108003," * - "1149490.10972798 691044.609108003))" - - # Method 1 - AG.createpolygon([# outring - [(1154115.274565847, 686419.4442701361), - (1154115.274565847, 653118.2574374934), - (1165678.1866605144, 653118.2574374934), - (1165678.1866605144, 686419.4442701361), - (1154115.274565847, 686419.4442701361)], - # innerring(s) - [(1149490.1097279799, 691044.6091080031), - (1149490.1097279799, 648030.5761158396), - (1191579.1097525698, 648030.5761158396), - (1191579.1097525698, 691044.6091080031), - (1149490.1097279799, 691044.6091080031)] - ]) do poly + poly = AG.creategeom(AG.wkbPolygon) + AG.addgeom!(poly, ring) @test AG.toWKT(poly) == wktpoly - end - # Method 2 - AG.createpolygon() do poly - outring = AG.creategeom(AG.wkbLinearRing) + @test AG.toWKT( + AG.createpolygon([ + (1179091.1646903288, 712782.8838459781), + (1161053.0218226474, 667456.2684348812), + (1214704.933941905, 641092.8288590391), + (1228580.428455506, 682719.3123998424), + (1218405.0658121984, 721108.1805541387), + (1179091.1646903288, 712782.8838459781), + ]), + ) == wktpoly + end + + @testset "Create a Polygon with holes" begin + + wktpoly = + "POLYGON ((1154115.27456585 686419.444270136,1154115.27456585 653118.257437493," * + "1165678.18666051 653118.257437493,1165678.18666051 686419.444270136," * + "1154115.27456585 686419.444270136)," * + "(1149490.10972798 691044.609108003,1149490.10972798 648030.57611584," * + "1191579.10975257 648030.57611584,1191579.10975257 691044.609108003," * + "1149490.10972798 691044.609108003))" + + # Method 1 + AG.createpolygon([# outring + [ + (1154115.274565847, 686419.4442701361), + (1154115.274565847, 653118.2574374934), + (1165678.1866605144, 653118.2574374934), + (1165678.1866605144, 686419.4442701361), + (1154115.274565847, 686419.4442701361), + ], + # innerring(s) + [ + (1149490.1097279799, 691044.6091080031), + (1149490.1097279799, 648030.5761158396), + (1191579.1097525698, 648030.5761158396), + (1191579.1097525698, 691044.6091080031), + (1149490.1097279799, 691044.6091080031), + ], + ]) do poly + @test AG.toWKT(poly) == wktpoly + end + + # Method 2 + AG.createpolygon() do poly + outring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) - innerring = AG.creategeom(AG.wkbLinearRing) + innerring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) - AG.addgeom!(poly, outring) - AG.addgeom!(poly, innerring) - @test AG.toWKT(poly) == wktpoly - end + AG.addgeom!(poly, outring) + AG.addgeom!(poly, innerring) + @test AG.toWKT(poly) == wktpoly + end - # Method 3 - AG.creategeom(AG.wkbPolygon) do poly - outring = AG.creategeom(AG.wkbLinearRing) + # Method 3 + AG.creategeom(AG.wkbPolygon) do poly + outring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) AG.addpoint!(outring, 1165678.1866605144, 686419.4442701361) AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) - innerring = AG.creategeom(AG.wkbLinearRing) + innerring = AG.creategeom(AG.wkbLinearRing) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) AG.addpoint!(innerring, 1191579.1097525698, 691044.6091080031) AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) - AG.addgeom!(poly, outring) - AG.addgeom!(poly, innerring) - @test AG.toWKT(poly) == wktpoly - end + AG.addgeom!(poly, outring) + AG.addgeom!(poly, innerring) + @test AG.toWKT(poly) == wktpoly + end - # Method 4 - poly = AG.creategeom(AG.wkbPolygon) + # Method 4 + poly = AG.creategeom(AG.wkbPolygon) outring = AG.creategeom(AG.wkbLinearRing) - AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) - AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) - AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) - AG.addpoint!(outring, 1165678.1866605144, 686419.4442701361) - AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) + AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) + AG.addpoint!(outring, 1154115.274565847, 653118.2574374934) + AG.addpoint!(outring, 1165678.1866605144, 653118.2574374934) + AG.addpoint!(outring, 1165678.1866605144, 686419.4442701361) + AG.addpoint!(outring, 1154115.274565847, 686419.4442701361) AG.addgeom!(poly, outring) innerring = AG.creategeom(AG.wkbLinearRing) - AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) - AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) - AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) - AG.addpoint!(innerring, 1191579.1097525698, 691044.6091080031) - AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) + AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) + AG.addpoint!(innerring, 1149490.1097279799, 648030.5761158396) + AG.addpoint!(innerring, 1191579.1097525698, 648030.5761158396) + AG.addpoint!(innerring, 1191579.1097525698, 691044.6091080031) + AG.addpoint!(innerring, 1149490.1097279799, 691044.6091080031) AG.addgeom!(poly, innerring) - @test AG.toWKT(poly) == wktpoly - - # Method 5 - @test AG.toWKT(AG.createpolygon([ - # outerring - [(1154115.274565847, 686419.4442701361), - (1154115.274565847, 653118.2574374934), - (1165678.1866605144, 653118.2574374934), - (1165678.1866605144, 686419.4442701361), - (1154115.274565847, 686419.4442701361)], - # innerring(s) - [(1149490.1097279799, 691044.6091080031), - (1149490.1097279799, 648030.5761158396), - (1191579.1097525698, 648030.5761158396), - (1191579.1097525698, 691044.6091080031), - (1149490.1097279799, 691044.6091080031)] - ])) == wktpoly -end - -@testset "Create a MultiPoint" begin + @test AG.toWKT(poly) == wktpoly - wktpoints = "MULTIPOINT (1251243.73616105 598078.795866876," * - "1240605.85703396 601778.927737169,1250318.70319348 606404.092575036)" + # Method 5 + @test AG.toWKT( + AG.createpolygon([ + # outerring + [ + (1154115.274565847, 686419.4442701361), + (1154115.274565847, 653118.2574374934), + (1165678.1866605144, 653118.2574374934), + (1165678.1866605144, 686419.4442701361), + (1154115.274565847, 686419.4442701361), + ], + # innerring(s) + [ + (1149490.1097279799, 691044.6091080031), + (1149490.1097279799, 648030.5761158396), + (1191579.1097525698, 648030.5761158396), + (1191579.1097525698, 691044.6091080031), + (1149490.1097279799, 691044.6091080031), + ], + ]), + ) == wktpoly + end + + @testset "Create a MultiPoint" begin + + wktpoints = + "MULTIPOINT (1251243.73616105 598078.795866876," * + "1240605.85703396 601778.927737169,1250318.70319348 606404.092575036)" + + # Method 1 + AG.createmultipoint([ + (1251243.7361610543, 598078.7958668759), + (1240605.8570339603, 601778.9277371694), + (1250318.7031934808, 606404.0925750365), + ]) do multipoint + @test AG.toWKT(multipoint) == wktpoints + end - # Method 1 - AG.createmultipoint([(1251243.7361610543, 598078.7958668759), - (1240605.8570339603, 601778.9277371694), - (1250318.7031934808, 606404.0925750365)]) do multipoint - @test AG.toWKT(multipoint) == wktpoints - end + # Method 2 + AG.createmultipoint() do multipoint + point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) + point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) + point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) + AG.addgeom!(multipoint, point1) + AG.addgeom!(multipoint, point2) + AG.addgeom!(multipoint, point3) + @test AG.toWKT(multipoint) == wktpoints + end - # Method 2 - AG.createmultipoint() do multipoint - point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) - point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) - point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) - AG.addgeom!(multipoint, point1) - AG.addgeom!(multipoint, point2) - AG.addgeom!(multipoint, point3) - @test AG.toWKT(multipoint) == wktpoints - end + # Method 3 + AG.creategeom(AG.wkbMultiPoint) do multipoint + point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) + point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) + point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) + AG.addgeom!(multipoint, point1) + AG.addgeom!(multipoint, point2) + AG.addgeom!(multipoint, point3) + @test AG.toWKT(multipoint) == wktpoints + end - # Method 3 - AG.creategeom(AG.wkbMultiPoint) do multipoint + # Method 4 + multipoint = AG.creategeom(AG.wkbMultiPoint) point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) @@ -300,475 +338,650 @@ end AG.addgeom!(multipoint, point2) AG.addgeom!(multipoint, point3) @test AG.toWKT(multipoint) == wktpoints - end - # Method 4 - multipoint = AG.creategeom(AG.wkbMultiPoint) - point1 = AG.createpoint(1251243.7361610543, 598078.7958668759) - point2 = AG.createpoint(1240605.8570339603, 601778.9277371694) - point3 = AG.createpoint(1250318.7031934808, 606404.0925750365) - AG.addgeom!(multipoint, point1) - AG.addgeom!(multipoint, point2) - AG.addgeom!(multipoint, point3) - @test AG.toWKT(multipoint) == wktpoints - - # Method 5 - @test AG.toWKT(AG.createmultipoint([ - (1251243.7361610543, 598078.7958668759), - (1240605.8570339603, 601778.9277371694), - (1250318.7031934808, 606404.0925750365) - ])) == wktpoints -end - -@testset "Create a MultiLineString" begin - - wktline = "MULTILINESTRING ((1214242.41745812 617041.971702131,1234593.14274473 629529.916764372)," * - "(1184641.36249577 626754.817861651,1219792.61526356 606866.609058823))" - - # Method 1 - AG.createmultilinestring(Vector{Tuple{Float64,Float64}}[ - [(1214242.4174581182, 617041.9717021306), - (1234593.142744733, 629529.9167643716)], - [(1184641.3624957693, 626754.8178616514), - (1219792.6152635587, 606866.6090588232)] - ]) do multiline - @test GeoInterface.geotype(multiline) == :MultiLineString - @test AG.toWKT(multiline) == wktline - end + # Method 5 + @test AG.toWKT( + AG.createmultipoint([ + (1251243.7361610543, 598078.7958668759), + (1240605.8570339603, 601778.9277371694), + (1250318.7031934808, 606404.0925750365), + ]), + ) == wktpoints + end + + @testset "Create a MultiLineString" begin + + wktline = + "MULTILINESTRING ((1214242.41745812 617041.971702131,1234593.14274473 629529.916764372)," * + "(1184641.36249577 626754.817861651,1219792.61526356 606866.609058823))" + + # Method 1 + AG.createmultilinestring( + Vector{Tuple{Float64,Float64}}[ + [ + (1214242.4174581182, 617041.9717021306), + (1234593.142744733, 629529.9167643716), + ], + [ + (1184641.3624957693, 626754.8178616514), + (1219792.6152635587, 606866.6090588232), + ], + ], + ) do multiline + @test GeoInterface.geotype(multiline) == :MultiLineString + @test AG.toWKT(multiline) == wktline + end - # Method 2 - AG.createmultilinestring() do multiline - AG.addgeom!(multiline, AG.createlinestring( - [(1214242.4174581182, 617041.9717021306), - (1234593.142744733, 629529.9167643716)])) - AG.addgeom!(multiline, AG.createlinestring( - [(1184641.3624957693, 626754.8178616514), - (1219792.6152635587, 606866.6090588232)])) - @test AG.toWKT(multiline) == wktline - end + # Method 2 + AG.createmultilinestring() do multiline + AG.addgeom!( + multiline, + AG.createlinestring([ + (1214242.4174581182, 617041.9717021306), + (1234593.142744733, 629529.9167643716), + ]), + ) + AG.addgeom!( + multiline, + AG.createlinestring([ + (1184641.3624957693, 626754.8178616514), + (1219792.6152635587, 606866.6090588232), + ]), + ) + @test AG.toWKT(multiline) == wktline + end - # Method 3 - AG.creategeom(AG.wkbMultiLineString) do multiline - line = AG.creategeom(AG.wkbLineString) + # Method 3 + AG.creategeom(AG.wkbMultiLineString) do multiline + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1214242.4174581182, 617041.9717021306) AG.addpoint!(line, 1234593.142744733, 629529.9167643716) - AG.addgeom!(multiline, line) + AG.addgeom!(multiline, line) - line = AG.creategeom(AG.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, 1184641.3624957693, 626754.8178616514) AG.addpoint!(line, 1219792.6152635587, 606866.6090588232) - AG.addgeom!(multiline, line) + AG.addgeom!(multiline, line) - @test AG.toWKT(multiline) == wktline - end + @test AG.toWKT(multiline) == wktline + end - # Method 4 - multiline = AG.creategeom(AG.wkbMultiLineString) + # Method 4 + multiline = AG.creategeom(AG.wkbMultiLineString) line = AG.creategeom(AG.wkbLineString) - AG.addpoint!(line, 1214242.4174581182, 617041.9717021306) - AG.addpoint!(line, 1234593.142744733, 629529.9167643716) + AG.addpoint!(line, 1214242.4174581182, 617041.9717021306) + AG.addpoint!(line, 1234593.142744733, 629529.9167643716) AG.addgeom!(multiline, line) line = AG.creategeom(AG.wkbLineString) - AG.addpoint!(line, 1184641.3624957693, 626754.8178616514) - AG.addpoint!(line, 1219792.6152635587, 606866.6090588232) + AG.addpoint!(line, 1184641.3624957693, 626754.8178616514) + AG.addpoint!(line, 1219792.6152635587, 606866.6090588232) AG.addgeom!(multiline, line) - - @test AG.toWKT(multiline) == wktline - - # Method 5 - @test AG.toWKT(AG.createmultilinestring(Vector{Tuple{Float64,Float64}}[ - [(1214242.4174581182, 617041.9717021306), - (1234593.142744733, 629529.9167643716)], - [(1184641.3624957693, 626754.8178616514), - (1219792.6152635587, 606866.6090588232)] - ])) == wktline -end -@testset "Create a MultiPolygon" begin - - wktmultipolygon = "MULTIPOLYGON " * - "(((1204067.05481481 634617.598086025,1204067.05481481 620742.103572424," * - "1215167.45042569 620742.103572424,1215167.45042569 634617.598086025," * - "1204067.05481481 634617.598086025))," * - "((1179553.68117412 647105.543148266,1179553.68117412 626292.301377865," * - "1194354.20865529 626292.301377865,1194354.20865529 647105.543148266," * - "1179553.68117412 647105.543148266)))" - - # Method 1 - AG.createmultipolygon_noholes(Vector{Tuple{Float64,Float64}}[ - [(1204067.0548148106, 634617.5980860253), - (1204067.0548148106, 620742.1035724243), - (1215167.4504256917, 620742.1035724243), - (1215167.4504256917, 634617.5980860253), - (1204067.0548148106, 634617.5980860253)], - [(1179553.6811741155, 647105.5431482664), - (1179553.6811741155, 626292.3013778647), - (1194354.20865529, 626292.3013778647), - (1194354.20865529, 647105.5431482664), - (1179553.6811741155, 647105.5431482664)] - ]) do multipolygon - @test AG.toWKT(multipolygon) == wktmultipolygon - end + @test AG.toWKT(multiline) == wktline - # Method 2 - AG.createmultipolygon() do multipolygon - poly = AG.createpolygon( - [(1204067.0548148106, 634617.5980860253), - (1204067.0548148106, 620742.1035724243), - (1215167.4504256917, 620742.1035724243), - (1215167.4504256917, 634617.5980860253), - (1204067.0548148106, 634617.5980860253)]) - AG.addgeom!(multipolygon,poly) - - poly = AG.createpolygon( - [(1179553.6811741155, 647105.5431482664), - (1179553.6811741155, 626292.3013778647), - (1194354.20865529, 626292.3013778647), - (1194354.20865529, 647105.5431482664), - (1179553.6811741155, 647105.5431482664)]) - AG.addgeom!(multipolygon,poly) + # Method 5 + @test AG.toWKT( + AG.createmultilinestring( + Vector{Tuple{Float64,Float64}}[ + [ + (1214242.4174581182, 617041.9717021306), + (1234593.142744733, 629529.9167643716), + ], + [ + (1184641.3624957693, 626754.8178616514), + (1219792.6152635587, 606866.6090588232), + ], + ], + ), + ) == wktline + end + + @testset "Create a MultiPolygon" begin + + wktmultipolygon = + "MULTIPOLYGON " * + "(((1204067.05481481 634617.598086025,1204067.05481481 620742.103572424," * + "1215167.45042569 620742.103572424,1215167.45042569 634617.598086025," * + "1204067.05481481 634617.598086025))," * + "((1179553.68117412 647105.543148266,1179553.68117412 626292.301377865," * + "1194354.20865529 626292.301377865,1194354.20865529 647105.543148266," * + "1179553.68117412 647105.543148266)))" + + # Method 1 + AG.createmultipolygon_noholes( + Vector{Tuple{Float64,Float64}}[ + [ + (1204067.0548148106, 634617.5980860253), + (1204067.0548148106, 620742.1035724243), + (1215167.4504256917, 620742.1035724243), + (1215167.4504256917, 634617.5980860253), + (1204067.0548148106, 634617.5980860253), + ], + [ + (1179553.6811741155, 647105.5431482664), + (1179553.6811741155, 626292.3013778647), + (1194354.20865529, 626292.3013778647), + (1194354.20865529, 647105.5431482664), + (1179553.6811741155, 647105.5431482664), + ], + ], + ) do multipolygon + @test AG.toWKT(multipolygon) == wktmultipolygon + end - @test AG.toWKT(multipolygon) == wktmultipolygon - end + # Method 2 + AG.createmultipolygon() do multipolygon + poly = AG.createpolygon([ + (1204067.0548148106, 634617.5980860253), + (1204067.0548148106, 620742.1035724243), + (1215167.4504256917, 620742.1035724243), + (1215167.4504256917, 634617.5980860253), + (1204067.0548148106, 634617.5980860253), + ]) + AG.addgeom!(multipolygon, poly) + + poly = AG.createpolygon([ + (1179553.6811741155, 647105.5431482664), + (1179553.6811741155, 626292.3013778647), + (1194354.20865529, 626292.3013778647), + (1194354.20865529, 647105.5431482664), + (1179553.6811741155, 647105.5431482664), + ]) + AG.addgeom!(multipolygon, poly) + + @test AG.toWKT(multipolygon) == wktmultipolygon + end - # Method 3 - AG.creategeom(AG.wkbMultiPolygon) do multipolygon - poly = AG.creategeom(AG.wkbPolygon) + # Method 3 + AG.creategeom(AG.wkbMultiPolygon) do multipolygon + poly = AG.creategeom(AG.wkbPolygon) ring = AG.creategeom(AG.wkbLinearRing) - AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) - AG.addpoint!(ring, 1204067.0548148106, 620742.1035724243) - AG.addpoint!(ring, 1215167.4504256917, 620742.1035724243) - AG.addpoint!(ring, 1215167.4504256917, 634617.5980860253) - AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) + AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) + AG.addpoint!(ring, 1204067.0548148106, 620742.1035724243) + AG.addpoint!(ring, 1215167.4504256917, 620742.1035724243) + AG.addpoint!(ring, 1215167.4504256917, 634617.5980860253) + AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) AG.addgeom!(poly, ring) - AG.addgeom!(multipolygon,poly) + AG.addgeom!(multipolygon, poly) - poly = AG.creategeom(AG.wkbPolygon) + poly = AG.creategeom(AG.wkbPolygon) ring = AG.creategeom(AG.wkbLinearRing) - AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) - AG.addpoint!(ring, 1179553.6811741155, 626292.3013778647) - AG.addpoint!(ring, 1194354.20865529, 626292.3013778647) - AG.addpoint!(ring, 1194354.20865529, 647105.5431482664) - AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) + AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) + AG.addpoint!(ring, 1179553.6811741155, 626292.3013778647) + AG.addpoint!(ring, 1194354.20865529, 626292.3013778647) + AG.addpoint!(ring, 1194354.20865529, 647105.5431482664) + AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) AG.addgeom!(poly, ring) - AG.addgeom!(multipolygon,poly) + AG.addgeom!(multipolygon, poly) - @test AG.toWKT(multipolygon) == wktmultipolygon - end + @test AG.toWKT(multipolygon) == wktmultipolygon + end - # Method 4 - multipolygon = AG.creategeom(AG.wkbMultiPolygon) + # Method 4 + multipolygon = AG.creategeom(AG.wkbMultiPolygon) poly = AG.creategeom(AG.wkbPolygon) - ring = AG.creategeom(AG.wkbLinearRing) - AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) - AG.addpoint!(ring, 1204067.0548148106, 620742.1035724243) - AG.addpoint!(ring, 1215167.4504256917, 620742.1035724243) - AG.addpoint!(ring, 1215167.4504256917, 634617.5980860253) - AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) - AG.addgeom!(poly, ring) - AG.addgeom!(multipolygon,poly) + ring = AG.creategeom(AG.wkbLinearRing) + AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) + AG.addpoint!(ring, 1204067.0548148106, 620742.1035724243) + AG.addpoint!(ring, 1215167.4504256917, 620742.1035724243) + AG.addpoint!(ring, 1215167.4504256917, 634617.5980860253) + AG.addpoint!(ring, 1204067.0548148106, 634617.5980860253) + AG.addgeom!(poly, ring) + AG.addgeom!(multipolygon, poly) poly = AG.creategeom(AG.wkbPolygon) - ring = AG.creategeom(AG.wkbLinearRing) - AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) - AG.addpoint!(ring, 1179553.6811741155, 626292.3013778647) - AG.addpoint!(ring, 1194354.20865529, 626292.3013778647) - AG.addpoint!(ring, 1194354.20865529, 647105.5431482664) - AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) - AG.addgeom!(poly, ring) - AG.addgeom!(multipolygon,poly) - - @test AG.toWKT(multipolygon) == wktmultipolygon - - # Method 5 - @test AG.toWKT(AG.createmultipolygon_noholes(Vector{Tuple{Float64,Float64}}[ - [(1204067.0548148106, 634617.5980860253), - (1204067.0548148106, 620742.1035724243), - (1215167.4504256917, 620742.1035724243), - (1215167.4504256917, 634617.5980860253), - (1204067.0548148106, 634617.5980860253)], - [(1179553.6811741155, 647105.5431482664), - (1179553.6811741155, 626292.3013778647), - (1194354.20865529, 626292.3013778647), - (1194354.20865529, 647105.5431482664), - (1179553.6811741155, 647105.5431482664)] - ])) == wktmultipolygon -end - -@testset "Create a GeometryCollection" begin - - wktcollection = "GEOMETRYCOLLECTION " * - "(POINT (-122.23 47.09),LINESTRING (-122.6 47.14,-122.48 47.23))" + ring = AG.creategeom(AG.wkbLinearRing) + AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) + AG.addpoint!(ring, 1179553.6811741155, 626292.3013778647) + AG.addpoint!(ring, 1194354.20865529, 626292.3013778647) + AG.addpoint!(ring, 1194354.20865529, 647105.5431482664) + AG.addpoint!(ring, 1179553.6811741155, 647105.5431482664) + AG.addgeom!(poly, ring) + AG.addgeom!(multipolygon, poly) - # Method not applicable here + @test AG.toWKT(multipolygon) == wktmultipolygon - # Method 2 - AG.creategeomcollection() do geomcol - for g in [AG.createpoint(-122.23, 47.09), - AG.createlinestring([(-122.60, 47.14), (-122.48, 47.23)])] - AG.addgeom!(geomcol, g) + # Method 5 + @test AG.toWKT( + AG.createmultipolygon_noholes( + Vector{Tuple{Float64,Float64}}[ + [ + (1204067.0548148106, 634617.5980860253), + (1204067.0548148106, 620742.1035724243), + (1215167.4504256917, 620742.1035724243), + (1215167.4504256917, 634617.5980860253), + (1204067.0548148106, 634617.5980860253), + ], + [ + (1179553.6811741155, 647105.5431482664), + (1179553.6811741155, 626292.3013778647), + (1194354.20865529, 626292.3013778647), + (1194354.20865529, 647105.5431482664), + (1179553.6811741155, 647105.5431482664), + ], + ], + ), + ) == wktmultipolygon + end + + @testset "Create a GeometryCollection" begin + + wktcollection = + "GEOMETRYCOLLECTION " * + "(POINT (-122.23 47.09),LINESTRING (-122.6 47.14,-122.48 47.23))" + + # Method not applicable here + + # Method 2 + AG.creategeomcollection() do geomcol + for g in [ + AG.createpoint(-122.23, 47.09), + AG.createlinestring([(-122.60, 47.14), (-122.48, 47.23)]), + ] + AG.addgeom!(geomcol, g) + end + @test AG.toWKT(geomcol) == wktcollection end - @test AG.toWKT(geomcol) == wktcollection - end - # Method 3 - AG.creategeom(AG.wkbGeometryCollection) do geomcol - point = AG.creategeom(AG.wkbPoint) + # Method 3 + AG.creategeom(AG.wkbGeometryCollection) do geomcol + point = AG.creategeom(AG.wkbPoint) AG.addpoint!(point, -122.23, 47.09) - AG.addgeom!(geomcol, point) + AG.addgeom!(geomcol, point) - line = AG.creategeom(AG.wkbLineString) + line = AG.creategeom(AG.wkbLineString) AG.addpoint!(line, -122.60, 47.14) AG.addpoint!(line, -122.48, 47.23) - AG.addgeom!(geomcol, line) + AG.addgeom!(geomcol, line) - @test AG.toWKT(geomcol) == wktcollection - end + @test AG.toWKT(geomcol) == wktcollection + end - # Method 4 - geomcol = AG.creategeom(AG.wkbGeometryCollection) + # Method 4 + geomcol = AG.creategeom(AG.wkbGeometryCollection) point = AG.creategeom(AG.wkbPoint) - AG.addpoint!(point, -122.23, 47.09) + AG.addpoint!(point, -122.23, 47.09) AG.addgeom!(geomcol, point) line = AG.creategeom(AG.wkbLineString) - AG.addpoint!(line, -122.60, 47.14) - AG.addpoint!(line, -122.48, 47.23) + AG.addpoint!(line, -122.60, 47.14) + AG.addpoint!(line, -122.48, 47.23) AG.addgeom!(geomcol, line) - @test AG.toWKT(geomcol) == wktcollection -end + @test AG.toWKT(geomcol) == wktcollection + end -@testset "Create Geometry from WKT" begin - wkt = "POINT (1120351.5712494177 741921.4223245403)" - x, y = 1120351.5712494177, 741921.4223245403 + @testset "Create Geometry from WKT" begin + wkt = "POINT (1120351.5712494177 741921.4223245403)" + x, y = 1120351.5712494177, 741921.4223245403 - # Method 1 - AG.fromWKT(wkt) do point + # Method 1 + AG.fromWKT(wkt) do point + @test AG.getx(point, 0) ≈ x + @test AG.gety(point, 0) ≈ y + end + + # Method 2 + point = AG.fromWKT(wkt) @test AG.getx(point, 0) ≈ x @test AG.gety(point, 0) ≈ y end - # Method 2 - point = AG.fromWKT(wkt) - @test AG.getx(point, 0) ≈ x - @test AG.gety(point, 0) ≈ y -end + @testset "Create Geometry from GeoJSON" begin + geojson = """{"type":"Point","coordinates":[108420.33,753808.59]}""" + x, y = 108420.33, 753808.59 -@testset "Create Geometry from GeoJSON" begin - geojson = """{"type":"Point","coordinates":[108420.33,753808.59]}""" - x, y = 108420.33, 753808.59 + # Method 1 + AG.fromJSON(geojson) do point + @test AG.getx(point, 0) ≈ x + @test AG.gety(point, 0) ≈ y + end - # Method 1 - AG.fromJSON(geojson) do point + # Method 2 + point = AG.fromJSON(geojson) @test AG.getx(point, 0) ≈ x @test AG.gety(point, 0) ≈ y end - # Method 2 - point = AG.fromJSON(geojson) - @test AG.getx(point, 0) ≈ x - @test AG.gety(point, 0) ≈ y -end + @testset "Create Geometry from GML" begin + gml = """ + 108420.33,753808.59 + """ + x, y = 108420.33, 753808.59 -@testset "Create Geometry from GML" begin - gml = """ - 108420.33,753808.59 - """ - x, y = 108420.33, 753808.59 + # Method 1 + AG.fromGML(gml) do point + @test AG.getx(point, 0) ≈ x + @test AG.gety(point, 0) ≈ y + end - # Method 1 - AG.fromGML(gml) do point + # Method 2 + point = AG.fromGML(gml) @test AG.getx(point, 0) ≈ x @test AG.gety(point, 0) ≈ y end - # Method 2 - point = AG.fromGML(gml) - @test AG.getx(point, 0) ≈ x - @test AG.gety(point, 0) ≈ y -end - -@testset "Create Geometry from WKB" begin - wkb = [0x01,0x01,0x00,0x00,0x00,0x7b,0x14,0xae,0x47,0x45,0x78,0xfa,0x40, - 0xe1,0x7a,0x14,0x2e,0x21,0x01,0x27,0x41] - x, y = 108420.33, 753808.59 + @testset "Create Geometry from WKB" begin + wkb = [ + 0x01, + 0x01, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x14, + 0xae, + 0x47, + 0x45, + 0x78, + 0xfa, + 0x40, + 0xe1, + 0x7a, + 0x14, + 0x2e, + 0x21, + 0x01, + 0x27, + 0x41, + ] + x, y = 108420.33, 753808.59 + + # Method 1 + AG.fromWKB(wkb) do point + @test AG.getx(point, 0) ≈ x + @test AG.gety(point, 0) ≈ y + end - # Method 1 - AG.fromWKB(wkb) do point + # Method 2 + point = AG.fromWKB(wkb) @test AG.getx(point, 0) ≈ x @test AG.gety(point, 0) ≈ y end - # Method 2 - point = AG.fromWKB(wkb) - @test AG.getx(point, 0) ≈ x - @test AG.gety(point, 0) ≈ y -end + @testset "Count Points in a LineString" begin + wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" -@testset "Count Points in a LineString" begin - wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" + # Method 1 + AG.fromWKT(wkt) do geom + @test AG.ngeom(geom) == 4 + end - # Method 1 - AG.fromWKT(wkt) do geom - @test AG.ngeom(geom) == 4 + # Method 2 + @test AG.ngeom(AG.fromWKT(wkt)) == 4 end - # Method 2 - @test AG.ngeom(AG.fromWKT(wkt)) == 4 -end + @testset "Count Points in a MultiPoint" begin + wkt = "MULTIPOINT (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" -@testset "Count Points in a MultiPoint" begin - wkt = "MULTIPOINT (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" + # Method 1 + AG.fromWKT(wkt) do geom + @test AG.ngeom(geom) == 4 + end - # Method 1 - AG.fromWKT(wkt) do geom - @test AG.ngeom(geom) == 4 + # Method 2 + @test AG.ngeom(AG.fromWKT(wkt)) == 4 end - # Method 2 - @test AG.ngeom(AG.fromWKT(wkt)) == 4 -end - -@testset "Iterate over Geometries in a Geometry" begin - wkt = "MULTIPOINT (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" - AG.fromWKT(wkt) do geom - # TODO Should getgeom use Julian counting from 1? - @test AG.toWKT(AG.getgeom(geom, 3)) == "POINT (1224880.29658521 665143.686015948)" + @testset "Iterate over Geometries in a Geometry" begin + wkt = "MULTIPOINT (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" + AG.fromWKT(wkt) do geom + # TODO Should getgeom use Julian counting from 1? + @test AG.toWKT(AG.getgeom(geom, 3)) == + "POINT (1224880.29658521 665143.686015948)" + end end -end -@testset "Iterate over Points in a Geometry" begin - wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" - AG.fromWKT(wkt) do geom - @test AG.getpoint(geom, 3) == (1.2248802965852122e6, 665143.6860159477, 0.0) + @testset "Iterate over Points in a Geometry" begin + wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" + AG.fromWKT(wkt) do geom + @test AG.getpoint(geom, 3) == (1.2248802965852122e6, 665143.6860159477, 0.0) + end end -end -@testset "Buffer a Geometry" begin - wkt = "POINT (1198054.34 648493.09)" + @testset "Buffer a Geometry" begin + wkt = "POINT (1198054.34 648493.09)" - # Method 1 - AG.fromWKT(wkt) do pt - bufferdist = 500 - AG.buffer(pt, bufferdist) do poly - @test AG.getgeomtype(poly) == AG.wkbPolygon + # Method 1 + AG.fromWKT(wkt) do pt + bufferdist = 500 + AG.buffer(pt, bufferdist) do poly + @test AG.getgeomtype(poly) == AG.wkbPolygon + end end - end - - # Method 2 - @test AG.getgeomtype(AG.buffer(AG.fromWKT(wkt), 500)) == AG.wkbPolygon -end -@testset "Calculate Envelope of a Geometry" begin - wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" - AG.fromWKT(wkt) do line - env = AG.envelope(line) - @test (env.MaxX - env.MinX) * (env.MaxY - env.MinY) ≈ 2.2431808256625123e9 + # Method 2 + @test AG.getgeomtype(AG.buffer(AG.fromWKT(wkt), 500)) == AG.wkbPolygon end -end -@testset "Calculate Bounding Box of a Geometry" begin - wkt = "POLYGON ((1162440.5712740074 672081.4332727483, 1162440.5712740074 647105.5431482664, 1195279.2416228633 647105.5431482664, 1195279.2416228633 672081.4332727483, 1162440.5712740074 672081.4332727483))" - expected = AG.createpolygon([[672081.4332727483, 1162440.5712740074], [672081.4332727483, 1195279.2416228633], [647105.5431482664, 1195279.2416228633], [647105.5431482664, 1162440.5712740074], [672081.4332727483, 1162440.5712740074]]) - AG.fromWKT(wkt) do polygon - calculated = AG.boundingbox(polygon) - @test AG.equals(expected, calculated) + @testset "Calculate Envelope of a Geometry" begin + wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" + AG.fromWKT(wkt) do line + env = AG.envelope(line) + @test (env.MaxX - env.MinX) * (env.MaxY - env.MinY) ≈ 2.2431808256625123e9 + end end -end -@testset "Calculate the Area of a Geometry" begin - wkt = "POLYGON ((1162440.5712740074 672081.4332727483, 1162440.5712740074 647105.5431482664, 1195279.2416228633 647105.5431482664, 1195279.2416228633 672081.4332727483, 1162440.5712740074 672081.4332727483))" - AG.fromWKT(wkt) do poly - @test AG.geomarea(poly) ≈ 8.201750224671059e8 + @testset "Calculate Bounding Box of a Geometry" begin + wkt = "POLYGON ((1162440.5712740074 672081.4332727483, 1162440.5712740074 647105.5431482664, 1195279.2416228633 647105.5431482664, 1195279.2416228633 672081.4332727483, 1162440.5712740074 672081.4332727483))" + expected = AG.createpolygon([ + [672081.4332727483, 1162440.5712740074], + [672081.4332727483, 1195279.2416228633], + [647105.5431482664, 1195279.2416228633], + [647105.5431482664, 1162440.5712740074], + [672081.4332727483, 1162440.5712740074], + ]) + AG.fromWKT(wkt) do polygon + calculated = AG.boundingbox(polygon) + @test AG.equals(expected, calculated) + end end -end -@testset "Calculate the Length of a Geometry" begin - wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" - AG.fromWKT(wkt) do line - @test AG.geomlength(line) ≈ 76121.94397805972 + @testset "Calculate the Area of a Geometry" begin + wkt = "POLYGON ((1162440.5712740074 672081.4332727483, 1162440.5712740074 647105.5431482664, 1195279.2416228633 647105.5431482664, 1195279.2416228633 672081.4332727483, 1162440.5712740074 672081.4332727483))" + AG.fromWKT(wkt) do poly + @test AG.geomarea(poly) ≈ 8.201750224671059e8 + end end -end -@testset "Get the geometry type (as a string) from a Geometry" begin - types = ["POINT", "LINESTRING", "POLYGON"] - wkts = [ - "POINT (1198054.34 648493.09)", - "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)", - "POLYGON ((1162440.5712740074 672081.4332727483, 1162440.5712740074 647105.5431482664, 1195279.2416228633 647105.5431482664, 1195279.2416228633 672081.4332727483, 1162440.5712740074 672081.4332727483))" - ] - for (i, wkt) in enumerate(wkts) - AG.fromWKT(wkt) do geom - @test AG.geomname(geom) == types[i] + @testset "Calculate the Length of a Geometry" begin + wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" + AG.fromWKT(wkt) do line + @test AG.geomlength(line) ≈ 76121.94397805972 end end -end - -@testset "Calculate intersection between two Geometries" begin - wkt1 = "POLYGON ((1208064.271243039 624154.6783778917, 1208064.271243039 601260.9785661874, 1231345.9998651114 601260.9785661874, 1231345.9998651114 624154.6783778917, 1208064.271243039 624154.6783778917))" - wkt2 = "POLYGON ((1199915.6662253144 633079.3410163528, 1199915.6662253144 614453.958118695, 1219317.1067437078 614453.958118695, 1219317.1067437078 633079.3410163528, 1199915.6662253144 633079.3410163528)))" - wkt3 = "POLYGON ((1208064.27124304 624154.678377892,1219317.10674371 624154.678377892,1219317.10674371 614453.958118695,1208064.27124304 614453.958118695,1208064.27124304 624154.678377892))" - - # Method 1 - AG.fromWKT(wkt1) do poly1 - AG.fromWKT(wkt2) do poly2 - AG.intersection(poly1, poly2) do poly3 - @test AG.toWKT(poly3) == wkt3 + @testset "Get the geometry type (as a string) from a Geometry" begin + types = ["POINT", "LINESTRING", "POLYGON"] + wkts = [ + "POINT (1198054.34 648493.09)", + "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)", + "POLYGON ((1162440.5712740074 672081.4332727483, 1162440.5712740074 647105.5431482664, 1195279.2416228633 647105.5431482664, 1195279.2416228633 672081.4332727483, 1162440.5712740074 672081.4332727483))", + ] + for (i, wkt) in enumerate(wkts) + AG.fromWKT(wkt) do geom + @test AG.geomname(geom) == types[i] + end end end - end - # Method 2 - @test AG.toWKT(AG.intersection(AG.fromWKT(wkt1), AG.fromWKT(wkt2))) == wkt3 -end + @testset "Calculate intersection between two Geometries" begin + wkt1 = "POLYGON ((1208064.271243039 624154.6783778917, 1208064.271243039 601260.9785661874, 1231345.9998651114 601260.9785661874, 1231345.9998651114 624154.6783778917, 1208064.271243039 624154.6783778917))" + wkt2 = "POLYGON ((1199915.6662253144 633079.3410163528, 1199915.6662253144 614453.958118695, 1219317.1067437078 614453.958118695, 1219317.1067437078 633079.3410163528, 1199915.6662253144 633079.3410163528)))" + wkt3 = "POLYGON ((1208064.27124304 624154.678377892,1219317.10674371 624154.678377892,1219317.10674371 614453.958118695,1208064.27124304 614453.958118695,1208064.27124304 624154.678377892))" -@testset "Calculate union between two Geometries" begin - wkt1 = "POLYGON ((1208064.271243039 624154.6783778917, 1208064.271243039 601260.9785661874, 1231345.9998651114 601260.9785661874, 1231345.9998651114 624154.6783778917, 1208064.271243039 624154.6783778917))" - wkt2 = "POLYGON ((1199915.6662253144 633079.3410163528, 1199915.6662253144 614453.958118695, 1219317.1067437078 614453.958118695, 1219317.1067437078 633079.3410163528, 1199915.6662253144 633079.3410163528)))" - wkt3 = "POLYGON ((1199915.66622531 614453.958118695,1199915.66622531 633079.341016353,1219317.10674371 633079.341016353,1219317.10674371 624154.678377892,1231345.99986511 624154.678377892,1231345.99986511 601260.978566187,1208064.27124304 601260.978566187,1208064.27124304 614453.958118695,1199915.66622531 614453.958118695))" - # Method 1 - AG.fromWKT(wkt1) do poly1 - AG.fromWKT(wkt2) do poly2 - AG.union(poly1, poly2) do poly3 - @test AG.toWKT(poly3) == wkt3 + # Method 1 + AG.fromWKT(wkt1) do poly1 + AG.fromWKT(wkt2) do poly2 + AG.intersection(poly1, poly2) do poly3 + @test AG.toWKT(poly3) == wkt3 + end + end end - end + + # Method 2 + @test AG.toWKT(AG.intersection(AG.fromWKT(wkt1), AG.fromWKT(wkt2))) == wkt3 end - # Method 2 - @test AG.toWKT(AG.union(AG.fromWKT(wkt1), AG.fromWKT(wkt2))) == wkt3 -end + @testset "Calculate union between two Geometries" begin + wkt1 = "POLYGON ((1208064.271243039 624154.6783778917, 1208064.271243039 601260.9785661874, 1231345.9998651114 601260.9785661874, 1231345.9998651114 624154.6783778917, 1208064.271243039 624154.6783778917))" + wkt2 = "POLYGON ((1199915.6662253144 633079.3410163528, 1199915.6662253144 614453.958118695, 1219317.1067437078 614453.958118695, 1219317.1067437078 633079.3410163528, 1199915.6662253144 633079.3410163528)))" + wkt3 = "POLYGON ((1199915.66622531 614453.958118695,1199915.66622531 633079.341016353,1219317.10674371 633079.341016353,1219317.10674371 624154.678377892,1231345.99986511 624154.678377892,1231345.99986511 601260.978566187,1208064.27124304 601260.978566187,1208064.27124304 614453.958118695,1199915.66622531 614453.958118695))" + + # Method 1 + AG.fromWKT(wkt1) do poly1 + AG.fromWKT(wkt2) do poly2 + AG.union(poly1, poly2) do poly3 + @test AG.toWKT(poly3) == wkt3 + end + end + end -@testset "Write Geometry to GeoJSON|GML|WKT|WKB" begin - AG.createpolygon([(1179091.1646903288, 712782.8838459781), - (1161053.0218226474, 667456.2684348812), - (1214704.933941905, 641092.8288590391), - (1228580.428455506, 682719.3123998424), - (1218405.0658121984, 721108.1805541387), - (1179091.1646903288, 712782.8838459781)]) do poly - @test AG.toJSON(poly)[1:19] == "{ \"type\": \"Polygon\"" - @test AG.toGML(poly)[1:13] == "" - @test AG.toWKT(poly)[1:7] == "POLYGON" - @test AG.toWKB(poly) == UInt8[0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x25, 0x29, 0x2a, 0xd3, 0xfd, 0x31, 0x41, 0xc5, 0x75, 0x87, 0xc4, 0x9d, 0xc0, 0x25, 0x41, 0x45, 0x2b, 0x96, 0x05, 0x5d, 0xb7, 0x31, 0x41, 0xf8, 0x4b, 0x70, 0x89, 0x80, 0x5e, 0x24, 0x41, 0x12, 0xd1, 0x16, 0xef, 0xf0, 0x88, 0x32, 0x41, 0x44, 0x36, 0x60, 0xa8, 0x89, 0x90, 0x23, 0x41, 0x92, 0x42, 0xaf, 0x6d, 0x24, 0xbf, 0x32, 0x41, 0x45, 0xdf, 0xf2, 0x9f, 0xbe, 0xd5, 0x24, 0x41, 0x78, 0x11, 0xd9, 0x10, 0x65, 0x97, 0x32, 0x41, 0x92, 0x97, 0x71, 0x5c, 0xa8, 0x01, 0x26, 0x41, 0x38, 0x25, 0x29, 0x2a, 0xd3, 0xfd, 0x31, 0x41, 0xc5, 0x75, 0x87, 0xc4, 0x9d, 0xc0, 0x25, 0x41] + # Method 2 + @test AG.toWKT(AG.union(AG.fromWKT(wkt1), AG.fromWKT(wkt2))) == wkt3 + end + + @testset "Write Geometry to GeoJSON|GML|WKT|WKB" begin + AG.createpolygon([ + (1179091.1646903288, 712782.8838459781), + (1161053.0218226474, 667456.2684348812), + (1214704.933941905, 641092.8288590391), + (1228580.428455506, 682719.3123998424), + (1218405.0658121984, 721108.1805541387), + (1179091.1646903288, 712782.8838459781), + ]) do poly + @test AG.toJSON(poly)[1:19] == "{ \"type\": \"Polygon\"" + @test AG.toGML(poly)[1:13] == "" + @test AG.toWKT(poly)[1:7] == "POLYGON" + @test AG.toWKB(poly) == UInt8[ + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x38, + 0x25, + 0x29, + 0x2a, + 0xd3, + 0xfd, + 0x31, + 0x41, + 0xc5, + 0x75, + 0x87, + 0xc4, + 0x9d, + 0xc0, + 0x25, + 0x41, + 0x45, + 0x2b, + 0x96, + 0x05, + 0x5d, + 0xb7, + 0x31, + 0x41, + 0xf8, + 0x4b, + 0x70, + 0x89, + 0x80, + 0x5e, + 0x24, + 0x41, + 0x12, + 0xd1, + 0x16, + 0xef, + 0xf0, + 0x88, + 0x32, + 0x41, + 0x44, + 0x36, + 0x60, + 0xa8, + 0x89, + 0x90, + 0x23, + 0x41, + 0x92, + 0x42, + 0xaf, + 0x6d, + 0x24, + 0xbf, + 0x32, + 0x41, + 0x45, + 0xdf, + 0xf2, + 0x9f, + 0xbe, + 0xd5, + 0x24, + 0x41, + 0x78, + 0x11, + 0xd9, + 0x10, + 0x65, + 0x97, + 0x32, + 0x41, + 0x92, + 0x97, + 0x71, + 0x5c, + 0xa8, + 0x01, + 0x26, + 0x41, + 0x38, + 0x25, + 0x29, + 0x2a, + 0xd3, + 0xfd, + 0x31, + 0x41, + 0xc5, + 0x75, + 0x87, + 0xc4, + 0x9d, + 0xc0, + 0x25, + 0x41, + ] + end end -end -@testset "Force polygon to multipolygon" begin - wkt = "POLYGON ((1179091.164690328761935 712782.883845978067257,1161053.021822647424415 667456.268434881232679,1214704.933941904921085 641092.828859039116651,1228580.428455505985767 682719.312399842427112,1218405.065812198445201 721108.180554138729349,1179091.164690328761935 712782.883845978067257))" + @testset "Force polygon to multipolygon" begin + wkt = "POLYGON ((1179091.164690328761935 712782.883845978067257,1161053.021822647424415 667456.268434881232679,1214704.933941904921085 641092.828859039116651,1228580.428455505985767 682719.312399842427112,1218405.065812198445201 721108.180554138729349,1179091.164690328761935 712782.883845978067257))" - # Method 1 - AG.fromWKT(wkt) do poly - @test AG.getgeomtype(poly) == AG.wkbPolygon - AG.forceto(poly, AG.wkbMultiPolygon) do mpoly - @test AG.getgeomtype(mpoly) == AG.wkbMultiPolygon + # Method 1 + AG.fromWKT(wkt) do poly + @test AG.getgeomtype(poly) == AG.wkbPolygon + AG.forceto(poly, AG.wkbMultiPolygon) do mpoly + @test AG.getgeomtype(mpoly) == AG.wkbMultiPolygon + end end - end - # Method 2 - @test AG.getgeomtype(AG.forceto(AG.fromWKT(wkt), AG.wkbMultiPolygon)) == AG.wkbMultiPolygon -end + # Method 2 + @test AG.getgeomtype(AG.forceto(AG.fromWKT(wkt), AG.wkbMultiPolygon)) == + AG.wkbMultiPolygon + end end diff --git a/test/test_cookbook_projection.jl b/test/test_cookbook_projection.jl index 1e286ddf..39c6e21d 100644 --- a/test/test_cookbook_projection.jl +++ b/test/test_cookbook_projection.jl @@ -1,102 +1,138 @@ using Test -import GeoInterface, GeoFormatTypes, ArchGDAL +import GeoInterface, GeoFormatTypes, ArchGDAL const AG = ArchGDAL const GFT = GeoFormatTypes @testset "test_cookbook_projection.jl" begin -@testset "Reproject a Geometry" begin - @testset "Method 1" begin - AG.importEPSG(2927) do source; AG.importEPSG(4326) do target - AG.createcoordtrans(source, target) do transform - AG.fromWKT("POINT (1120351.57 741921.42)") do point - @test AG.toWKT(point) == "POINT (1120351.57 741921.42)" - AG.transform!(point, transform) - @test GeoInterface.coordinates(point) ≈ [47.3488070138318, -122.5981499431438] - end end end end - end - - @testset "Method 2" begin - AG.importEPSG(2927) do source; AG.importEPSG(4326) do target - AG.createcoordtrans(source, target) do transform - xs = [47.348801, 47.348801] - ys = [-122.598135,-122.598135] - zs = [0.0, 0.0] - @test AG.transform!(xs, ys, zs, transform) == true - @test xs ≈ [45.151458, 45.151458] - @test ys ≈ [-126.863475, -126.863475] - @test zs ≈ [0.0, 0.0] - end end end - end + @testset "Reproject a Geometry" begin + @testset "Method 1" begin + AG.importEPSG(2927) do source + AG.importEPSG(4326) do target + AG.createcoordtrans(source, target) do transform + AG.fromWKT("POINT (1120351.57 741921.42)") do point + @test AG.toWKT(point) == "POINT (1120351.57 741921.42)" + AG.transform!(point, transform) + @test GeoInterface.coordinates(point) ≈ + [47.3488070138318, -122.5981499431438] + end + end + end + end + end - @testset "Use reproject" begin - @testset "reciprocal reprojection of wkt" begin - wktpoint = GFT.WellKnownText(GFT.Geom(), "POINT (1120351.57 741921.42)") - result = GFT.WellKnownText(GFT.Geom(), "POINT (47.3488070138318 -122.598149943144)") - @test AG.reproject(wktpoint, GFT.EPSG(2927), GFT.EPSG(4326)) == result - @test convert(AG.Geometry, AG.reproject(result, GFT.EPSG(4326), GFT.EPSG(2927))) |> - GeoInterface.coordinates ≈ [1.12035156999967e6, 741921.420000271] + @testset "Method 2" begin + AG.importEPSG(2927) do source + AG.importEPSG(4326) do target + AG.createcoordtrans(source, target) do transform + xs = [47.348801, 47.348801] + ys = [-122.598135, -122.598135] + zs = [0.0, 0.0] + @test AG.transform!(xs, ys, zs, transform) == true + @test xs ≈ [45.151458, 45.151458] + @test ys ≈ [-126.863475, -126.863475] + @test zs ≈ [0.0, 0.0] + end + end + end end - @testset "reproject vector, vector of vector, or tuple" begin - coord = [1120351.57, 741921.42] - @test AG.reproject(coord, GFT.EPSG(2927), nothing) ≈ [1120351.57, 741921.42] - @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326)) ≈ - [47.3488070138318, -122.5981499431438] - @test AG.reproject([coord], GFT.EPSG(2927), GFT.EPSG(4326)) ≈ - [[47.3488070138318, -122.5981499431438]] - coord = (1120351.57, 741921.42) - @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326); order=:compliant) ≈ - [47.3488070138318, -122.5981499431438] - @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326); order=:trad) ≈ - [-122.5981499431438, 47.3488070138318] - @test AG.reproject([coord], GFT.EPSG(2927), convert(GFT.WellKnownText, GFT.EPSG(4326)); order=:compliant) ≈ - [[47.3488070138318, -122.5981499431438]] - @test AG.reproject([coord], GFT.EPSG(2927), convert(GFT.WellKnownText, GFT.EPSG(4326)); order=:trad) ≈ - [[-122.5981499431438, 47.3488070138318]] - # :compliant doesn't work on PROJ axis order, it loses authority information - @test AG.reproject([coord], GFT.EPSG(2927), convert(GFT.ProjString, GFT.EPSG(4326)); order=:compliant) ≈ - [[-122.5981499431438, 47.3488070138318]] - @test AG.reproject([coord], GFT.EPSG(2927), convert(GFT.ProjString, GFT.EPSG(4326)); order=:trad) ≈ - [[-122.5981499431438, 47.3488070138318]] + + @testset "Use reproject" begin + @testset "reciprocal reprojection of wkt" begin + wktpoint = GFT.WellKnownText(GFT.Geom(), "POINT (1120351.57 741921.42)") + result = GFT.WellKnownText( + GFT.Geom(), + "POINT (47.3488070138318 -122.598149943144)", + ) + @test AG.reproject(wktpoint, GFT.EPSG(2927), GFT.EPSG(4326)) == result + @test convert( + AG.Geometry, + AG.reproject(result, GFT.EPSG(4326), GFT.EPSG(2927)), + ) |> GeoInterface.coordinates ≈ [1.12035156999967e6, 741921.420000271] + end + @testset "reproject vector, vector of vector, or tuple" begin + coord = [1120351.57, 741921.42] + @test AG.reproject(coord, GFT.EPSG(2927), nothing) ≈ [1120351.57, 741921.42] + @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326)) ≈ + [47.3488070138318, -122.5981499431438] + @test AG.reproject([coord], GFT.EPSG(2927), GFT.EPSG(4326)) ≈ + [[47.3488070138318, -122.5981499431438]] + coord = (1120351.57, 741921.42) + @test AG.reproject( + coord, + GFT.EPSG(2927), + GFT.EPSG(4326); + order = :compliant, + ) ≈ [47.3488070138318, -122.5981499431438] + @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326); order = :trad) ≈ + [-122.5981499431438, 47.3488070138318] + @test AG.reproject( + [coord], + GFT.EPSG(2927), + convert(GFT.WellKnownText, GFT.EPSG(4326)); + order = :compliant, + ) ≈ [[47.3488070138318, -122.5981499431438]] + @test AG.reproject( + [coord], + GFT.EPSG(2927), + convert(GFT.WellKnownText, GFT.EPSG(4326)); + order = :trad, + ) ≈ [[-122.5981499431438, 47.3488070138318]] + # :compliant doesn't work on PROJ axis order, it loses authority information + @test AG.reproject( + [coord], + GFT.EPSG(2927), + convert(GFT.ProjString, GFT.EPSG(4326)); + order = :compliant, + ) ≈ [[-122.5981499431438, 47.3488070138318]] + @test AG.reproject( + [coord], + GFT.EPSG(2927), + convert(GFT.ProjString, GFT.EPSG(4326)); + order = :trad, + ) ≈ [[-122.5981499431438, 47.3488070138318]] + end end - end -end + end -@testset "Get Projection" begin - AG.read("ospy/data1/sites.shp") do dataset - layer = AG.getlayer(dataset, 0) - spatialref = AG.getspatialref(layer) - @test AG.toWKT(spatialref)[1:6] == "PROJCS" - @test AG.toWKT(spatialref, false)[1:6] == "PROJCS" - @test AG.toPROJ4(spatialref) == "+proj=utm +zone=12 +datum=WGS84 +units=m +no_defs" - @test AG.toXML(spatialref)[1:17] == " POINT - (index 0) FID => 0.0 - (index 1) pointname => a + layer = AG.getlayer(dataset, 0) + @test sprint(print, layer) == """ + Layer: point + Geometry 0 (): [wkbPoint], POINT (100 0), POINT (100.2785 0.0893), ... + Field 0 (FID): [OFTReal], 2.0, 3.0, 0.0, 3.0 + Field 1 (pointname): [OFTString], point-a, point-b, a, b + """ + @test sprint(print, AG.layerdefn(layer)) == """ + Geometry (index 0): (wkbPoint) + Field (index 0): FID (OFTReal) + Field (index 1): pointname (OFTString) """ - @test sprint(print, AG.getfielddefn(feature, 1)) == - "pointname (OFTString)" - @test sprint(print, AG.getgeomdefn(feature, 0)) == - " (wkbPoint)" + @test sprint(print, AG.getspatialref(layer)) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + + AG.getfeature(layer, 2) do feature + @test sprint(print, feature) == """ + Feature + (index 0) geom => POINT + (index 0) FID => 0.0 + (index 1) pointname => a + """ + @test sprint(print, AG.getfielddefn(feature, 1)) == "pointname (OFTString)" + @test sprint(print, AG.getgeomdefn(feature, 0)) == " (wkbPoint)" + end end - end - AG.read("gdalworkshop/world.tif") do dataset - @test sprint(print, dataset) == """ - GDAL Dataset (Driver: GTiff/GeoTIFF) - File(s): - gdalworkshop/world.tif + AG.read("gdalworkshop/world.tif") do dataset + @test sprint(print, dataset) == """ + GDAL Dataset (Driver: GTiff/GeoTIFF) + File(s): + gdalworkshop/world.tif - Dataset (width x height): 2048 x 1024 (pixels) - Number of raster bands: 3 - [GA_ReadOnly] Band 1 (Red): 2048 x 1024 (UInt8) - [GA_ReadOnly] Band 2 (Green): 2048 x 1024 (UInt8) - [GA_ReadOnly] Band 3 (Blue): 2048 x 1024 (UInt8) - """ + Dataset (width x height): 2048 x 1024 (pixels) + Number of raster bands: 3 + [GA_ReadOnly] Band 1 (Red): 2048 x 1024 (UInt8) + [GA_ReadOnly] Band 2 (Green): 2048 x 1024 (UInt8) + [GA_ReadOnly] Band 3 (Blue): 2048 x 1024 (UInt8) + """ - @test sprint(print, AG.getband(dataset, 1)) == """ - [GA_ReadOnly] Band 1 (Red): 2048 x 1024 (UInt8) - blocksize: 256×256, nodata: nothing, units: 1.0px + 0.0 - overviews: (0) 1024x512 (1) 512x256 (2) 256x128 - (3) 128x64 (4) 64x32 (5) 32x16 - (6) 16x8 """ + @test sprint(print, AG.getband(dataset, 1)) == """ + [GA_ReadOnly] Band 1 (Red): 2048 x 1024 (UInt8) + blocksize: 256×256, nodata: nothing, units: 1.0px + 0.0 + overviews: (0) 1024x512 (1) 512x256 (2) 256x128 + (3) 128x64 (4) 64x32 (5) 32x16 + (6) 16x8 """ + end end -end -# untested -# Geometry with length(toWKT(geom)) > 60 # should be able to see ... -# Dataset with nlayer(dataset) > 5 + # untested + # Geometry with length(toWKT(geom)) > 60 # should be able to see ... + # Dataset with nlayer(dataset) > 5 end diff --git a/test/test_drivers.jl b/test/test_drivers.jl index fc65c91d..20b312f7 100644 --- a/test/test_drivers.jl +++ b/test/test_drivers.jl @@ -1,97 +1,110 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_drivers.jl" begin -@testset "Testing ConfigOptions" begin - @test AG.getconfigoption("GDAL_CACHEMAX") == "" - AG.setconfigoption("GDAL_CACHEMAX", "64") - @test AG.getconfigoption("GDAL_CACHEMAX") == "64" - AG.clearconfigoption("GDAL_CACHEMAX") - @test AG.getconfigoption("GDAL_CACHEMAX", "128") == "128" - - @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "" - AG.setthreadconfigoption("GDAL_CACHEMAX","32") - @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "32" - AG.clearthreadconfigoption("GDAL_CACHEMAX") - @test AG.getthreadconfigoption("GDAL_CACHEMAX", "128") == "128" - - @test AG.getconfigoption("GDAL_CACHEMAX") == "" - @test AG.getconfigoption("CPL_LOG_ERRORS") == "" - @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "" - @test AG.getthreadconfigoption("CPL_LOG_ERRORS") == "" + @testset "Testing ConfigOptions" begin + @test AG.getconfigoption("GDAL_CACHEMAX") == "" + AG.setconfigoption("GDAL_CACHEMAX", "64") + @test AG.getconfigoption("GDAL_CACHEMAX") == "64" + AG.clearconfigoption("GDAL_CACHEMAX") + @test AG.getconfigoption("GDAL_CACHEMAX", "128") == "128" - AG.environment(globalconfig=[("GDAL_CACHEMAX","64"), - ("CPL_LOG_ERRORS","ON")], - threadconfig=[("GDAL_CACHEMAX","32"), - ("CPL_LOG_ERRORS","OFF")]) do - # it seems that thread settings overwrites global settings? - @test AG.getconfigoption("GDAL_CACHEMAX") == "32" - @test AG.getconfigoption("CPL_LOG_ERRORS") == "OFF" + @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "" + AG.setthreadconfigoption("GDAL_CACHEMAX", "32") @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "32" - @test AG.getthreadconfigoption("CPL_LOG_ERRORS") == "OFF" - end + AG.clearthreadconfigoption("GDAL_CACHEMAX") + @test AG.getthreadconfigoption("GDAL_CACHEMAX", "128") == "128" - AG.environment(globalconfig=[("GDAL_CACHEMAX","64"), - ("CPL_LOG_ERRORS","ON")]) do - # everything normal here - @test AG.getconfigoption("GDAL_CACHEMAX") == "64" - @test AG.getconfigoption("CPL_LOG_ERRORS") == "ON" + @test AG.getconfigoption("GDAL_CACHEMAX") == "" + @test AG.getconfigoption("CPL_LOG_ERRORS") == "" @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "" @test AG.getthreadconfigoption("CPL_LOG_ERRORS") == "" + + AG.environment( + globalconfig = [("GDAL_CACHEMAX", "64"), ("CPL_LOG_ERRORS", "ON")], + threadconfig = [("GDAL_CACHEMAX", "32"), ("CPL_LOG_ERRORS", "OFF")], + ) do + # it seems that thread settings overwrites global settings? + @test AG.getconfigoption("GDAL_CACHEMAX") == "32" + @test AG.getconfigoption("CPL_LOG_ERRORS") == "OFF" + @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "32" + @test AG.getthreadconfigoption("CPL_LOG_ERRORS") == "OFF" + end + + AG.environment( + globalconfig = [("GDAL_CACHEMAX", "64"), ("CPL_LOG_ERRORS", "ON")], + ) do + # everything normal here + @test AG.getconfigoption("GDAL_CACHEMAX") == "64" + @test AG.getconfigoption("CPL_LOG_ERRORS") == "ON" + @test AG.getthreadconfigoption("GDAL_CACHEMAX") == "" + @test AG.getthreadconfigoption("CPL_LOG_ERRORS") == "" + end end -end -@testset "Test Driver Capabilities" begin - drivers = AG.listdrivers() - @test drivers["GTiff"] == "GeoTIFF" - @test length(AG.driveroptions("GTiff")) > 100 - @test sprint(print, AG.identifydriver("data/point.geojson")) == "Driver: GeoJSON/GeoJSON" - @test sprint(print, AG.identifydriver("data/utmsmall.tif")) == "Driver: GTiff/GeoTIFF" + @testset "Test Driver Capabilities" begin + drivers = AG.listdrivers() + @test drivers["GTiff"] == "GeoTIFF" + @test length(AG.driveroptions("GTiff")) > 100 + @test sprint(print, AG.identifydriver("data/point.geojson")) == + "Driver: GeoJSON/GeoJSON" + @test sprint(print, AG.identifydriver("data/utmsmall.tif")) == + "Driver: GTiff/GeoTIFF" - driver = AG.getdriver("GTiff") - @test isnothing(AG.deregister(driver)) - @test isnothing(AG.register(driver)) - @test AG.validate(driver, ["COMPRESS=LZW", "INTERLEAVE=PIXEL"]) == true - @test AG.validate(driver, ["COMPRESS=LZW"]) == true - @test AG.validate(driver, ["INTERLEAVE=PIXEL"]) == true + driver = AG.getdriver("GTiff") + @test isnothing(AG.deregister(driver)) + @test isnothing(AG.register(driver)) + @test AG.validate(driver, ["COMPRESS=LZW", "INTERLEAVE=PIXEL"]) == true + @test AG.validate(driver, ["COMPRESS=LZW"]) == true + @test AG.validate(driver, ["INTERLEAVE=PIXEL"]) == true - AG.read("data/point.geojson") do dataset - @test AG.listcapability(dataset) == Dict( - "CreateLayer"=>false, - "DeleteLayer"=>false, - "CreateGeomFieldAfterCreateLayer"=>false, - "CurveGeometries"=>false, - "Transactions"=>false, - "EmulatedTransactions"=>false - ) - @test AG.listcapability(AG.getlayer(dataset,0)) == Dict( - "SequentialWrite"=>false, "DeleteField"=>false, - "IgnoreFields"=>false, "FastSpatialFilter"=>false, - "DeleteFeature"=>false, "FastFeatureCount"=>true, - "StringsAsUTF8"=>true, "CreateGeomField"=>false, - "ReorderFields"=>false, "MeasuredGeometries"=>true, - "FastSetNextByIndex"=>true, "CreateField"=>false, - "RandomWrite"=>false, "RandomRead"=>true, - "CurveGeometries"=>false, "FastGetExtent"=>false, - "Transactions"=>false, "AlterFieldDefn"=>false - ) + AG.read("data/point.geojson") do dataset + @test AG.listcapability(dataset) == Dict( + "CreateLayer" => false, + "DeleteLayer" => false, + "CreateGeomFieldAfterCreateLayer" => false, + "CurveGeometries" => false, + "Transactions" => false, + "EmulatedTransactions" => false, + ) + @test AG.listcapability(AG.getlayer(dataset, 0)) == Dict( + "SequentialWrite" => false, + "DeleteField" => false, + "IgnoreFields" => false, + "FastSpatialFilter" => false, + "DeleteFeature" => false, + "FastFeatureCount" => true, + "StringsAsUTF8" => true, + "CreateGeomField" => false, + "ReorderFields" => false, + "MeasuredGeometries" => true, + "FastSetNextByIndex" => true, + "CreateField" => false, + "RandomWrite" => false, + "RandomRead" => true, + "CurveGeometries" => false, + "FastGetExtent" => false, + "Transactions" => false, + "AlterFieldDefn" => false, + ) + end end -end -@testset "Test extensions list" begin - exts = AG.extensions() - @test exts[".tif"] == "GTiff" - @test exts[".grb"] == "GRIB" - @test exts[".geojson"] == "GeoJSON" -end + @testset "Test extensions list" begin + exts = AG.extensions() + @test exts[".tif"] == "GTiff" + @test exts[".grb"] == "GRIB" + @test exts[".geojson"] == "GeoJSON" + end -@testset "Test getting extensiondriver" begin - @test AG.extensiondriver("filename.tif") == "GTiff" - @test AG.extensiondriver(".tif") == "GTiff" - @test AG.extensiondriver("filename.asc") == "AAIGrid" - @test AG.extensiondriver(".asc") == "AAIGrid" - @test_throws ArgumentError AG.extensiondriver(".not_an_extension") -end + @testset "Test getting extensiondriver" begin + @test AG.extensiondriver("filename.tif") == "GTiff" + @test AG.extensiondriver(".tif") == "GTiff" + @test AG.extensiondriver("filename.asc") == "AAIGrid" + @test AG.extensiondriver(".asc") == "AAIGrid" + @test_throws ArgumentError AG.extensiondriver(".not_an_extension") + end end diff --git a/test/test_feature.jl b/test/test_feature.jl index 8872661b..6dffe1f3 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -1,188 +1,192 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_feature.jl" begin -AG.read("data/point.geojson") do dataset - layer = AG.getlayer(dataset, 0) - AG.getfeature(layer, 0) do f1 - AG.getfeature(layer, 2) do f2 - @test sprint(print, f1) == """ - Feature - (index 0) geom => POINT - (index 0) FID => 2.0 - (index 1) pointname => point-a - """ - AG.getgeom(f1) do g1 - @test sprint(print, g1) == "Geometry: POINT (100 0)" - end - fid1 = AG.getfid(f1) - @test fid1 == 0 + AG.read("data/point.geojson") do dataset + layer = AG.getlayer(dataset, 0) + AG.getfeature(layer, 0) do f1 + AG.getfeature(layer, 2) do f2 + @test sprint(print, f1) == """ + Feature + (index 0) geom => POINT + (index 0) FID => 2.0 + (index 1) pointname => point-a + """ + AG.getgeom(f1) do g1 + @test sprint(print, g1) == "Geometry: POINT (100 0)" + end + fid1 = AG.getfid(f1) + @test fid1 == 0 - AG.getgeom(f2, "fake name") do g - @test sprint(print, g) == "NULL Geometry" - end + AG.getgeom(f2, "fake name") do g + @test sprint(print, g) == "NULL Geometry" + end - @test sprint(print, f2) == """ - Feature - (index 0) geom => POINT - (index 0) FID => 0.0 - (index 1) pointname => a - """ - AG.getgeom(f2, "") do g2 - @test sprint(print, g2) == "Geometry: POINT (100 0)" - end - fid2 = AG.getfid(f2) - @test fid2 == 2 + @test sprint(print, f2) == """ + Feature + (index 0) geom => POINT + (index 0) FID => 0.0 + (index 1) pointname => a + """ + AG.getgeom(f2, "") do g2 + @test sprint(print, g2) == "Geometry: POINT (100 0)" + end + fid2 = AG.getfid(f2) + @test fid2 == 2 - AG.clone(f1) do f3 - @test AG.equals(AG.getgeom(f1), AG.getgeom(f3)) == true + AG.clone(f1) do f3 + @test AG.equals(AG.getgeom(f1), AG.getgeom(f3)) == true + end + AG.setfid!(f1, fid2) + AG.setfid!(f2, fid1) + @test AG.getfid(f1) == 2 + @test AG.getfid(f2) == 0 + + @test AG.findgeomindex(f1, "geom") == -1 + @test AG.findgeomindex(f1, "") == 0 + @test AG.findgeomindex(f2, "geom") == -1 + @test AG.findgeomindex(f2, "") == 0 + @test AG.gettype(AG.getgeomdefn(f1, 0)) == AG.wkbPoint + @test AG.gettype(AG.getgeomdefn(f2, 0)) == AG.wkbPoint end - AG.setfid!(f1, fid2); AG.setfid!(f2, fid1) - @test AG.getfid(f1) == 2 - @test AG.getfid(f2) == 0 - - @test AG.findgeomindex(f1, "geom") == -1 - @test AG.findgeomindex(f1, "") == 0 - @test AG.findgeomindex(f2, "geom") == -1 - @test AG.findgeomindex(f2, "") == 0 - @test AG.gettype(AG.getgeomdefn(f1, 0)) == AG.wkbPoint - @test AG.gettype(AG.getgeomdefn(f2, 0)) == AG.wkbPoint - end - end - - AG.getfeature(layer, 0) do f - @test AG.toWKT(AG.getgeom(f,0)) == "POINT (100 0)" - AG.setgeom!(f, 0, AG.createpoint(0,100)) - @test AG.toWKT(AG.getgeom(f,0)) == "POINT (0 100)" - AG.createpolygon([(0.,100.),(100.,0.)]) do poly - AG.setgeom!(f, 0, poly) end - @test AG.toWKT(AG.getgeom(f,0)) == "POLYGON ((0 100,100 0))" - AG.setstylestring!(f, "@Name") - @test AG.getstylestring(f) == "@Name" - AG.setstylestring!(f, "NewName") - @test AG.getstylestring(f) == "NewName" + AG.getfeature(layer, 0) do f + @test AG.toWKT(AG.getgeom(f, 0)) == "POINT (100 0)" + AG.setgeom!(f, 0, AG.createpoint(0, 100)) + @test AG.toWKT(AG.getgeom(f, 0)) == "POINT (0 100)" + AG.createpolygon([(0.0, 100.0), (100.0, 0.0)]) do poly + AG.setgeom!(f, 0, poly) + end + @test AG.toWKT(AG.getgeom(f, 0)) == "POLYGON ((0 100,100 0))" - AG.createstyletable() do st - AG.addstyle!(st, "name", "style") - AG.setstyletable!(f, st) - @test AG.findstylestring(AG.getstyletable(f), "name") == "style" - end + AG.setstylestring!(f, "@Name") + @test AG.getstylestring(f) == "@Name" + AG.setstylestring!(f, "NewName") + @test AG.getstylestring(f) == "NewName" - AG.setnativedata!(f, "nativedata1") - @test AG.getnativedata(f) == "nativedata1" - AG.setnativedata!(f, "nativedata2") - @test AG.getnativedata(f) == "nativedata2" - - AG.setmediatype!(f, "mediatype1") - @test AG.getmediatype(f) == "mediatype1" - AG.setmediatype!(f, "mediatype2") - @test AG.getmediatype(f) == "mediatype2" - - @test AG.validate(f, AG.F_VAL_NULL, false) == true - @test AG.validate(f, AG.F_VAL_GEOM_TYPE, false) == false - @test AG.validate(f, AG.F_VAL_WIDTH, false) == true - @test AG.validate(f, AG.F_VAL_ALLOW_NULL_WHEN_DEFAULT, false) == true - @test AG.validate(f, AG.F_VAL_ALLOW_DIFFERENT_GEOM_DIM, false) == true - - @test AG.getfield(f, 1) == "point-a" - @test AG.getdefault(f, 1) == "" - AG.setdefault!(AG.getfielddefn(f, 1), "default value") - @test AG.getdefault(f, 1) == "default value" - @test AG.getfield(f, 1) == "point-a" - AG.unsetfield!(f, 1) - @test AG.getfield(f, 1) == "default value" - AG.fillunsetwithdefault!(f, notnull = false) - @test AG.getfield(f, 1) == AG.getdefault(f, 1) - end -end + AG.createstyletable() do st + AG.addstyle!(st, "name", "style") + AG.setstyletable!(f, st) + @test AG.findstylestring(AG.getstyletable(f), "name") == "style" + end -@testset "In-Memory Driver" begin - AG.create(AG.getdriver("MEMORY")) do output - layer = AG.createlayer(dataset = output, geom = AG.wkbPolygon) - AG.createfielddefn("int64field", AG.OFTInteger64) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfielddefn("doublefield", AG.OFTReal) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfielddefn("intlistfield", AG.OFTIntegerList) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfielddefn("int64listfield", AG.OFTInteger64List) do fielddefn - AG.addfielddefn!(layer, fielddefn) + AG.setnativedata!(f, "nativedata1") + @test AG.getnativedata(f) == "nativedata1" + AG.setnativedata!(f, "nativedata2") + @test AG.getnativedata(f) == "nativedata2" + + AG.setmediatype!(f, "mediatype1") + @test AG.getmediatype(f) == "mediatype1" + AG.setmediatype!(f, "mediatype2") + @test AG.getmediatype(f) == "mediatype2" + + @test AG.validate(f, AG.F_VAL_NULL, false) == true + @test AG.validate(f, AG.F_VAL_GEOM_TYPE, false) == false + @test AG.validate(f, AG.F_VAL_WIDTH, false) == true + @test AG.validate(f, AG.F_VAL_ALLOW_NULL_WHEN_DEFAULT, false) == true + @test AG.validate(f, AG.F_VAL_ALLOW_DIFFERENT_GEOM_DIM, false) == true + + @test AG.getfield(f, 1) == "point-a" + @test AG.getdefault(f, 1) == "" + AG.setdefault!(AG.getfielddefn(f, 1), "default value") + @test AG.getdefault(f, 1) == "default value" + @test AG.getfield(f, 1) == "point-a" + AG.unsetfield!(f, 1) + @test AG.getfield(f, 1) == "default value" + AG.fillunsetwithdefault!(f, notnull = false) + @test AG.getfield(f, 1) == AG.getdefault(f, 1) end - AG.createfielddefn("doublelistfield", AG.OFTRealList) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfielddefn("stringlistfield", AG.OFTStringList) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfielddefn("binaryfield", AG.OFTBinary) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfielddefn("datetimefield", AG.OFTDateTime) do fielddefn - AG.addfielddefn!(layer, fielddefn) - end - AG.createfeature(layer) do feature - AG.setfield!(feature, 0, 1) - AG.setfield!(feature, 1, 1.0) - AG.setfield!(feature, 2, Int32[1, 2]) - AG.setfield!(feature, 3, Int64[1, 2]) - AG.setfield!(feature, 4, Float64[1.0, 2.0]) - AG.setfield!(feature, 5, ["1", "2.0"]) - AG.setfield!(feature, 6, UInt8[1,2,3,4]) - AG.setfield!(feature, 7, Dates.DateTime(2016,9,25,21,17,0)) - @test sprint(print, AG.getgeom(feature)) == "NULL Geometry" - AG.getgeom(feature) do geom - @test sprint(print, geom) == "NULL Geometry" + end + + @testset "In-Memory Driver" begin + AG.create(AG.getdriver("MEMORY")) do output + layer = AG.createlayer(dataset = output, geom = AG.wkbPolygon) + AG.createfielddefn("int64field", AG.OFTInteger64) do fielddefn + AG.addfielddefn!(layer, fielddefn) end - @test sprint(print, AG.getgeom(feature, 0)) == "NULL Geometry" - AG.getgeom(feature, 0) do geom - @test sprint(print, geom) == "NULL Geometry" + AG.createfielddefn("doublefield", AG.OFTReal) do fielddefn + AG.addfielddefn!(layer, fielddefn) end + AG.createfielddefn("intlistfield", AG.OFTIntegerList) do fielddefn + AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("int64listfield", AG.OFTInteger64List) do fielddefn + AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("doublelistfield", AG.OFTRealList) do fielddefn + AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("stringlistfield", AG.OFTStringList) do fielddefn + AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("binaryfield", AG.OFTBinary) do fielddefn + AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("datetimefield", AG.OFTDateTime) do fielddefn + AG.addfielddefn!(layer, fielddefn) + end + AG.createfeature(layer) do feature + AG.setfield!(feature, 0, 1) + AG.setfield!(feature, 1, 1.0) + AG.setfield!(feature, 2, Int32[1, 2]) + AG.setfield!(feature, 3, Int64[1, 2]) + AG.setfield!(feature, 4, Float64[1.0, 2.0]) + AG.setfield!(feature, 5, ["1", "2.0"]) + AG.setfield!(feature, 6, UInt8[1, 2, 3, 4]) + AG.setfield!(feature, 7, Dates.DateTime(2016, 9, 25, 21, 17, 0)) + @test sprint(print, AG.getgeom(feature)) == "NULL Geometry" + AG.getgeom(feature) do geom + @test sprint(print, geom) == "NULL Geometry" + end + @test sprint(print, AG.getgeom(feature, 0)) == "NULL Geometry" + AG.getgeom(feature, 0) do geom + @test sprint(print, geom) == "NULL Geometry" + end - AG.addfeature(layer) do newfeature - AG.setfrom!(newfeature, feature) - @test AG.getfield(newfeature, 0) == 1 - @test AG.getfield(newfeature, 1) ≈ 1.0 - @test AG.getfield(newfeature, 2) == Int32[1, 2] - @test AG.getfield(newfeature, 3) == Int64[1, 2] - @test AG.getfield(newfeature, 4) ≈ Float64[1.0, 2.0] - @test AG.getfield(newfeature, 5) == String["1", "2.0"] - @test AG.getfield(newfeature, 6) == UInt8[1,2,3,4] - @test AG.getfield(newfeature, 7) == Dates.DateTime(2016,9,25,21,17,0) - - AG.createfeature(layer) do lastfeature - AG.setfrom!(lastfeature, feature) - AG.setfield!(lastfeature, 0, 45) - AG.setfield!(lastfeature, 1, 18.2) - AG.setfield!(lastfeature, 5, ["foo", "bar"]) - @test AG.getfield(lastfeature, 0) == 45 - @test AG.getfield(lastfeature, 1) ≈ 18.2 - @test AG.getfield(lastfeature, 2) == Int32[1, 2] - @test AG.getfield(lastfeature, 3) == Int64[1, 2] - @test AG.getfield(lastfeature, 4) ≈ Float64[1.0, 2.0] - @test AG.getfield(lastfeature, 5) == String["foo", "bar"] - @test AG.getfield(lastfeature, 6) == UInt8[1,2,3,4] - @test AG.getfield(lastfeature, 7) == Dates.DateTime(2016,9,25,21,17,0) - + AG.addfeature(layer) do newfeature + AG.setfrom!(newfeature, feature) @test AG.getfield(newfeature, 0) == 1 - @test AG.getfield(newfeature, 1) ≈ 1.0 + @test AG.getfield(newfeature, 1) ≈ 1.0 + @test AG.getfield(newfeature, 2) == Int32[1, 2] + @test AG.getfield(newfeature, 3) == Int64[1, 2] + @test AG.getfield(newfeature, 4) ≈ Float64[1.0, 2.0] @test AG.getfield(newfeature, 5) == String["1", "2.0"] - AG.setfrom!(newfeature, lastfeature, collect(Cint, 0:7)) - @test AG.getfield(newfeature, 0) == 45 - @test AG.getfield(newfeature, 1) ≈ 18.2 - @test AG.getfield(newfeature, 5) == String["foo", "bar"] + @test AG.getfield(newfeature, 6) == UInt8[1, 2, 3, 4] + @test AG.getfield(newfeature, 7) == + Dates.DateTime(2016, 9, 25, 21, 17, 0) + + AG.createfeature(layer) do lastfeature + AG.setfrom!(lastfeature, feature) + AG.setfield!(lastfeature, 0, 45) + AG.setfield!(lastfeature, 1, 18.2) + AG.setfield!(lastfeature, 5, ["foo", "bar"]) + @test AG.getfield(lastfeature, 0) == 45 + @test AG.getfield(lastfeature, 1) ≈ 18.2 + @test AG.getfield(lastfeature, 2) == Int32[1, 2] + @test AG.getfield(lastfeature, 3) == Int64[1, 2] + @test AG.getfield(lastfeature, 4) ≈ Float64[1.0, 2.0] + @test AG.getfield(lastfeature, 5) == String["foo", "bar"] + @test AG.getfield(lastfeature, 6) == UInt8[1, 2, 3, 4] + @test AG.getfield(lastfeature, 7) == + Dates.DateTime(2016, 9, 25, 21, 17, 0) + + @test AG.getfield(newfeature, 0) == 1 + @test AG.getfield(newfeature, 1) ≈ 1.0 + @test AG.getfield(newfeature, 5) == String["1", "2.0"] + AG.setfrom!(newfeature, lastfeature, collect(Cint, 0:7)) + @test AG.getfield(newfeature, 0) == 45 + @test AG.getfield(newfeature, 1) ≈ 18.2 + @test AG.getfield(newfeature, 5) == String["foo", "bar"] + end + @test AG.nfeature(layer) == 1 end - @test AG.nfeature(layer) == 1 + @test AG.nfeature(layer) == 2 end - @test AG.nfeature(layer) == 2 + @test AG.nfeature(layer) == 3 end - @test AG.nfeature(layer) == 3 end -end end diff --git a/test/test_featurelayer.jl b/test/test_featurelayer.jl index 593c4d3b..3bd8d548 100644 --- a/test/test_featurelayer.jl +++ b/test/test_featurelayer.jl @@ -1,45 +1,47 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_featurelayer.jl" begin -@testset "Testing FeatureLayer Methods" begin - AG.read("data/point.geojson") do dataset - AG.copy(dataset) do tmpcopy - @test AG.nlayer(tmpcopy) == 1 - tmplayer = AG.getlayer(tmpcopy,0) - @test sprint(print, AG.getspatialref(tmplayer)) == "NULL Spatial Reference System" - AG.getspatialref(tmplayer) do spref - @test sprint(print, spref) == "NULL Spatial Reference System" + @testset "Testing FeatureLayer Methods" begin + AG.read("data/point.geojson") do dataset + AG.copy(dataset) do tmpcopy + @test AG.nlayer(tmpcopy) == 1 + tmplayer = AG.getlayer(tmpcopy, 0) + @test sprint(print, AG.getspatialref(tmplayer)) == + "NULL Spatial Reference System" + AG.getspatialref(tmplayer) do spref + @test sprint(print, spref) == "NULL Spatial Reference System" + end + @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer), 0)) == false + AG.setignoredfields!(tmplayer, ["OGR_GEOMETRY"]) + @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer), 0)) == true end - @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer),0)) == false - AG.setignoredfields!(tmplayer, ["OGR_GEOMETRY"]) - @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer),0)) == true - end - AG.copy(dataset, driver = AG.getdriver("Memory")) do tmpcopy - tmplayer = AG.getlayer(dataset, 0) - AG.copy(tmplayer) do copylayer - @test AG.nfeature(tmplayer) == AG.nfeature(copylayer) - end - @test sprint(print, AG.getspatialref(tmplayer)) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" - AG.getspatialref(tmplayer) do spref - @test sprint(print, spref) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" - end - newlayer = AG.createlayer( - name = "new layer", - dataset = tmpcopy, - spatialref = AG.getspatialref(tmplayer), - geom = AG.wkbPoint - ) + AG.copy(dataset, driver = AG.getdriver("Memory")) do tmpcopy + tmplayer = AG.getlayer(dataset, 0) + AG.copy(tmplayer) do copylayer + @test AG.nfeature(tmplayer) == AG.nfeature(copylayer) + end + @test sprint(print, AG.getspatialref(tmplayer)) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + AG.getspatialref(tmplayer) do spref + @test sprint(print, spref) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + end + newlayer = AG.createlayer( + name = "new layer", + dataset = tmpcopy, + spatialref = AG.getspatialref(tmplayer), + geom = AG.wkbPoint, + ) @test AG.ngeom(AG.layerdefn(newlayer)) == 1 @test sprint(print, newlayer) == """ Layer: new layer Geometry 0 (): [wkbPoint] """ - AG.writegeomdefn(newlayer, - "new geom", - AG.wkbLineString) do gfd + AG.writegeomdefn(newlayer, "new geom", AG.wkbLineString) do gfd @test AG.getname(gfd) == "new geom" @test AG.gettype(gfd) == AG.wkbLineString end @@ -79,12 +81,19 @@ import ArchGDAL; const AG = ArchGDAL AG.addfeature(newlayer) do newfeature AG.setgeom!(newfeature, 0, AG.createpoint()) AG.setgeom!(newfeature, 1, AG.createlinestring()) - AG.setgeom!(newfeature, 2, AG.createpolygon([[[0.,0.], [1.,1.], [0.,1.]]])) + AG.setgeom!( + newfeature, + 2, + AG.createpolygon([[[0.0, 0.0], [1.0, 1.0], [0.0, 1.0]]]), + ) @test sprint(print, AG.getgeom(newfeature)) == "Geometry: POINT EMPTY" - @test sprint(print, AG.getgeom(newfeature, 0)) == "Geometry: POINT EMPTY" - @test sprint(print, AG.getgeom(newfeature, 1)) == "Geometry: LINESTRING EMPTY" - @test sprint(print, AG.getgeom(newfeature, 2)) == "Geometry: POLYGON ((0 0,1 1,0 1))" + @test sprint(print, AG.getgeom(newfeature, 0)) == + "Geometry: POINT EMPTY" + @test sprint(print, AG.getgeom(newfeature, 1)) == + "Geometry: LINESTRING EMPTY" + @test sprint(print, AG.getgeom(newfeature, 2)) == + "Geometry: POLYGON ((0 0,1 1,0 1))" AG.getgeom(newfeature) do g @test sprint(print, g) == "Geometry: POINT EMPTY" end @@ -95,92 +104,125 @@ import ArchGDAL; const AG = ArchGDAL @test sprint(print, g) == "Geometry: POLYGON ((0 0,1 1,0 1))" end end - end + end + + layer = AG.getlayer(dataset, 0) + @test sprint(print, AG.getspatialref(layer)) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + @test AG.fidcolumnname(layer) == "" + @test AG.geomcolumnname(layer) == "" + @test AG.nreference(layer) == 0 + AG.reference(layer) + @test AG.nreference(layer) == 1 + AG.dereference(layer) + @test AG.nreference(layer) == 0 - layer = AG.getlayer(dataset, 0) - @test sprint(print, AG.getspatialref(layer)) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" - @test AG.fidcolumnname(layer) == "" - @test AG.geomcolumnname(layer) == "" - @test AG.nreference(layer) == 0 - AG.reference(layer) - @test AG.nreference(layer) == 1 - AG.dereference(layer) - @test AG.nreference(layer) == 0 - - @test AG.nfeature(layer) == 4 - @test AG.getfield.(layer, 1) == ["point-a", "point-b", "a", "b"] - AG.setspatialfilter!(layer,100,-1,100.1,1) - @test AG.toWKT(AG.getspatialfilter(layer)) == "POLYGON ((100 -1,100 1,100.1 1.0,100.1 -1,100 -1))" - @test AG.nfeature(layer) == -1 - @test AG.getfield.(layer, 1) == ["point-a", "a"] - AG.clearspatialfilter!(layer) - - @test AG.nfeature(layer) == 4 - @test AG.getfield.(layer, 1) == ["point-a", "point-b", "a", "b"] - @test AG.findgeomindex(AG.layerdefn(layer)) == 0 - AG.setspatialfilter!(layer,0,100,-1,100.1,1) - @test AG.toWKT(AG.getspatialfilter(layer)) == "POLYGON ((100 -1,100 1,100.1 1.0,100.1 -1,100 -1))" - @test AG.nfeature(layer) == -1 - @test AG.getfield.(layer, 1) == ["point-a", "a"] - - AG.clone(AG.getspatialfilter(layer)) do poly - n = 0; for feature in layer; n += 1 end; @test n == 2 + @test AG.nfeature(layer) == 4 + @test AG.getfield.(layer, 1) == ["point-a", "point-b", "a", "b"] + AG.setspatialfilter!(layer, 100, -1, 100.1, 1) + @test AG.toWKT(AG.getspatialfilter(layer)) == + "POLYGON ((100 -1,100 1,100.1 1.0,100.1 -1,100 -1))" + @test AG.nfeature(layer) == -1 + @test AG.getfield.(layer, 1) == ["point-a", "a"] AG.clearspatialfilter!(layer) - @test sprint(print, AG.getspatialfilter(layer)) == "NULL Geometry" - n = 0; for feature in layer; n += 1 end; @test n == 4 - - @testset "Test with setting to index of geomfield" begin - AG.setspatialfilter!(layer, 0, poly) - n = 0; for feature in layer; n += 1 end; @test n == 2 - AG.clearspatialfilter!(layer, 0) - n = 0; for feature in layer; n += 1 end; @test n == 4 - - AG.setattributefilter!(layer, "FID = 2") - n = 0; for feature in layer; n += 1 end; @test n == 1 - AG.setattributefilter!(layer, "FID = 3") - n = 0; for feature in layer; n += 1 end; @test n == 2 - AG.clearattributefilter!(layer) - n = 0; for feature in layer; n += 1 end; @test n == 4 - AG.nextfeature(layer) do feature - @test AG.getfield(feature, 1) == "point-a" + + @test AG.nfeature(layer) == 4 + @test AG.getfield.(layer, 1) == ["point-a", "point-b", "a", "b"] + @test AG.findgeomindex(AG.layerdefn(layer)) == 0 + AG.setspatialfilter!(layer, 0, 100, -1, 100.1, 1) + @test AG.toWKT(AG.getspatialfilter(layer)) == + "POLYGON ((100 -1,100 1,100.1 1.0,100.1 -1,100 -1))" + @test AG.nfeature(layer) == -1 + @test AG.getfield.(layer, 1) == ["point-a", "a"] + + AG.clone(AG.getspatialfilter(layer)) do poly + n = 0 + for feature in layer + n += 1 end - AG.setnextbyindex!(layer, 2) - AG.nextfeature(layer) do feature - @test AG.getfield(feature, 1) == "a" + @test n == 2 + AG.clearspatialfilter!(layer) + @test sprint(print, AG.getspatialfilter(layer)) == "NULL Geometry" + n = 0 + for feature in layer + n += 1 + end + @test n == 4 + + @testset "Test with setting to index of geomfield" begin + AG.setspatialfilter!(layer, 0, poly) + n = 0 + for feature in layer + n += 1 + end + @test n == 2 + AG.clearspatialfilter!(layer, 0) + n = 0 + for feature in layer + n += 1 + end + @test n == 4 + + AG.setattributefilter!(layer, "FID = 2") + n = 0 + for feature in layer + n += 1 + end + @test n == 1 + AG.setattributefilter!(layer, "FID = 3") + n = 0 + for feature in layer + n += 1 + end + @test n == 2 + AG.clearattributefilter!(layer) + n = 0 + for feature in layer + n += 1 + end + @test n == 4 + AG.nextfeature(layer) do feature + @test AG.getfield(feature, 1) == "point-a" + end + AG.setnextbyindex!(layer, 2) + AG.nextfeature(layer) do feature + @test AG.getfield(feature, 1) == "a" + end + @test AG.testcapability(layer, "OLCRandomWrite") == false end - @test AG.testcapability(layer,"OLCRandomWrite") == false end + @test AG.findfieldindex(layer, "FID", true) == 0 + @test AG.findfieldindex(layer, :FID, false) == 0 + @test AG.findfieldindex(layer, "pointname", true) == 1 + @test AG.findfieldindex(layer, "pointname", false) == 1 + @test AG.findfieldindex(layer, "geom", true) == -1 + @test AG.findfieldindex(layer, "geom", true) == -1 + @test AG.findfieldindex(layer, "rubbish", true) == -1 + @test AG.findfieldindex(layer, "rubbish", false) == -1 + @test sprint(print, AG.envelope(layer, 0, true)) == + "GDAL.OGREnvelope(100.0, 100.2785, 0.0, 0.0893)" + @test sprint(print, AG.envelope(layer, true)) == + "GDAL.OGREnvelope(100.0, 100.2785, 0.0, 0.0893)" end - @test AG.findfieldindex(layer, "FID", true) == 0 - @test AG.findfieldindex(layer, :FID, false) == 0 - @test AG.findfieldindex(layer, "pointname", true) == 1 - @test AG.findfieldindex(layer, "pointname", false) == 1 - @test AG.findfieldindex(layer, "geom", true) == -1 - @test AG.findfieldindex(layer, "geom", true) == -1 - @test AG.findfieldindex(layer, "rubbish", true) == -1 - @test AG.findfieldindex(layer, "rubbish", false) == -1 - @test sprint(print, AG.envelope(layer, 0, true)) == "GDAL.OGREnvelope(100.0, 100.2785, 0.0, 0.0893)" - @test sprint(print, AG.envelope(layer, true)) == "GDAL.OGREnvelope(100.0, 100.2785, 0.0, 0.0893)" end -end -# Not implemented yet: + # Not implemented yet: -# intersection(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) -# union(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressdata = C_NULL, progressfunc::Function = GDAL.gdaldummyprogress) -# symdifference(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) -# identity(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) -# update(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) -# clip(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) -# erase(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) + # intersection(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) + # union(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressdata = C_NULL, progressfunc::Function = GDAL.gdaldummyprogress) + # symdifference(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) + # identity(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) + # update(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) + # clip(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) + # erase(input::FeatureLayer, method::FeatureLayer, result::FeatureLayer; options = StringList(C_NULL), progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL) -# deletefielddefn!(layer::FeatureLayer, i::Integer) -# reorderfielddefn!(layer::FeatureLayer, indices::Vector{Cint}) -# reorderfielddefn!(layer::FeatureLayer, oldpos::Integer, newpos::Integer) -# updatefielddefn!(layer::FeatureLayer, i::Integer, newfielddefn::FieldDefn, flags::UInt8) + # deletefielddefn!(layer::FeatureLayer, i::Integer) + # reorderfielddefn!(layer::FeatureLayer, indices::Vector{Cint}) + # reorderfielddefn!(layer::FeatureLayer, oldpos::Integer, newpos::Integer) + # updatefielddefn!(layer::FeatureLayer, i::Integer, newfielddefn::FieldDefn, flags::UInt8) -# starttransaction(layer) -# committransaction(layer) -# rollbacktransaction(layer) + # starttransaction(layer) + # committransaction(layer) + # rollbacktransaction(layer) end diff --git a/test/test_fielddefn.jl b/test/test_fielddefn.jl index 6a844367..db0a0820 100644 --- a/test/test_fielddefn.jl +++ b/test/test_fielddefn.jl @@ -1,175 +1,184 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_fielddefn.jl" begin -@testset "Tests for field defn" begin - AG.createfielddefn("fieldname", AG.OFTInteger) do fd - @test sprint(print, fd) == "fieldname (OFTInteger)" - @test AG.getname(fd) == "fieldname" - AG.setname!(fd, "newname") - @test AG.getname(fd) == "newname" - @test AG.gettype(fd) == AG.OFTInteger - AG.settype!(fd, AG.OFTDate) - @test AG.gettype(fd) == AG.OFTDate - AG.settype!(fd, AG.OFTInteger) - @test AG.getsubtype(fd) == AG.OFSTNone - AG.setsubtype!(fd, AG.OFSTInt16) - @test AG.getsubtype(fd) == AG.OFSTInt16 - AG.setsubtype!(fd, AG.OFSTBoolean) - @test AG.getsubtype(fd) == AG.OFSTBoolean - AG.setsubtype!(fd, AG.OFSTNone) - @test AG.getjustify(fd) == AG.OJUndefined - AG.setjustify!(fd, AG.OJLeft) - @test AG.getjustify(fd) == AG.OJLeft - @test AG.getwidth(fd) == 0 - AG.setwidth!(fd, 10) - @test AG.getwidth(fd) == 10 - @test AG.getprecision(fd) == 0 - AG.setprecision!(fd, 20) - @test AG.getprecision(fd) == 20 - AG.setparams!(fd, "finalname", AG.OFTDate, nwidth = 5, nprecision = 2, - justify = AG.OJRight) - @test AG.gettype(fd) == AG.OFTDate - @test AG.getname(fd) == "finalname" - @test AG.getsubtype(fd) == AG.OFSTNone - @test AG.getjustify(fd) == AG.OJRight - @test AG.getwidth(fd) == 5 - @test AG.getprecision(fd) == 2 - @test AG.isignored(fd) == false - AG.setignored!(fd, true) - @test AG.isignored(fd) == true - AG.setignored!(fd, false) - @test AG.isignored(fd) == false - - @test AG.isnullable(fd) == true - AG.setnullable!(fd, false) - @test AG.isnullable(fd) == false - AG.setnullable!(fd, true) - @test AG.isnullable(fd) == true - - @test AG.getdefault(fd) == "" - AG.setdefault!(fd, "0001/01/01 00:00:00") - @test AG.getdefault(fd) == "0001/01/01 00:00:00" - @test AG.isdefaultdriverspecific(fd) == true + @testset "Tests for field defn" begin + AG.createfielddefn("fieldname", AG.OFTInteger) do fd + @test sprint(print, fd) == "fieldname (OFTInteger)" + @test AG.getname(fd) == "fieldname" + AG.setname!(fd, "newname") + @test AG.getname(fd) == "newname" + @test AG.gettype(fd) == AG.OFTInteger + AG.settype!(fd, AG.OFTDate) + @test AG.gettype(fd) == AG.OFTDate + AG.settype!(fd, AG.OFTInteger) + @test AG.getsubtype(fd) == AG.OFSTNone + AG.setsubtype!(fd, AG.OFSTInt16) + @test AG.getsubtype(fd) == AG.OFSTInt16 + AG.setsubtype!(fd, AG.OFSTBoolean) + @test AG.getsubtype(fd) == AG.OFSTBoolean + AG.setsubtype!(fd, AG.OFSTNone) + @test AG.getjustify(fd) == AG.OJUndefined + AG.setjustify!(fd, AG.OJLeft) + @test AG.getjustify(fd) == AG.OJLeft + @test AG.getwidth(fd) == 0 + AG.setwidth!(fd, 10) + @test AG.getwidth(fd) == 10 + @test AG.getprecision(fd) == 0 + AG.setprecision!(fd, 20) + @test AG.getprecision(fd) == 20 + AG.setparams!( + fd, + "finalname", + AG.OFTDate, + nwidth = 5, + nprecision = 2, + justify = AG.OJRight, + ) + @test AG.gettype(fd) == AG.OFTDate + @test AG.getname(fd) == "finalname" + @test AG.getsubtype(fd) == AG.OFSTNone + @test AG.getjustify(fd) == AG.OJRight + @test AG.getwidth(fd) == 5 + @test AG.getprecision(fd) == 2 + @test AG.isignored(fd) == false + AG.setignored!(fd, true) + @test AG.isignored(fd) == true + AG.setignored!(fd, false) + @test AG.isignored(fd) == false + + @test AG.isnullable(fd) == true + AG.setnullable!(fd, false) + @test AG.isnullable(fd) == false + AG.setnullable!(fd, true) + @test AG.isnullable(fd) == true + + @test AG.getdefault(fd) == "" + AG.setdefault!(fd, "0001/01/01 00:00:00") + @test AG.getdefault(fd) == "0001/01/01 00:00:00" + @test AG.isdefaultdriverspecific(fd) == true + end end -end -@testset "Tests for Geom Field Defn" begin - AG.creategeomdefn("geomname", AG.wkbPolygon) do gfd - @test AG.getname(gfd) == "geomname" - AG.setname!(gfd, "my name!") - @test AG.getname(gfd) == "my name!" + @testset "Tests for Geom Field Defn" begin + AG.creategeomdefn("geomname", AG.wkbPolygon) do gfd + @test AG.getname(gfd) == "geomname" + AG.setname!(gfd, "my name!") + @test AG.getname(gfd) == "my name!" - @test AG.gettype(gfd) == AG.wkbPolygon - AG.settype!(gfd, AG.wkbPolyhedralSurface) - @test AG.gettype(gfd) == AG.wkbPolyhedralSurface + @test AG.gettype(gfd) == AG.wkbPolygon + AG.settype!(gfd, AG.wkbPolyhedralSurface) + @test AG.gettype(gfd) == AG.wkbPolyhedralSurface - @test sprint(print, AG.getspatialref(gfd)) == "NULL Spatial Reference System" - AG.getspatialref(gfd) do spref - @test sprint(print, spref) == "NULL Spatial Reference System" - end - AG.setspatialref!(gfd, AG.importEPSG(4326)) - @test sprint(print, AG.getspatialref(gfd)) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" - AG.getspatialref(gfd) do spref - @test sprint(print, spref) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" - end + @test sprint(print, AG.getspatialref(gfd)) == "NULL Spatial Reference System" + AG.getspatialref(gfd) do spref + @test sprint(print, spref) == "NULL Spatial Reference System" + end + AG.setspatialref!(gfd, AG.importEPSG(4326)) + @test sprint(print, AG.getspatialref(gfd)) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + AG.getspatialref(gfd) do spref + @test sprint(print, spref) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + end - @test AG.isignored(gfd) == false - AG.setignored!(gfd, true) - @test AG.isignored(gfd) == true - AG.setignored!(gfd, false) - @test AG.isignored(gfd) == false - - @test AG.isnullable(gfd) == true - AG.setnullable!(gfd, false) - @test AG.isnullable(gfd) == false - AG.setnullable!(gfd, true) - @test AG.isnullable(gfd) == true + @test AG.isignored(gfd) == false + AG.setignored!(gfd, true) + @test AG.isignored(gfd) == true + AG.setignored!(gfd, false) + @test AG.isignored(gfd) == false + + @test AG.isnullable(gfd) == true + AG.setnullable!(gfd, false) + @test AG.isnullable(gfd) == false + AG.setnullable!(gfd, true) + @test AG.isnullable(gfd) == true + end end -end -@testset "Tests for Feature Defn" begin - AG.createfeaturedefn("new_feature") do fd - @test AG.nreference(fd) == 0 - AG.reference(fd) - @test AG.nreference(fd) == 1 - AG.reference(fd) - @test AG.nreference(fd) == 2 - AG.release(fd) - @test AG.nreference(fd) == 1 - AG.dereference(fd) - @test AG.nreference(fd) == 0 - AG.createfielddefn("fieldname", AG.OFTInteger) do fielddef - @test AG.nfield(fd) == 0 - AG.addfielddefn!(fd, fielddef) - @test AG.nfield(fd) == 1 - AG.addfielddefn!(fd, fielddef) - @test AG.nfield(fd) == 2 - AG.addfielddefn!(fd, fielddef) + @testset "Tests for Feature Defn" begin + AG.createfeaturedefn("new_feature") do fd + @test AG.nreference(fd) == 0 + AG.reference(fd) + @test AG.nreference(fd) == 1 + AG.reference(fd) + @test AG.nreference(fd) == 2 + AG.release(fd) + @test AG.nreference(fd) == 1 + AG.dereference(fd) + @test AG.nreference(fd) == 0 + AG.createfielddefn("fieldname", AG.OFTInteger) do fielddef + @test AG.nfield(fd) == 0 + AG.addfielddefn!(fd, fielddef) + @test AG.nfield(fd) == 1 + AG.addfielddefn!(fd, fielddef) + @test AG.nfield(fd) == 2 + AG.addfielddefn!(fd, fielddef) + @test AG.nfield(fd) == 3 + AG.createfielddefn("newfield", AG.OFTInteger) do fielddef2 + AG.addfielddefn!(fd, fielddef2) + @test AG.nfield(fd) == 4 + AG.getname(AG.getfielddefn(fd, 0)) == "fieldname" + AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" + AG.getname(AG.getfielddefn(fd, 2)) == "fieldname" + AG.getname(AG.getfielddefn(fd, 3)) == "newfield" + end + end + AG.deletefielddefn!(fd, 0) @test AG.nfield(fd) == 3 - AG.createfielddefn("newfield", AG.OFTInteger) do fielddef2 - AG.addfielddefn!(fd, fielddef2) - @test AG.nfield(fd) == 4 - AG.getname(AG.getfielddefn(fd,0)) == "fieldname" - AG.getname(AG.getfielddefn(fd,1)) == "fieldname" - AG.getname(AG.getfielddefn(fd,2)) == "fieldname" - AG.getname(AG.getfielddefn(fd,3)) == "newfield" + AG.getname(AG.getfielddefn(fd, 0)) == "fieldname" + AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" + AG.getname(AG.getfielddefn(fd, 2)) == "newfield" + + AG.reorderfielddefns!(fd, Cint[2, 1, 0]) + @test AG.nfield(fd) == 3 + AG.getname(AG.getfielddefn(fd, 0)) == "newfield" + AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" + AG.getname(AG.getfielddefn(fd, 2)) == "fieldname" + + @test AG.ngeom(fd) == 1 + @test AG.getgeomtype(fd) == AG.wkbUnknown + AG.setgeomtype!(fd, AG.wkbPolygon) + @test AG.getgeomtype(fd) == AG.wkbPolygon + @test AG.ngeom(fd) == 1 + + @test AG.isgeomignored(fd) == false + AG.setgeomignored!(fd, true) + @test AG.isgeomignored(fd) == true + AG.setgeomignored!(fd, false) + @test AG.isgeomignored(fd) == false + + @test AG.isstyleignored(fd) == false + AG.setstyleignored!(fd, true) + @test AG.isstyleignored(fd) == true + AG.setstyleignored!(fd, false) + @test AG.isstyleignored(fd) == false + + @test AG.findgeomindex(fd) == 0 + gfd0 = AG.getgeomdefn(fd, 0) + @test AG.ngeom(fd) == 1 + AG.addgeomdefn!(fd, gfd0) + @test AG.ngeom(fd) == 2 + gfd1 = AG.getgeomdefn(fd, 1) + AG.setname!(gfd0, "name0") + AG.setname!(gfd1, "name1") + @test AG.findgeomindex(fd, "") == -1 + @test AG.findgeomindex(fd, "name0") == 0 + @test AG.findgeomindex(fd, "name1") == 1 + AG.deletegeomdefn!(fd, 0) + @test AG.ngeom(fd) == 1 + @test AG.findgeomindex(fd, "") == -1 + @test AG.findgeomindex(fd, "name0") == -1 + @test AG.findgeomindex(fd, "name1") == 0 + @test AG.nreference(fd) == 0 + AG.createfeature(fd) do f + @test AG.nreference(fd) == 2 # artificially inflated + @test AG.issame(AG.getfeaturedefn(f), fd) == true end + @test AG.nreference(fd) == 0 end - AG.deletefielddefn!(fd, 0) - @test AG.nfield(fd) == 3 - AG.getname(AG.getfielddefn(fd,0)) == "fieldname" - AG.getname(AG.getfielddefn(fd,1)) == "fieldname" - AG.getname(AG.getfielddefn(fd,2)) == "newfield" - - AG.reorderfielddefns!(fd, Cint[2,1,0]) - @test AG.nfield(fd) == 3 - AG.getname(AG.getfielddefn(fd,0)) == "newfield" - AG.getname(AG.getfielddefn(fd,1)) == "fieldname" - AG.getname(AG.getfielddefn(fd,2)) == "fieldname" - - @test AG.ngeom(fd) == 1 - @test AG.getgeomtype(fd) == AG.wkbUnknown - AG.setgeomtype!(fd, AG.wkbPolygon) - @test AG.getgeomtype(fd) == AG.wkbPolygon - @test AG.ngeom(fd) == 1 - - @test AG.isgeomignored(fd) == false - AG.setgeomignored!(fd, true) - @test AG.isgeomignored(fd) == true - AG.setgeomignored!(fd, false) - @test AG.isgeomignored(fd) == false - - @test AG.isstyleignored(fd) == false - AG.setstyleignored!(fd, true) - @test AG.isstyleignored(fd) == true - AG.setstyleignored!(fd, false) - @test AG.isstyleignored(fd) == false - - @test AG.findgeomindex(fd) == 0 - gfd0 = AG.getgeomdefn(fd, 0) - @test AG.ngeom(fd) == 1 - AG.addgeomdefn!(fd, gfd0) - @test AG.ngeom(fd) == 2 - gfd1 = AG.getgeomdefn(fd, 1) - AG.setname!(gfd0, "name0") - AG.setname!(gfd1, "name1") - @test AG.findgeomindex(fd, "") == -1 - @test AG.findgeomindex(fd, "name0") == 0 - @test AG.findgeomindex(fd, "name1") == 1 - AG.deletegeomdefn!(fd, 0) - @test AG.ngeom(fd) == 1 - @test AG.findgeomindex(fd, "") == -1 - @test AG.findgeomindex(fd, "name0") == -1 - @test AG.findgeomindex(fd, "name1") == 0 - @test AG.nreference(fd) == 0 - AG.createfeature(fd) do f - @test AG.nreference(fd) == 2 # artificially inflated - @test AG.issame(AG.getfeaturedefn(f), fd) == true - end - @test AG.nreference(fd) == 0 end -end end diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index f390af35..c33ba1b4 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -1,133 +1,219 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_gdal_tutorials.jl" begin -@testset "Raster Tutorial" begin - driver = AG.getdriver("GTiff") - - AG.read("data/utmsmall.tif") do dataset - @test AG.shortname(driver) == "GTiff" - @test AG.longname(driver) == "GeoTIFF" - @test AG.width(dataset) == 100 - @test AG.height(dataset) == 100 - @test AG.nraster(dataset) == 1 - - nad27_prefix = "PROJCS[\"NAD27 / UTM zone 11N\",GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\"," - @test startswith(AG.getproj(dataset), nad27_prefix) == true - @test AG.getgeotransform(dataset) ≈ - [440720.0,60.0,0.0,3.75132e6,0.0,-60.0] - - band = AG.getband(dataset, 1) - @test AG.blocksize(band) ≈ [100, 81] - @test AG.pixeltype(band) == UInt8 - @test AG.getname(AG.getcolorinterp(band)) == "Gray" - - @test AG.minimum(band) ≈ 0.0 - @test AG.maximum(band) ≈ 255.0 - - @test AG.noverview(band) == 0 - - # Reading Raster Data - @test AG.width(band) == 100 - data = map(Float32, AG.read(dataset, 1)) - @test data[:,1] ≈ Float32[107.0f0,123.0f0,132.0f0,115.0f0, - 132.0f0,132.0f0,140.0f0,132.0f0,132.0f0,132.0f0,107.0f0, - 132.0f0,107.0f0,132.0f0,132.0f0,107.0f0,123.0f0,115.0f0, - 156.0f0,148.0f0,107.0f0,132.0f0,107.0f0,115.0f0,99.0f0, - 123.0f0,99.0f0,74.0f0,115.0f0,82.0f0,115.0f0,115.0f0, - 107.0f0,123.0f0,123.0f0,99.0f0,123.0f0,123.0f0,115.0f0, - 115.0f0,107.0f0,90.0f0,99.0f0,107.0f0,107.0f0,99.0f0, - 123.0f0,107.0f0,140.0f0,123.0f0,123.0f0,115.0f0,99.0f0, - 132.0f0,123.0f0,115.0f0,115.0f0,123.0f0,132.0f0,115.0f0, - 123.0f0,132.0f0,214.0f0,156.0f0,165.0f0,148.0f0,115.0f0, - 148.0f0,156.0f0,148.0f0,140.0f0,165.0f0,156.0f0,197.0f0, - 156.0f0,197.0f0,140.0f0,173.0f0,156.0f0,165.0f0,148.0f0, - 156.0f0,206.0f0,214.0f0,181.0f0,206.0f0,173.0f0,222.0f0, - 206.0f0,255.0f0,214.0f0,173.0f0,214.0f0,255.0f0,214.0f0, - 247.0f0,255.0f0,230.0f0,206.0f0,197.0f0] - - @test AG.metadatadomainlist(dataset) == ["IMAGE_STRUCTURE", "", "DERIVED_SUBDATASETS"] - @test AG.metadata(dataset) == ["AREA_OR_POINT=Area"] - @test AG.metadataitem(dataset, "AREA_OR_POINT") == "Area" - @test AG.metadata(dataset, domain = "IMAGE_STRUCTURE") == ["INTERLEAVE=BAND"] - @test AG.metadata(dataset, domain = "") == ["AREA_OR_POINT=Area"] - @test AG.metadata(dataset, domain = "DERIVED_SUBDATASETS") == [ - "DERIVED_SUBDATASET_1_NAME=DERIVED_SUBDATASET:LOGAMPLITUDE:data/utmsmall.tif", - "DERIVED_SUBDATASET_1_DESC=log10 of amplitude of input bands from data/utmsmall.tif" - ] - end + @testset "Raster Tutorial" begin + driver = AG.getdriver("GTiff") + + AG.read("data/utmsmall.tif") do dataset + @test AG.shortname(driver) == "GTiff" + @test AG.longname(driver) == "GeoTIFF" + @test AG.width(dataset) == 100 + @test AG.height(dataset) == 100 + @test AG.nraster(dataset) == 1 + + nad27_prefix = "PROJCS[\"NAD27 / UTM zone 11N\",GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\"," + @test startswith(AG.getproj(dataset), nad27_prefix) == true + @test AG.getgeotransform(dataset) ≈ [440720.0, 60.0, 0.0, 3.75132e6, 0.0, -60.0] + + band = AG.getband(dataset, 1) + @test AG.blocksize(band) ≈ [100, 81] + @test AG.pixeltype(band) == UInt8 + @test AG.getname(AG.getcolorinterp(band)) == "Gray" + + @test AG.minimum(band) ≈ 0.0 + @test AG.maximum(band) ≈ 255.0 + + @test AG.noverview(band) == 0 + + # Reading Raster Data + @test AG.width(band) == 100 + data = map(Float32, AG.read(dataset, 1)) + @test data[:, 1] ≈ Float32[ + 107.0f0, + 123.0f0, + 132.0f0, + 115.0f0, + 132.0f0, + 132.0f0, + 140.0f0, + 132.0f0, + 132.0f0, + 132.0f0, + 107.0f0, + 132.0f0, + 107.0f0, + 132.0f0, + 132.0f0, + 107.0f0, + 123.0f0, + 115.0f0, + 156.0f0, + 148.0f0, + 107.0f0, + 132.0f0, + 107.0f0, + 115.0f0, + 99.0f0, + 123.0f0, + 99.0f0, + 74.0f0, + 115.0f0, + 82.0f0, + 115.0f0, + 115.0f0, + 107.0f0, + 123.0f0, + 123.0f0, + 99.0f0, + 123.0f0, + 123.0f0, + 115.0f0, + 115.0f0, + 107.0f0, + 90.0f0, + 99.0f0, + 107.0f0, + 107.0f0, + 99.0f0, + 123.0f0, + 107.0f0, + 140.0f0, + 123.0f0, + 123.0f0, + 115.0f0, + 99.0f0, + 132.0f0, + 123.0f0, + 115.0f0, + 115.0f0, + 123.0f0, + 132.0f0, + 115.0f0, + 123.0f0, + 132.0f0, + 214.0f0, + 156.0f0, + 165.0f0, + 148.0f0, + 115.0f0, + 148.0f0, + 156.0f0, + 148.0f0, + 140.0f0, + 165.0f0, + 156.0f0, + 197.0f0, + 156.0f0, + 197.0f0, + 140.0f0, + 173.0f0, + 156.0f0, + 165.0f0, + 148.0f0, + 156.0f0, + 206.0f0, + 214.0f0, + 181.0f0, + 206.0f0, + 173.0f0, + 222.0f0, + 206.0f0, + 255.0f0, + 214.0f0, + 173.0f0, + 214.0f0, + 255.0f0, + 214.0f0, + 247.0f0, + 255.0f0, + 230.0f0, + 206.0f0, + 197.0f0, + ] + + @test AG.metadatadomainlist(dataset) == + ["IMAGE_STRUCTURE", "", "DERIVED_SUBDATASETS"] + @test AG.metadata(dataset) == ["AREA_OR_POINT=Area"] + @test AG.metadataitem(dataset, "AREA_OR_POINT") == "Area" + @test AG.metadata(dataset, domain = "IMAGE_STRUCTURE") == ["INTERLEAVE=BAND"] + @test AG.metadata(dataset, domain = "") == ["AREA_OR_POINT=Area"] + @test AG.metadata(dataset, domain = "DERIVED_SUBDATASETS") == [ + "DERIVED_SUBDATASET_1_NAME=DERIVED_SUBDATASET:LOGAMPLITUDE:data/utmsmall.tif", + "DERIVED_SUBDATASET_1_DESC=log10 of amplitude of input bands from data/utmsmall.tif", + ] + end - # Get metadata from a RasterDataset - AG.readraster("data/utmsmall.tif") do dataset - # interestingly the list order below is different from the order above - @test AG.metadatadomainlist(dataset) == ["IMAGE_STRUCTURE", "DERIVED_SUBDATASETS", ""] - @test AG.metadata(dataset) == ["AREA_OR_POINT=Area"] - @test AG.metadataitem(dataset, "AREA_OR_POINT") == "Area" - end + # Get metadata from a RasterDataset + AG.readraster("data/utmsmall.tif") do dataset + # interestingly the list order below is different from the order above + @test AG.metadatadomainlist(dataset) == + ["IMAGE_STRUCTURE", "DERIVED_SUBDATASETS", ""] + @test AG.metadata(dataset) == ["AREA_OR_POINT=Area"] + @test AG.metadataitem(dataset, "AREA_OR_POINT") == "Area" + end - # Techniques for Creating Files - @test AG.metadataitem(driver, "DCAP_CREATE", domain = "") == "YES" - @test AG.metadataitem(driver, "DCAP_CREATECOPY", domain = "") == "YES" + # Techniques for Creating Files + @test AG.metadataitem(driver, "DCAP_CREATE", domain = "") == "YES" + @test AG.metadataitem(driver, "DCAP_CREATECOPY", domain = "") == "YES" - AG.read("data/utmsmall.tif") do ds_src - AG.write(ds_src, "/vsimem/utmsmall.tif") - AG.read("/vsimem/utmsmall.tif") do ds_copy - @test AG.read(ds_src) == AG.read(ds_copy) + AG.read("data/utmsmall.tif") do ds_src + AG.write(ds_src, "/vsimem/utmsmall.tif") + AG.read("/vsimem/utmsmall.tif") do ds_copy + @test AG.read(ds_src) == AG.read(ds_copy) + end end end -end -@testset "Vector Tutorial" begin - AG.read("data/point.geojson") do dataset - @test AG.nlayer(dataset) == 1 - layer = AG.getlayer(dataset, 0) - @test (AG.getname(layer) in ["point", "OGRGeoJSON"]) == true - layerbyname = AG.getlayer(dataset, "point") - @test layerbyname.ptr == layer.ptr - AG.resetreading!(layer) - - featuredefn = AG.layerdefn(layer) - @test AG.nfield(featuredefn) == 2 - fielddefn = AG.getfielddefn(featuredefn, 0) - @test AG.gettype(fielddefn) == AG.OFTReal - fielddefn = AG.getfielddefn(featuredefn, 1) - @test AG.gettype(fielddefn) == AG.OFTString - - AG.nextfeature(layer) do feature - @test AG.asdouble(feature, 0) ≈ 2.0 - @test AG.asstring(feature, 1) == "point-a" - end - AG.nextfeature(layer) do feature # second feature - @test AG.asdouble(feature, 0) ≈ 3.0 - @test AG.asstring(feature, 1) == "point-b" + @testset "Vector Tutorial" begin + AG.read("data/point.geojson") do dataset + @test AG.nlayer(dataset) == 1 + layer = AG.getlayer(dataset, 0) + @test (AG.getname(layer) in ["point", "OGRGeoJSON"]) == true + layerbyname = AG.getlayer(dataset, "point") + @test layerbyname.ptr == layer.ptr + AG.resetreading!(layer) - geometry = AG.getgeom(feature) - @test AG.geomname(geometry) == "POINT" - @test AG.getgeomtype(geometry) == AG.wkbPoint + featuredefn = AG.layerdefn(layer) @test AG.nfield(featuredefn) == 2 - @test AG.getx(geometry, 0) ≈ 100.2785 - @test AG.gety(geometry, 0) ≈ 0.0893 - @test AG.getpoint(geometry, 0) == (100.2785,0.0893,0.0) + fielddefn = AG.getfielddefn(featuredefn, 0) + @test AG.gettype(fielddefn) == AG.OFTReal + fielddefn = AG.getfielddefn(featuredefn, 1) + @test AG.gettype(fielddefn) == AG.OFTString + + AG.nextfeature(layer) do feature + @test AG.asdouble(feature, 0) ≈ 2.0 + @test AG.asstring(feature, 1) == "point-a" + end + AG.nextfeature(layer) do feature # second feature + @test AG.asdouble(feature, 0) ≈ 3.0 + @test AG.asstring(feature, 1) == "point-b" + + geometry = AG.getgeom(feature) + @test AG.geomname(geometry) == "POINT" + @test AG.getgeomtype(geometry) == AG.wkbPoint + @test AG.nfield(featuredefn) == 2 + @test AG.getx(geometry, 0) ≈ 100.2785 + @test AG.gety(geometry, 0) ≈ 0.0893 + @test AG.getpoint(geometry, 0) == (100.2785, 0.0893, 0.0) + end end - end - AG.create(AG.getdriver("MEMORY")) do dataset - layer = AG.createlayer( - name = "point_out", - dataset = dataset, - geom = AG.wkbPoint - ) - AG.addfielddefn!(layer, "Name", AG.OFTString, nwidth = 32) - featuredefn = AG.layerdefn(layer) - @test AG.getname(featuredefn) == "point_out" - @test AG.nfeature(layer) == 0 - AG.createfeature(layer) do feature - AG.setfield!(feature, AG.findfieldindex(feature, "Name"), "myname") - AG.setgeom!(feature, AG.createpoint(100.123, 0.123)) + AG.create(AG.getdriver("MEMORY")) do dataset + layer = + AG.createlayer(name = "point_out", dataset = dataset, geom = AG.wkbPoint) + AG.addfielddefn!(layer, "Name", AG.OFTString, nwidth = 32) + featuredefn = AG.layerdefn(layer) + @test AG.getname(featuredefn) == "point_out" + @test AG.nfeature(layer) == 0 + AG.createfeature(layer) do feature + AG.setfield!(feature, AG.findfieldindex(feature, "Name"), "myname") + AG.setgeom!(feature, AG.createpoint(100.123, 0.123)) + end + @test AG.nfeature(layer) == 1 end - @test AG.nfeature(layer) == 1 end -end end diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index 9ced97a4..f609ea8e 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -1,125 +1,171 @@ -using ArchGDAL, GDAL; AG = ArchGDAL +using ArchGDAL, GDAL; +AG = ArchGDAL; using Test @testset "test_gdalutilities.jl" begin -AG.read("data/utmsmall.tif") do ds_small - @testset "GDAL Error" begin - @test_throws GDAL.GDALError AG.gdalinfo(ds_small, ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdaltranslate(ds_small, ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdalbuildvrt([ds_small], ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdaldem(ds_small, "hillshade", ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdalnearblack(ds_small, ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdalwarp([ds_small], ["-novalidoption"]) - end - - @testset "GDAL Info" begin - infostr = AG.gdalinfo(ds_small, ["-checksum"]) - @test occursin("Checksum=50054", infostr) - info_default = AG.gdalinfo(ds_small) - @test occursin("Driver: GTiff/GeoTIFF", info_default) - end + AG.read("data/utmsmall.tif") do ds_small + @testset "GDAL Error" begin + @test_throws GDAL.GDALError AG.gdalinfo(ds_small, ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdaltranslate( + ds_small, + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdalbuildvrt( + [ds_small], + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdaldem( + ds_small, + "hillshade", + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdalnearblack( + ds_small, + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdalwarp([ds_small], ["-novalidoption"]) + end - AG.gdaltranslate(ds_small, # resample to a 5×5 ascii grid - ["-of","AAIGrid","-r","cubic","-tr","1200","1200"] - ) do ds_tiny - @testset "GDAL Translate" begin - @test AG.read(ds_tiny, 1) == [128 171 127 93 83; - 126 164 148 114 101; - 161 175 177 164 140; - 185 206 205 172 128; - 193 205 209 181 122] + @testset "GDAL Info" begin + infostr = AG.gdalinfo(ds_small, ["-checksum"]) + @test occursin("Checksum=50054", infostr) + info_default = AG.gdalinfo(ds_small) + @test occursin("Driver: GTiff/GeoTIFF", info_default) end - @testset "GDAL Build VRT" begin - AG.gdalbuildvrt([ds_tiny]) do ds_vrt - @test AG.read(ds_vrt, 1) == [128 171 127 93 83; - 126 164 148 114 101; - 161 175 177 164 140; - 185 206 205 172 128; - 193 205 209 181 122] + AG.gdaltranslate( + ds_small, # resample to a 5×5 ascii grid + ["-of", "AAIGrid", "-r", "cubic", "-tr", "1200", "1200"], + ) do ds_tiny + @testset "GDAL Translate" begin + @test AG.read(ds_tiny, 1) == [ + 128 171 127 93 83 + 126 164 148 114 101 + 161 175 177 164 140 + 185 206 205 172 128 + 193 205 209 181 122 + ] end - end - @testset "GDAL DEM Processing" begin - AG.gdaldem(ds_tiny, "hillshade", ["-of","AAIGrid"]) do ds_dempr - @test AG.read(ds_dempr, 1) == [ 0 0 0 0 0; - 0 183 180 181 0; - 0 184 182 181 0; - 0 183 181 177 0; - 0 0 0 0 0] + @testset "GDAL Build VRT" begin + AG.gdalbuildvrt([ds_tiny]) do ds_vrt + @test AG.read(ds_vrt, 1) == [ + 128 171 127 93 83 + 126 164 148 114 101 + 161 175 177 164 140 + 185 206 205 172 128 + 193 205 209 181 122 + ] + end end - AG.gdaldem( + + @testset "GDAL DEM Processing" begin + AG.gdaldem(ds_tiny, "hillshade", ["-of", "AAIGrid"]) do ds_dempr + @test AG.read(ds_dempr, 1) == [ + 0 0 0 0 0 + 0 183 180 181 0 + 0 184 182 181 0 + 0 183 181 177 0 + 0 0 0 0 0 + ] + end + AG.gdaldem( ds_tiny, "color-relief", - colorfile = "data/color_relief.txt" + colorfile = "data/color_relief.txt", ) do ds_dempr - @test AG.read(ds_dempr, 1) == [ 0x80 0x87 0x80 0x7b 0x7a; - 0x80 0x86 0x83 0x7e 0x7d; - 0x85 0x87 0x88 0x86 0x82; - 0x89 0x8c 0x8c 0x87 0x80; - 0x8a 0x8c 0x8c 0x88 0x80] + @test AG.read(ds_dempr, 1) == [ + 0x80 0x87 0x80 0x7b 0x7a + 0x80 0x86 0x83 0x7e 0x7d + 0x85 0x87 0x88 0x86 0x82 + 0x89 0x8c 0x8c 0x87 0x80 + 0x8a 0x8c 0x8c 0x88 0x80 + ] + end end - end - @testset "GDAL Near Black" begin - AG.gdalnearblack(ds_tiny, ["-of","GTiff","-color","0"]) do ds_nearblack - @test AG.read(ds_nearblack, 1) == [ 0 0 0 0 0; - 0 0 0 0 0; - 0 0 177 0 0; - 0 0 0 0 0; - 0 0 0 0 0] + @testset "GDAL Near Black" begin + AG.gdalnearblack(ds_tiny, ["-of", "GTiff", "-color", "0"]) do ds_nearblack + @test AG.read(ds_nearblack, 1) == [ + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 177 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + ] + end end end - end - @testset "GDAL Warp" begin - AG.gdalwarp([ds_small], ["-of","MEM","-t_srs","EPSG:4326"]) do ds_warped - @test AG.width(ds_small) == 100 - @test AG.height(ds_small) == 100 - @test AG.width(ds_warped) == 109 - @test AG.height(ds_warped) == 91 + @testset "GDAL Warp" begin + AG.gdalwarp([ds_small], ["-of", "MEM", "-t_srs", "EPSG:4326"]) do ds_warped + @test AG.width(ds_small) == 100 + @test AG.height(ds_small) == 100 + @test AG.width(ds_warped) == 109 + @test AG.height(ds_warped) == 91 + end end - end - @testset "GDAL Warp" begin - AG.gdalwarp([ds_small], ["-of","MEM"]) do ds_warped - @test AG.width(ds_small) == 100 - @test AG.height(ds_small) == 100 - @test AG.shortname(AG.getdriver(ds_small)) == "GTiff" - @test AG.width(ds_warped) == 100 - @test AG.height(ds_warped) == 100 - @test AG.shortname(AG.getdriver(ds_warped)) == "MEM" + @testset "GDAL Warp" begin + AG.gdalwarp([ds_small], ["-of", "MEM"]) do ds_warped + @test AG.width(ds_small) == 100 + @test AG.height(ds_small) == 100 + @test AG.shortname(AG.getdriver(ds_small)) == "GTiff" + @test AG.width(ds_warped) == 100 + @test AG.height(ds_warped) == 100 + @test AG.shortname(AG.getdriver(ds_warped)) == "MEM" + end end end -end -AG.read("data/point.geojson") do ds_point - @testset "GDAL Grid" begin - AG.gdalgrid(ds_point, ["-of","MEM","-outsize","3", - "10","-txe","100","100.3","-tye","0","0.1"]) do ds_grid - @test AG.getgeotransform(ds_grid) ≈ [100.0,0.1,0.0,0.0,0.0,0.01] + AG.read("data/point.geojson") do ds_point + @testset "GDAL Grid" begin + AG.gdalgrid( + ds_point, + [ + "-of", + "MEM", + "-outsize", + "3", + "10", + "-txe", + "100", + "100.3", + "-tye", + "0", + "0.1", + ], + ) do ds_grid + @test AG.getgeotransform(ds_grid) ≈ [100.0, 0.1, 0.0, 0.0, 0.0, 0.01] + end end - end - @testset "GDAL Rasterize" begin - AG.gdalrasterize(ds_point, ["-of","MEM","-tr","0.05","0.05"]) do ds_rasterize - @test AG.getgeotransform(ds_rasterize) ≈ [99.975,0.05,0.0,0.1143,0.0,-0.05] + @testset "GDAL Rasterize" begin + AG.gdalrasterize( + ds_point, + ["-of", "MEM", "-tr", "0.05", "0.05"], + ) do ds_rasterize + @test AG.getgeotransform(ds_rasterize) ≈ + [99.975, 0.05, 0.0, 0.1143, 0.0, -0.05] + end end - end - @testset "GDAL Vector Translate" begin - AG.gdalvectortranslate([ds_point], ["-f","CSV","-lco", - "GEOMETRY=AS_XY"], dest = "data/point.csv") do ds_csv + @testset "GDAL Vector Translate" begin + AG.gdalvectortranslate( + [ds_point], + ["-f", "CSV", "-lco", "GEOMETRY=AS_XY"], + dest = "data/point.csv", + ) do ds_csv + end + @test replace(read("data/point.csv", String), "\r" => "") == """ + X,Y,FID,pointname + 100,0,2,point-a + 100.2785,0.0893,3,point-b + 100,0,0,a + 100.2785,0.0893,3,b + """ + rm("data/point.csv") end - @test replace(read("data/point.csv", String), "\r" => "") == """ - X,Y,FID,pointname - 100,0,2,point-a - 100.2785,0.0893,3,point-b - 100,0,0,a - 100.2785,0.0893,3,b - """ - rm("data/point.csv") end -end end diff --git a/test/test_geometry.jl b/test/test_geometry.jl index cb4c6736..b5fbd7e5 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -5,21 +5,151 @@ const GFT = GeoFormatTypes @testset "test_geometry.jl" begin -@testset "Incomplete GeoInterface geometries" begin - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbCircularString)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbCompoundCurve)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbCurvePolygon)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbMultiSurface)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbPolyhedralSurface)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbTIN)) - @test_logs (:warn, "unknown geometry type") GeoInterface.geotype(AG.creategeom(AG.wkbTriangle)) -end + @testset "Incomplete GeoInterface geometries" begin + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbCircularString), + ) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbCompoundCurve), + ) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbCurvePolygon), + ) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbMultiSurface), + ) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbPolyhedralSurface), + ) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbTIN), + ) + @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( + AG.creategeom(AG.wkbTriangle), + ) + end -@testset "Create a Point" begin - # Method 1 - AG.createpoint(100, 70) do point - @test GeoInterface.geotype(point) == :Point - @test isapprox(GeoInterface.coordinates(point), [100,70], atol=1e-6) + @testset "Create a Point" begin + # Method 1 + AG.createpoint(100, 70) do point + @test GeoInterface.geotype(point) == :Point + @test isapprox(GeoInterface.coordinates(point), [100, 70], atol = 1e-6) + @test AG.geomdim(point) == 0 + @test AG.getcoorddim(point) == 2 + AG.setcoorddim!(point, 3) + @test AG.getcoorddim(point) == 3 + @test AG.isvalid(point) == true + @test AG.issimple(point) == true + @test AG.isring(point) == false + @test AG.getz(point, 0) == 0 + + @test sprint(print, AG.envelope(point)) == + "GDAL.OGREnvelope(100.0, 100.0, 70.0, 70.0)" + @test sprint(print, AG.envelope3d(point)) == + "GDAL.OGREnvelope3D(100.0, 100.0, 70.0, 70.0, 0.0, 0.0)" + @test AG.toISOWKB(point, AG.wkbNDR) == UInt8[ + 0x01, + 0xe9, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x59, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x51, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ] + @test AG.toISOWKB(point, AG.wkbXDR) == UInt8[ + 0x00, + 0x00, + 0x00, + 0x03, + 0xe9, + 0x40, + 0x59, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x51, + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ] + @test AG.toKML(point, "relativeToGround") == + "relativeToGround100,70,0" + @test AG.toKML(point, "clampToGround") == + "clampToGround100,70,0" + @test AG.toKML(point) == "100,70,0" + @test AG.toJSON(point) == + "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" + @test startswith( + AG.toJSON(point, SIGNIFICANT_FIGURES = 1), + "{ \"type\": \"Point\", \"coordinates\": [", + ) + @test startswith( + AG.toJSON(point, ["SIGNIFICANT_FIGURES=1"]), + "{ \"type\": \"Point\", \"coordinates\": [", + ) + AG.createpoint(100, 70, 0) do point2 + @test isapprox(GeoInterface.coordinates(point2), [100, 70, 0], atol = 1e-6) + @test AG.equals(point, point2) == true + end + AG.createpoint((100, 70, 0)) do point3 + @test AG.equals(point, point3) == true + end + AG.createpoint([100, 70, 0]) do point4 + @test AG.equals(point, point4) == true + end + point5 = AG.createpoint([100, 70, 0]) + @test AG.equals(point, point5) == true + AG.flattento2d!(point) + @test AG.getcoorddim(point) == 2 + @test AG.getnonlineargeomflag() == true + AG.setnonlineargeomflag!(false) + @test AG.getnonlineargeomflag() == false + AG.setnonlineargeomflag!(true) + @test AG.getnonlineargeomflag() == true + AG.closerings!(point) + @test AG.toJSON(point) == + "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0 ] }" + end + + # Method 2 + point = AG.createpoint(100, 70) @test AG.geomdim(point) == 0 @test AG.getcoorddim(point) == 2 AG.setcoorddim!(point, 3) @@ -28,33 +158,81 @@ end @test AG.issimple(point) == true @test AG.isring(point) == false @test AG.getz(point, 0) == 0 - - @test sprint(print, AG.envelope(point)) == "GDAL.OGREnvelope(100.0, 100.0, 70.0, 70.0)" - @test sprint(print, AG.envelope3d(point)) == "GDAL.OGREnvelope3D(100.0, 100.0, 70.0, 70.0, 0.0, 0.0)" - @test AG.toISOWKB(point, AG.wkbNDR) == UInt8[0x01,0xe9,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x40,0x00,0x00,0x00,0x00,0x00,0x80, - 0x51,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] - @test AG.toISOWKB(point, AG.wkbXDR) == UInt8[0x00,0x00,0x00,0x03,0xe9, - 0x40,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x51,0x80,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] - @test AG.toKML(point, "relativeToGround") == "relativeToGround100,70,0" - @test AG.toKML(point, "clampToGround") == "clampToGround100,70,0" + @test sprint(print, AG.envelope(point)) == + "GDAL.OGREnvelope(100.0, 100.0, 70.0, 70.0)" + @test sprint(print, AG.envelope3d(point)) == + "GDAL.OGREnvelope3D(100.0, 100.0, 70.0, 70.0, 0.0, 0.0)" + @test AG.toISOWKB(point, AG.wkbNDR) == UInt8[ + 0x01, + 0xe9, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x59, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x51, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ] + @test AG.toISOWKB(point, AG.wkbXDR) == UInt8[ + 0x00, + 0x00, + 0x00, + 0x03, + 0xe9, + 0x40, + 0x59, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0x51, + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ] + @test AG.toKML(point, "relativeToGround") == + "relativeToGround100,70,0" + @test AG.toKML(point, "clampToGround") == + "clampToGround100,70,0" @test AG.toKML(point) == "100,70,0" - @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" - @test startswith(AG.toJSON(point, SIGNIFICANT_FIGURES=1), "{ \"type\": \"Point\", \"coordinates\": [") - @test startswith(AG.toJSON(point, ["SIGNIFICANT_FIGURES=1"]), "{ \"type\": \"Point\", \"coordinates\": [") - AG.createpoint(100,70,0) do point2 - @test isapprox(GeoInterface.coordinates(point2), [100,70,0], atol=1e-6) - @test AG.equals(point, point2) == true - end - AG.createpoint((100,70,0)) do point3 - @test AG.equals(point, point3) == true - end - AG.createpoint([100,70,0]) do point4 - @test AG.equals(point, point4) == true - end - point5 = AG.createpoint([100,70,0]) - @test AG.equals(point, point5) == true + @test AG.toJSON(point) == + "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" + @test AG.equals(point, AG.createpoint(100, 70, 0)) == true + @test AG.equals(point, AG.createpoint((100, 70, 0))) == true AG.flattento2d!(point) @test AG.getcoorddim(point) == 2 @test AG.getnonlineargeomflag() == true @@ -63,305 +241,355 @@ end AG.setnonlineargeomflag!(true) @test AG.getnonlineargeomflag() == true AG.closerings!(point) - @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0 ] }" + @test AG.toJSON(point) == + "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0 ] }" end - # Method 2 - point = AG.createpoint(100, 70) - @test AG.geomdim(point) == 0 - @test AG.getcoorddim(point) == 2 - AG.setcoorddim!(point, 3) - @test AG.getcoorddim(point) == 3 - @test AG.isvalid(point) == true - @test AG.issimple(point) == true - @test AG.isring(point) == false - @test AG.getz(point, 0) == 0 - @test sprint(print, AG.envelope(point)) == "GDAL.OGREnvelope(100.0, 100.0, 70.0, 70.0)" - @test sprint(print, AG.envelope3d(point)) == "GDAL.OGREnvelope3D(100.0, 100.0, 70.0, 70.0, 0.0, 0.0)" - @test AG.toISOWKB(point, AG.wkbNDR) == UInt8[0x01,0xe9,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x40,0x00,0x00,0x00,0x00,0x00,0x80, - 0x51,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] - @test AG.toISOWKB(point, AG.wkbXDR) == UInt8[0x00,0x00,0x00,0x03,0xe9, - 0x40,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x51,0x80,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] - @test AG.toKML(point, "relativeToGround") == "relativeToGround100,70,0" - @test AG.toKML(point, "clampToGround") == "clampToGround100,70,0" - @test AG.toKML(point) == "100,70,0" - @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" - @test AG.equals(point, AG.createpoint(100,70,0)) == true - @test AG.equals(point, AG.createpoint((100,70,0))) == true - AG.flattento2d!(point) - @test AG.getcoorddim(point) == 2 - @test AG.getnonlineargeomflag() == true - AG.setnonlineargeomflag!(false) - @test AG.getnonlineargeomflag() == false - AG.setnonlineargeomflag!(true) - @test AG.getnonlineargeomflag() == true - AG.closerings!(point) - @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0 ] }" -end + @testset "Testing construction of complex geometries" begin + @test AG.toWKT(AG.createlinestring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])) == + "LINESTRING (1 4,2 5,3 6)" + AG.createlinestring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]) do geom + @test GeoInterface.geotype(geom) == :LineString + @test isapprox( + GeoInterface.coordinates(geom), + [[1, 4], [2, 5], [3, 6]], + atol = 1e-6, + ) + @test AG.toWKT(geom) == "LINESTRING (1 4,2 5,3 6)" + AG.closerings!(geom) + @test AG.toWKT(geom) == "LINESTRING (1 4,2 5,3 6)" + AG.setpoint!(geom, 1, 10, 10) + @test AG.toWKT(geom) == "LINESTRING (1 4,10 10,3 6)" + @test GFT.val(convert(GFT.WellKnownText, geom)) == AG.toWKT(geom) + end + AG.createlinestring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + @test AG.toWKT(geom) == "LINESTRING (1 4 7,2 5 8,3 6 9)" + AG.setpoint!(geom, 1, 10, 10, 10) + @test AG.toWKT(geom) == "LINESTRING (1 4 7,10 10 10,3 6 9)" + AG.addpoint!(geom, 11, 11, 11) + @test AG.toWKT(geom) == "LINESTRING (1 4 7,10 10 10,3 6 9,11 11 11)" + end -@testset "Testing construction of complex geometries" begin - @test AG.toWKT(AG.createlinestring([1.,2.,3.], [4.,5.,6.])) == "LINESTRING (1 4,2 5,3 6)" - AG.createlinestring([1.,2.,3.], [4.,5.,6.]) do geom - @test GeoInterface.geotype(geom) == :LineString - @test isapprox(GeoInterface.coordinates(geom), [[1,4],[2,5],[3,6]], atol=1e-6) - @test AG.toWKT(geom) == "LINESTRING (1 4,2 5,3 6)" - AG.closerings!(geom) - @test AG.toWKT(geom) == "LINESTRING (1 4,2 5,3 6)" - AG.setpoint!(geom, 1, 10, 10) - @test AG.toWKT(geom) == "LINESTRING (1 4,10 10,3 6)" - @test GFT.val(convert(GFT.WellKnownText, geom)) == AG.toWKT(geom) - end - AG.createlinestring([1.,2.,3.], [4.,5.,6.], [7.,8.,9.]) do geom - @test AG.toWKT(geom) == "LINESTRING (1 4 7,2 5 8,3 6 9)" - AG.setpoint!(geom, 1, 10, 10, 10) - @test AG.toWKT(geom) == "LINESTRING (1 4 7,10 10 10,3 6 9)" - AG.addpoint!(geom, 11, 11, 11) - @test AG.toWKT(geom) == "LINESTRING (1 4 7,10 10 10,3 6 9,11 11 11)" - end - - @test AG.toWKT(AG.createlinearring([1.,2.,3.], [4.,5.,6.])) == "LINEARRING (1 4,2 5,3 6)" - AG.createlinearring([1.,2.,3.], [4.,5.,6.]) do geom - @test GeoInterface.geotype(geom) == :LineString - @test isapprox(GeoInterface.coordinates(geom), [[1,4], [2,5], [3,6]], atol=1e-6) - @test AG.toWKT(geom) == "LINEARRING (1 4,2 5,3 6)" - AG.setpointcount!(geom, 5) - @test AG.toWKT(geom) == "LINEARRING (1 4,2 5,3 6,0 0,0 0)" - AG.empty!(geom) - @test AG.toWKT(geom) == "LINEARRING EMPTY" - end - AG.createlinearring([1.,2.,3.], [4.,5.,6.], [7.,8.,9.]) do geom - @test AG.toWKT(geom) == "LINEARRING (1 4 7,2 5 8,3 6 9)" - AG.closerings!(geom) - @test AG.toWKT(geom) == "LINEARRING (1 4 7,2 5 8,3 6 9,1 4 7)" - end + @test AG.toWKT(AG.createlinearring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])) == + "LINEARRING (1 4,2 5,3 6)" + AG.createlinearring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]) do geom + @test GeoInterface.geotype(geom) == :LineString + @test isapprox( + GeoInterface.coordinates(geom), + [[1, 4], [2, 5], [3, 6]], + atol = 1e-6, + ) + @test AG.toWKT(geom) == "LINEARRING (1 4,2 5,3 6)" + AG.setpointcount!(geom, 5) + @test AG.toWKT(geom) == "LINEARRING (1 4,2 5,3 6,0 0,0 0)" + AG.empty!(geom) + @test AG.toWKT(geom) == "LINEARRING EMPTY" + end + AG.createlinearring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + @test AG.toWKT(geom) == "LINEARRING (1 4 7,2 5 8,3 6 9)" + AG.closerings!(geom) + @test AG.toWKT(geom) == "LINEARRING (1 4 7,2 5 8,3 6 9,1 4 7)" + end - @test AG.toWKT(AG.createpolygon([1.,2.,3.], [4.,5.,6.])) == "POLYGON ((1 4,2 5,3 6))" - AG.createpolygon([1.,2.,3.], [4.,5.,6.]) do geom - @test GeoInterface.geotype(geom) == :Polygon - @test isapprox(GeoInterface.coordinates(geom), [[[1,4],[2,5],[3,6]]], atol=1e-6) - @test AG.toWKT(geom) == "POLYGON ((1 4,2 5,3 6))" - end - AG.createpolygon([1.,2.,3.], [4.,5.,6.], [7.,8.,9.]) do geom - @test AG.toWKT(geom) == "POLYGON ((1 4 7,2 5 8,3 6 9))" - AG.closerings!(geom) - @test AG.toWKT(geom) == "POLYGON ((1 4 7,2 5 8,3 6 9,1 4 7))" - end + @test AG.toWKT(AG.createpolygon([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])) == + "POLYGON ((1 4,2 5,3 6))" + AG.createpolygon([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]) do geom + @test GeoInterface.geotype(geom) == :Polygon + @test isapprox( + GeoInterface.coordinates(geom), + [[[1, 4], [2, 5], [3, 6]]], + atol = 1e-6, + ) + @test AG.toWKT(geom) == "POLYGON ((1 4,2 5,3 6))" + end + AG.createpolygon([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + @test AG.toWKT(geom) == "POLYGON ((1 4 7,2 5 8,3 6 9))" + AG.closerings!(geom) + @test AG.toWKT(geom) == "POLYGON ((1 4 7,2 5 8,3 6 9,1 4 7))" + end - @test AG.toWKT(AG.createmultipoint([1.,2.,3.], [4.,5.,6.])) == "MULTIPOINT (1 4,2 5,3 6)" - AG.createmultipoint([1.,2.,3.], [4.,5.,6.]) do geom - @test GeoInterface.geotype(geom) == :MultiPoint - @test isapprox(GeoInterface.coordinates(geom), [[1,4],[2,5],[3,6]], atol=1e-6) - @test AG.toWKT(geom) == "MULTIPOINT (1 4,2 5,3 6)" - end - AG.createmultipoint([1.,2.,3.], [4.,5.,6.], [7.,8.,9.]) do geom - @test AG.toWKT(geom) == "MULTIPOINT (1 4 7,2 5 8,3 6 9)" - end + @test AG.toWKT(AG.createmultipoint([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])) == + "MULTIPOINT (1 4,2 5,3 6)" + AG.createmultipoint([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]) do geom + @test GeoInterface.geotype(geom) == :MultiPoint + @test isapprox( + GeoInterface.coordinates(geom), + [[1, 4], [2, 5], [3, 6]], + atol = 1e-6, + ) + @test AG.toWKT(geom) == "MULTIPOINT (1 4,2 5,3 6)" + end + AG.createmultipoint([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + @test AG.toWKT(geom) == "MULTIPOINT (1 4 7,2 5 8,3 6 9)" + end - @test AG.toWKT(AG.createmultipolygon(Vector{Vector{Tuple{Cdouble,Cdouble}}}[ - Vector{Tuple{Cdouble,Cdouble}}[ - [(0,0),(0,4),(4,4),(4,0)], - [(1,1),(1,3),(3,3),(3,1)]], - Vector{Tuple{Cdouble,Cdouble}}[ - [(10,0),(10,4),(14,4),(14,0)], - [(11,1),(11,3),(13,3),(13,1)]]] - )) == "MULTIPOLYGON (((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1)),((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" - AG.createmultipolygon(Vector{Vector{Tuple{Cdouble,Cdouble}}}[ - Vector{Tuple{Cdouble,Cdouble}}[ - [(0,0),(0,4),(4,4),(4,0)], - [(1,1),(1,3),(3,3),(3,1)]], - Vector{Tuple{Cdouble,Cdouble}}[ - [(10,0),(10,4),(14,4),(14,0)], - [(11,1),(11,3),(13,3),(13,1)]]]) do geom - @test GeoInterface.geotype(geom) == :MultiPolygon - @test isapprox( - GeoInterface.coordinates(geom), [ - [[[0,0],[0,4],[4,4],[4,0]], [[1,1],[1,3],[3,3],[3,1]]], - [[[10,0],[10,4],[14,4],[14,0]], [[11,1],[11,3],[13,3],[13,1]]] + @test AG.toWKT( + AG.createmultipolygon( + Vector{Vector{Tuple{Cdouble,Cdouble}}}[ + Vector{Tuple{Cdouble,Cdouble}}[ + [(0, 0), (0, 4), (4, 4), (4, 0)], + [(1, 1), (1, 3), (3, 3), (3, 1)], + ], + Vector{Tuple{Cdouble,Cdouble}}[ + [(10, 0), (10, 4), (14, 4), (14, 0)], + [(11, 1), (11, 3), (13, 3), (13, 1)], + ], + ], + ), + ) == + "MULTIPOLYGON (((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1)),((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" + AG.createmultipolygon( + Vector{Vector{Tuple{Cdouble,Cdouble}}}[ + Vector{Tuple{Cdouble,Cdouble}}[ + [(0, 0), (0, 4), (4, 4), (4, 0)], + [(1, 1), (1, 3), (3, 3), (3, 1)], + ], + Vector{Tuple{Cdouble,Cdouble}}[ + [(10, 0), (10, 4), (14, 4), (14, 0)], + [(11, 1), (11, 3), (13, 3), (13, 1)], + ], ], - atol=1e-6 - ) - @test AG.toWKT(geom) == "MULTIPOLYGON (((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1)),((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" - end + ) do geom + @test GeoInterface.geotype(geom) == :MultiPolygon + @test isapprox( + GeoInterface.coordinates(geom), + [ + [[[0, 0], [0, 4], [4, 4], [4, 0]], [[1, 1], [1, 3], [3, 3], [3, 1]]], + [ + [[10, 0], [10, 4], [14, 4], [14, 0]], + [[11, 1], [11, 3], [13, 3], [13, 1]], + ], + ], + atol = 1e-6, + ) + @test AG.toWKT(geom) == + "MULTIPOLYGON (((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1)),((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" + end - AG.fromWKT("CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))") do geom - @test AG.toWKT(AG.curvegeom(AG.lineargeom(geom, 0.5))) == "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" - AG.lineargeom(geom, 0.5) do lgeom - AG.curvegeom(lgeom) do clgeom - @test AG.toWKT(clgeom) == "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" - end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 - AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom - AG.polygonize(mlsgeom) do plgeom - @test AG.ngeom(plgeom) == 2 + AG.fromWKT( + "CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))", + ) do geom + @test AG.toWKT(AG.curvegeom(AG.lineargeom(geom, 0.5))) == + "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" + AG.lineargeom(geom, 0.5) do lgeom + AG.curvegeom(lgeom) do clgeom + @test AG.toWKT(clgeom) == + "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" + end + @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom + AG.polygonize(mlsgeom) do plgeom + @test AG.ngeom(plgeom) == 2 + end end end - end - @test startswith(AG.toWKT(AG.curvegeom(AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT="NO"))), "CURVEPOLYGON (CIRCULARSTRING (") - AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT="NO") do lgeom - AG.curvegeom(lgeom) do clgeom - @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") - end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 - AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom - AG.polygonize(mlsgeom) do plgeom - @test AG.ngeom(plgeom) == 2 + @test startswith( + AG.toWKT( + AG.curvegeom(AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT = "NO")), + ), + "CURVEPOLYGON (CIRCULARSTRING (", + ) + AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT = "NO") do lgeom + AG.curvegeom(lgeom) do clgeom + @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") + end + @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom + AG.polygonize(mlsgeom) do plgeom + @test AG.ngeom(plgeom) == 2 + end end end - end - @test startswith(AG.toWKT(AG.curvegeom(AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5))), "CURVEPOLYGON (CIRCULARSTRING (") - AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5) do lgeom - AG.curvegeom(lgeom) do clgeom - @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") - end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 - AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom - AG.polygonize(mlsgeom) do plgeom - @test AG.ngeom(plgeom) == 2 + @test startswith( + AG.toWKT( + AG.curvegeom(AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5)), + ), + "CURVEPOLYGON (CIRCULARSTRING (", + ) + AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5) do lgeom + AG.curvegeom(lgeom) do clgeom + @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") + end + @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom + AG.polygonize(mlsgeom) do plgeom + @test AG.ngeom(plgeom) == 2 + end end end end end -end -@testset "Testing remaining methods for geometries" begin - geom1 = AG.createmultipolygon(Vector{Vector{Tuple{Cdouble,Cdouble}}}[ - Vector{Tuple{Cdouble,Cdouble}}[ - [(0,0),(0,4),(4,4),(4,0)], - [(1,1),(1,3),(3,3),(3,1)]], - Vector{Tuple{Cdouble,Cdouble}}[ - [(10,0),(10,4),(14,4),(14,0)], - [(11,1),(11,3),(13,3),(13,1)]]]) - geom2 = AG.createmultipoint([1.,2.,3.], [4.,5.,6.], [7.,8.,9.]) + @testset "Testing remaining methods for geometries" begin + geom1 = AG.createmultipolygon( + Vector{Vector{Tuple{Cdouble,Cdouble}}}[ + Vector{Tuple{Cdouble,Cdouble}}[ + [(0, 0), (0, 4), (4, 4), (4, 0)], + [(1, 1), (1, 3), (3, 3), (3, 1)], + ], + Vector{Tuple{Cdouble,Cdouble}}[ + [(10, 0), (10, 4), (14, 4), (14, 0)], + [(11, 1), (11, 3), (13, 3), (13, 1)], + ], + ], + ) + geom2 = AG.createmultipoint([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) - AG.closerings!(geom1) - @test AG.disjoint(geom1, geom2) == false - @test AG.touches(geom1, geom2) == true - @test AG.crosses(geom1, geom2) == false - @test AG.overlaps(geom1, geom2) == false + AG.closerings!(geom1) + @test AG.disjoint(geom1, geom2) == false + @test AG.touches(geom1, geom2) == true + @test AG.crosses(geom1, geom2) == false + @test AG.overlaps(geom1, geom2) == false - @test AG.toWKT(AG.boundary(geom2)) == "GEOMETRYCOLLECTION EMPTY" - AG.boundary(geom2) do result - @test AG.toWKT(result) == "GEOMETRYCOLLECTION EMPTY" - end + @test AG.toWKT(AG.boundary(geom2)) == "GEOMETRYCOLLECTION EMPTY" + AG.boundary(geom2) do result + @test AG.toWKT(result) == "GEOMETRYCOLLECTION EMPTY" + end - @test AG.toWKT(AG.union(geom1, geom2)) == "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" - AG.union(geom1, geom2) do result - @test AG.toWKT(result) == "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" - @test AG.hascurvegeom(result, true) == false - @test AG.hascurvegeom(result, false) == false - end + @test AG.toWKT(AG.union(geom1, geom2)) == + "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + AG.union(geom1, geom2) do result + @test AG.toWKT(result) == + "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + @test AG.hascurvegeom(result, true) == false + @test AG.hascurvegeom(result, false) == false + end - @test AG.toWKT(AG.difference(geom1, geom2)) == "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" - AG.difference(geom1, geom2) do result - @test AG.toWKT(result) == "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" - AG.segmentize!(result, 20) - @test AG.toWKT(result) == "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" - AG.segmentize!(result, 2) - @test AG.toWKT(result) == "MULTIPOLYGON (((0 4 8,2 4 8,4 4 8,4 2 8,4 0 8,2 0 8,0 0 8,0 2 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,12 4 8,14 4 8,14 2 8,14 0 8,12 0 8,10 0 8,10 2 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" - end + @test AG.toWKT(AG.difference(geom1, geom2)) == + "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + AG.difference(geom1, geom2) do result + @test AG.toWKT(result) == + "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + AG.segmentize!(result, 20) + @test AG.toWKT(result) == + "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + AG.segmentize!(result, 2) + @test AG.toWKT(result) == + "MULTIPOLYGON (((0 4 8,2 4 8,4 4 8,4 2 8,4 0 8,2 0 8,0 0 8,0 2 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,12 4 8,14 4 8,14 2 8,14 0 8,12 0 8,10 0 8,10 2 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + end - @test AG.toWKT(AG.symdifference(geom1, geom2)) == "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" - AG.symdifference(geom1, geom2) do result - @test GeoInterface.geotype(result) == :GeometryCollection - @test AG.toWKT(result) == "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" - AG.removegeom!(result, 1) - @test AG.toWKT(result) == "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POINT (2 5 8),POINT (3 6 9))" - AG.removeallgeoms!(result) - @test AG.toWKT(result) == "GEOMETRYCOLLECTION EMPTY" - end + @test AG.toWKT(AG.symdifference(geom1, geom2)) == + "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + AG.symdifference(geom1, geom2) do result + @test GeoInterface.geotype(result) == :GeometryCollection + @test AG.toWKT(result) == + "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + AG.removegeom!(result, 1) + @test AG.toWKT(result) == + "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POINT (2 5 8),POINT (3 6 9))" + AG.removeallgeoms!(result) + @test AG.toWKT(result) == "GEOMETRYCOLLECTION EMPTY" + end - geom3 = AG.fromWKT("GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8,0 4 8,4 4 8,4 0 8,0 0 8),(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8)),POLYGON ((10 0 8,10 4 8,14 4 8,14 0 8,10 0 8),(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8)), POINT EMPTY)") - AG.clone(geom3) do geom4 - @test sprint(print, AG.clone(geom3)) == "Geometry: GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8, ... MPTY)" - @test sprint(print, AG.clone(geom4)) == "Geometry: GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8, ... MPTY)" - end - AG.clone(AG.getgeom(geom3, 3)) do geom4 - @test sprint(print, geom4) == "Geometry: POINT EMPTY" - end + geom3 = AG.fromWKT( + "GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8,0 4 8,4 4 8,4 0 8,0 0 8),(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8)),POLYGON ((10 0 8,10 4 8,14 4 8,14 0 8,10 0 8),(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8)), POINT EMPTY)", + ) + AG.clone(geom3) do geom4 + @test sprint(print, AG.clone(geom3)) == + "Geometry: GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8, ... MPTY)" + @test sprint(print, AG.clone(geom4)) == + "Geometry: GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8, ... MPTY)" + end + AG.clone(AG.getgeom(geom3, 3)) do geom4 + @test sprint(print, geom4) == "Geometry: POINT EMPTY" + end - @test AG.toISOWKT(geom3) == "GEOMETRYCOLLECTION Z (POINT Z (2 5 8),POLYGON Z ((0 0 8,0 4 8,4 4 8,4 0 8,0 0 8),(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8)),POLYGON Z ((10 0 8,10 4 8,14 4 8,14 0 8,10 0 8),(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8)),POINT Z EMPTY)" - AG.removegeom!(geom3, AG.ngeom(geom3)-1) # the JSON driver in GDAL 3.0 does not handle null geometries well yet - @test AG.toJSON(geom3) == """{ "type": "GeometryCollection", "geometries": [ { "type": "Point", "coordinates": [ 2.0, 5.0, 8.0 ] }, { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0, 8.0 ], [ 0.0, 4.0, 8.0 ], [ 4.0, 4.0, 8.0 ], [ 4.0, 0.0, 8.0 ], [ 0.0, 0.0, 8.0 ] ], [ [ 1.0, 1.0, 8.0 ], [ 3.0, 1.0, 8.0 ], [ 3.0, 3.0, 8.0 ], [ 1.0, 3.0, 8.0 ], [ 1.0, 1.0, 8.0 ] ] ] }, { "type": "Polygon", "coordinates": [ [ [ 10.0, 0.0, 8.0 ], [ 10.0, 4.0, 8.0 ], [ 14.0, 4.0, 8.0 ], [ 14.0, 0.0, 8.0 ], [ 10.0, 0.0, 8.0 ] ], [ [ 11.0, 1.0, 8.0 ], [ 13.0, 1.0, 8.0 ], [ 13.0, 3.0, 8.0 ], [ 11.0, 3.0, 8.0 ], [ 11.0, 1.0, 8.0 ] ] ] } ] }""" + @test AG.toISOWKT(geom3) == + "GEOMETRYCOLLECTION Z (POINT Z (2 5 8),POLYGON Z ((0 0 8,0 4 8,4 4 8,4 0 8,0 0 8),(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8)),POLYGON Z ((10 0 8,10 4 8,14 4 8,14 0 8,10 0 8),(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8)),POINT Z EMPTY)" + AG.removegeom!(geom3, AG.ngeom(geom3) - 1) # the JSON driver in GDAL 3.0 does not handle null geometries well yet + @test AG.toJSON(geom3) == + """{ "type": "GeometryCollection", "geometries": [ { "type": "Point", "coordinates": [ 2.0, 5.0, 8.0 ] }, { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0, 8.0 ], [ 0.0, 4.0, 8.0 ], [ 4.0, 4.0, 8.0 ], [ 4.0, 0.0, 8.0 ], [ 0.0, 0.0, 8.0 ] ], [ [ 1.0, 1.0, 8.0 ], [ 3.0, 1.0, 8.0 ], [ 3.0, 3.0, 8.0 ], [ 1.0, 3.0, 8.0 ], [ 1.0, 1.0, 8.0 ] ] ] }, { "type": "Polygon", "coordinates": [ [ [ 10.0, 0.0, 8.0 ], [ 10.0, 4.0, 8.0 ], [ 14.0, 4.0, 8.0 ], [ 14.0, 0.0, 8.0 ], [ 10.0, 0.0, 8.0 ] ], [ [ 11.0, 1.0, 8.0 ], [ 13.0, 1.0, 8.0 ], [ 13.0, 3.0, 8.0 ], [ 11.0, 3.0, 8.0 ], [ 11.0, 1.0, 8.0 ] ] ] } ] }""" - AG.createmultilinestring([[[1.,4.], [2.,5.], [3.,6.], [1.,4.]]]) do geom4 - @test AG.toWKT(geom4) == "MULTILINESTRING ((1 4,2 5,3 6,1 4))" - @test AG.toWKT(AG.polygonfromedges(geom4, 0.1)) == "POLYGON ((1 4,2 5,3 6,1 4))" - AG.polygonfromedges(geom4, 0.1) do geom5 - @test AG.toWKT(geom5) == "POLYGON ((1 4,2 5,3 6,1 4))" + AG.createmultilinestring([[ + [1.0, 4.0], + [2.0, 5.0], + [3.0, 6.0], + [1.0, 4.0], + ]]) do geom4 + @test AG.toWKT(geom4) == "MULTILINESTRING ((1 4,2 5,3 6,1 4))" + @test AG.toWKT(AG.polygonfromedges(geom4, 0.1)) == "POLYGON ((1 4,2 5,3 6,1 4))" + AG.polygonfromedges(geom4, 0.1) do geom5 + @test AG.toWKT(geom5) == "POLYGON ((1 4,2 5,3 6,1 4))" + end end - end - - @test AG.getgeomtype(AG.getgeom(geom3, 0)) == AG.wkbPoint25D - @test AG.getgeomtype(AG.getgeom(geom3, 1)) == AG.wkbPolygon25D - @test AG.getgeomtype(AG.getgeom(geom3, 2)) == AG.wkbPolygon25D - @test sprint(print, AG.getgeom(geom3, 3)) == "NULL Geometry" - @test sprint(print, AG.getgeom(AG.IGeometry(), 3)) == "NULL Geometry" - AG.getgeom(geom3, 0) do geom4 - @test AG.getgeomtype(geom4) == AG.wkbPoint25D - end - AG.getgeom(geom3, 1) do geom4 - @test AG.getgeomtype(geom4) == AG.wkbPolygon25D - end - AG.getgeom(geom3, 2) do geom4 - @test AG.getgeomtype(geom4) == AG.wkbPolygon25D - end - AG.getgeom(geom3, 3) do geom4 - @test sprint(print, geom4) == "NULL Geometry" - end - AG.getgeom(AG.IGeometry(), 0) do geom - @test sprint(print, geom) == "NULL Geometry" - end -end -@testset "Spatial Reference Systems" begin - @test sprint(print, AG.getspatialref(AG.IGeometry())) == "NULL Spatial Reference System" - AG.getspatialref(AG.IGeometry()) do spatialref - @test sprint(print, spatialref) == "NULL Spatial Reference System" + @test AG.getgeomtype(AG.getgeom(geom3, 0)) == AG.wkbPoint25D + @test AG.getgeomtype(AG.getgeom(geom3, 1)) == AG.wkbPolygon25D + @test AG.getgeomtype(AG.getgeom(geom3, 2)) == AG.wkbPolygon25D + @test sprint(print, AG.getgeom(geom3, 3)) == "NULL Geometry" + @test sprint(print, AG.getgeom(AG.IGeometry(), 3)) == "NULL Geometry" + AG.getgeom(geom3, 0) do geom4 + @test AG.getgeomtype(geom4) == AG.wkbPoint25D + end + AG.getgeom(geom3, 1) do geom4 + @test AG.getgeomtype(geom4) == AG.wkbPolygon25D + end + AG.getgeom(geom3, 2) do geom4 + @test AG.getgeomtype(geom4) == AG.wkbPolygon25D + end + AG.getgeom(geom3, 3) do geom4 + @test sprint(print, geom4) == "NULL Geometry" + end + AG.getgeom(AG.IGeometry(), 0) do geom + @test sprint(print, geom) == "NULL Geometry" + end end - AG.createpoint(100,70,0) do geom - @test sprint(print, AG.getspatialref(geom)) == "NULL Spatial Reference System" - AG.getspatialref(geom) do spatialref + @testset "Spatial Reference Systems" begin + @test sprint(print, AG.getspatialref(AG.IGeometry())) == + "NULL Spatial Reference System" + AG.getspatialref(AG.IGeometry()) do spatialref @test sprint(print, spatialref) == "NULL Spatial Reference System" end - end - AG.read("data/point.geojson") do dataset - layer = AG.getlayer(dataset, 0) - AG.nextfeature(layer) do feature - geom = AG.getgeom(feature) - @test AG.toPROJ4(AG.getspatialref(geom)) == "+proj=longlat +datum=WGS84 +no_defs" + AG.createpoint(100, 70, 0) do geom + @test sprint(print, AG.getspatialref(geom)) == "NULL Spatial Reference System" AG.getspatialref(geom) do spatialref - @test AG.toPROJ4(spatialref) == "+proj=longlat +datum=WGS84 +no_defs" + @test sprint(print, spatialref) == "NULL Spatial Reference System" end end - AG.createpoint(1,2) do point - @test sprint(print, AG.getspatialref(point)) == "NULL Spatial Reference System" - AG.getspatialref(point) do spatialref - @test sprint(print, spatialref) == "NULL Spatial Reference System" + + AG.read("data/point.geojson") do dataset + layer = AG.getlayer(dataset, 0) + AG.nextfeature(layer) do feature + geom = AG.getgeom(feature) + @test AG.toPROJ4(AG.getspatialref(geom)) == + "+proj=longlat +datum=WGS84 +no_defs" + AG.getspatialref(geom) do spatialref + @test AG.toPROJ4(spatialref) == "+proj=longlat +datum=WGS84 +no_defs" + end + end + AG.createpoint(1, 2) do point + @test sprint(print, AG.getspatialref(point)) == + "NULL Spatial Reference System" + AG.getspatialref(point) do spatialref + @test sprint(print, spatialref) == "NULL Spatial Reference System" + end end end - end - AG.importEPSG(2927) do source; AG.importEPSG(4326) do target - AG.createcoordtrans(source, target) do transform - AG.fromWKT("POINT (1120351.57 741921.42)") do point - @test AG.toWKT(point) == "POINT (1120351.57 741921.42)" - AG.transform!(point, transform) - @test GeoInterface.coordinates(point) ≈ [47.3488070138318, -122.5981499431438] - end end end end -end + AG.importEPSG(2927) do source + AG.importEPSG(4326) do target + AG.createcoordtrans(source, target) do transform + AG.fromWKT("POINT (1120351.57 741921.42)") do point + @test AG.toWKT(point) == "POINT (1120351.57 741921.42)" + AG.transform!(point, transform) + @test GeoInterface.coordinates(point) ≈ + [47.3488070138318, -122.5981499431438] + end + end + end + end + end -@testset "Cloning NULL geometries" begin - geom = AG.IGeometry() - @test sprint(print, AG.clone(geom)) == "NULL Geometry" - AG.clone(geom) do g - @test sprint(print, g) == "NULL Geometry" + @testset "Cloning NULL geometries" begin + geom = AG.IGeometry() + @test sprint(print, AG.clone(geom)) == "NULL Geometry" + AG.clone(geom) do g + @test sprint(print, g) == "NULL Geometry" + end end -end end diff --git a/test/test_geos_operations.jl b/test/test_geos_operations.jl index 2e64eb84..559739a1 100644 --- a/test/test_geos_operations.jl +++ b/test/test_geos_operations.jl @@ -1,225 +1,238 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_geos_operations.jl" begin -function equivalent_to_wkt(geom::AG.Geometry, wkt::String) - fromWKT(wkt) do test_geom - @test toWKT(geom) == toWKT(test_geom) + function equivalent_to_wkt(geom::AG.Geometry, wkt::String) + fromWKT(wkt) do test_geom + @test toWKT(geom) == toWKT(test_geom) + end end -end -@testset "Interpolation along a LineString" begin - AG.createlinestring([(8.,1.),(9.,1.),(9.,2.),(8.,2.)]) do ls - for (dist,dest) in [(1.0,(9,1)), (2.0,(9,2)), - (1.5,(9.0,1.5)),(2.5,(8.5,2.0))] - AG.pointalongline(ls, dist) do pt1 - AG.createpoint(dest) do pt2 - @test AG.toWKT(pt1) == AG.toWKT(pt2) + @testset "Interpolation along a LineString" begin + AG.createlinestring([(8.0, 1.0), (9.0, 1.0), (9.0, 2.0), (8.0, 2.0)]) do ls + for (dist, dest) in + [(1.0, (9, 1)), (2.0, (9, 2)), (1.5, (9.0, 1.5)), (2.5, (8.5, 2.0))] + AG.pointalongline(ls, dist) do pt1 + AG.createpoint(dest) do pt2 + @test AG.toWKT(pt1) == AG.toWKT(pt2) + end + end + @test AG.toWKT(AG.pointalongline(ls, dist)) == + AG.toWKT(AG.createpoint(dest)) end - end - @test AG.toWKT(AG.pointalongline(ls, dist)) == AG.toWKT(AG.createpoint(dest)) end end -end - -@testset "Contains operation" begin - AG.fromWKT("POLYGON EMPTY") do g1 - AG.fromWKT("POLYGON EMPTY") do g2 - @test AG.contains(g1, g2) == false - @test AG.contains(g2, g1) == false - end - end - AG.fromWKT("POLYGON((1 1,1 5,5 5,5 1,1 1))") do g1 - AG.fromWKT("POINT(2 2)") do g2 - @test AG.contains(g1, g2) == true - @test AG.contains(g2, g1) == false - end - end + @testset "Contains operation" begin + AG.fromWKT("POLYGON EMPTY") do g1 + AG.fromWKT("POLYGON EMPTY") do g2 + @test AG.contains(g1, g2) == false + @test AG.contains(g2, g1) == false + end + end - AG.fromWKT("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))") do g1 - AG.fromWKT("POLYGON((1 1,1 2,2 2,2 1,1 1))") do g2 - @test AG.contains(g1, g2) == true - @test AG.contains(g2, g1) == false - end - end -end + AG.fromWKT("POLYGON((1 1,1 5,5 5,5 1,1 1))") do g1 + AG.fromWKT("POINT(2 2)") do g2 + @test AG.contains(g1, g2) == true + @test AG.contains(g2, g1) == false + end + end -@testset "Convex Hull" begin - AG.fromWKT("MULTIPOINT (130 240, 130 240, 130 240, 570 240, 570 240, 570 240, 650 240)") do input - AG.fromWKT("LINESTRING (130 240, 650 240)") do expected - AG.convexhull(input) do output - @test AG.isempty(output) == false - @test AG.toWKT(output) == AG.toWKT(expected) + AG.fromWKT("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))") do g1 + AG.fromWKT("POLYGON((1 1,1 2,2 2,2 1,1 1))") do g2 + @test AG.contains(g1, g2) == true + @test AG.contains(g2, g1) == false + end end - @test AG.toWKT(AG.convexhull(input)) == AG.toWKT(expected) - end end -end -@testset "Delaunay Triangulation" begin - AG.fromWKT("POLYGON EMPTY") do g1 - AG.delaunaytriangulation(g1,0,true) do g2 - @test AG.isempty(g1) == true - @test AG.isempty(g2) == true - @test AG.toWKT(g2) == "MULTILINESTRING EMPTY" + @testset "Convex Hull" begin + AG.fromWKT( + "MULTIPOINT (130 240, 130 240, 130 240, 570 240, 570 240, 570 240, 650 240)", + ) do input + AG.fromWKT("LINESTRING (130 240, 650 240)") do expected + AG.convexhull(input) do output + @test AG.isempty(output) == false + @test AG.toWKT(output) == AG.toWKT(expected) + end + @test AG.toWKT(AG.convexhull(input)) == AG.toWKT(expected) + end end - @test AG.toWKT(AG.delaunaytriangulation(g1,0,true)) == "MULTILINESTRING EMPTY" end - AG.fromWKT("POINT(0 0)") do g1 - AG.delaunaytriangulation(g1,0,false) do g2 - @test AG.isempty(g2) == true - @test AG.toWKT(g2) == "GEOMETRYCOLLECTION EMPTY" + + @testset "Delaunay Triangulation" begin + AG.fromWKT("POLYGON EMPTY") do g1 + AG.delaunaytriangulation(g1, 0, true) do g2 + @test AG.isempty(g1) == true + @test AG.isempty(g2) == true + @test AG.toWKT(g2) == "MULTILINESTRING EMPTY" + end + @test AG.toWKT(AG.delaunaytriangulation(g1, 0, true)) == "MULTILINESTRING EMPTY" end - @test AG.toWKT(AG.delaunaytriangulation(g1,0,false)) == "GEOMETRYCOLLECTION EMPTY" - end - AG.fromWKT("MULTIPOINT(0 0, 5 0, 10 0)") do g1 - AG.delaunaytriangulation(g1,0,false) do g2 - @test AG.toWKT(g2) == "GEOMETRYCOLLECTION EMPTY" + AG.fromWKT("POINT(0 0)") do g1 + AG.delaunaytriangulation(g1, 0, false) do g2 + @test AG.isempty(g2) == true + @test AG.toWKT(g2) == "GEOMETRYCOLLECTION EMPTY" + end + @test AG.toWKT(AG.delaunaytriangulation(g1, 0, false)) == + "GEOMETRYCOLLECTION EMPTY" end - AG.delaunaytriangulation(g1,0,true) do g2 - @test AG.toWKT(g2) == "MULTILINESTRING ((5 0,10 0),(0 0,5 0))" + AG.fromWKT("MULTIPOINT(0 0, 5 0, 10 0)") do g1 + AG.delaunaytriangulation(g1, 0, false) do g2 + @test AG.toWKT(g2) == "GEOMETRYCOLLECTION EMPTY" + end + AG.delaunaytriangulation(g1, 0, true) do g2 + @test AG.toWKT(g2) == "MULTILINESTRING ((5 0,10 0),(0 0,5 0))" + end end - end - AG.fromWKT("MULTIPOINT(0 0, 10 0, 10 10, 11 10)") do g1 - AG.delaunaytriangulation(g1,2.0,true) do g2 - @test AG.toWKT(g2) == "MULTILINESTRING ((0 0,10 10),(0 0,10 0),(10 0,10 10))" + AG.fromWKT("MULTIPOINT(0 0, 10 0, 10 10, 11 10)") do g1 + AG.delaunaytriangulation(g1, 2.0, true) do g2 + @test AG.toWKT(g2) == + "MULTILINESTRING ((0 0,10 10),(0 0,10 0),(10 0,10 10))" + end end end -end -@testset "Distance" begin - AG.fromWKT("POINT(10 10)") do g1 - AG.fromWKT("POINT(3 6)") do g2 - @test AG.distance(g1, g2) ≈ 8.06225774829855 atol=1e-12 - end + @testset "Distance" begin + AG.fromWKT("POINT(10 10)") do g1 + AG.fromWKT("POINT(3 6)") do g2 + @test AG.distance(g1, g2) ≈ 8.06225774829855 atol = 1e-12 + end + end end -end -function test_method(f::Function, wkt1::AbstractString, wkt2::AbstractString) - AG.fromWKT(wkt1) do geom - f(geom) do result - @test AG.toWKT(result) == wkt2 + function test_method(f::Function, wkt1::AbstractString, wkt2::AbstractString) + AG.fromWKT(wkt1) do geom + f(geom) do result + @test AG.toWKT(result) == wkt2 + end + @test AG.toWKT(f(geom)) == wkt2 end - @test AG.toWKT(f(geom)) == wkt2 end -end -@testset "Centroid" begin - test_method(AG.centroid, "POINT(10 0)", "POINT (10 0)") - test_method(AG.centroid, "LINESTRING(0 0, 10 0)", "POINT (5 0)") - test_method(AG.centroid, "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", "POINT (5 5)") - test_method(AG.centroid, "LINESTRING EMPTY", "POINT EMPTY") -end - -@testset "Point on Surface" begin - test_method(AG.pointonsurface, "POINT(10 0)", "POINT (10 0)") - test_method(AG.pointonsurface, "LINESTRING(0 0, 5 0, 10 0)", "POINT (5 0)") - test_method(AG.pointonsurface, "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", "POINT (5 5)") - test_method(AG.pointonsurface, "LINESTRING EMPTY", "POINT EMPTY") - test_method(AG.pointonsurface, "LINESTRING(0 0, 0 0)", "POINT (0 0)") -end - -function test_method(f::Function, wkt1::AbstractString, - wkt2::AbstractString, wkt3::AbstractString) - AG.fromWKT(wkt1) do geom1 - AG.fromWKT(wkt2) do geom2 - f(geom1, geom2) do result - @test AG.toWKT(result) == wkt3 + @testset "Centroid" begin + test_method(AG.centroid, "POINT(10 0)", "POINT (10 0)") + test_method(AG.centroid, "LINESTRING(0 0, 10 0)", "POINT (5 0)") + test_method(AG.centroid, "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", "POINT (5 5)") + test_method(AG.centroid, "LINESTRING EMPTY", "POINT EMPTY") + end + + @testset "Point on Surface" begin + test_method(AG.pointonsurface, "POINT(10 0)", "POINT (10 0)") + test_method(AG.pointonsurface, "LINESTRING(0 0, 5 0, 10 0)", "POINT (5 0)") + test_method( + AG.pointonsurface, + "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", + "POINT (5 5)", + ) + test_method(AG.pointonsurface, "LINESTRING EMPTY", "POINT EMPTY") + test_method(AG.pointonsurface, "LINESTRING(0 0, 0 0)", "POINT (0 0)") + end + + function test_method( + f::Function, + wkt1::AbstractString, + wkt2::AbstractString, + wkt3::AbstractString, + ) + AG.fromWKT(wkt1) do geom1 + AG.fromWKT(wkt2) do geom2 + f(geom1, geom2) do result + @test AG.toWKT(result) == wkt3 + end + @test AG.toWKT(f(geom1, geom2)) == wkt3 + end end - @test AG.toWKT(f(geom1, geom2)) == wkt3 - end end -end -@testset "Intersection" begin - test_method(AG.intersection, - "POLYGON EMPTY", - "POLYGON EMPTY", - "POLYGON EMPTY") - test_method(AG.intersection, - "POLYGON((1 1,1 5,5 5,5 1,1 1))", - "POINT(2 2)", - "POINT (2 2)") - test_method(AG.intersection, - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", - "POLYGON((-1 1,-1 2,2 2,2 1,-1 1))", - "POLYGON ((0 2,2 2,2 1,0 1,0 2))") - test_method(AG.intersection, - "MULTIPOLYGON(((0 0,5 10,10 0,0 0),(1 1,1 2,2 2,2 1,1 1),(100 100,100 102,102 102,102 100,100 100)))", - "POLYGON((0 1,0 2,10 2,10 1,0 1))", - "GEOMETRYCOLLECTION (POLYGON ((0.5 1.0,1 2,1 1,0.5 1.0)),POLYGON ((2 2,9 2,9.5 1.0,2 1,2 2)),LINESTRING (2 1,1 1),LINESTRING (1 2,2 2))") -end - -function test_predicate(f::Function, wkt1, wkt2, result::Bool) - AG.fromWKT(wkt1) do geom1 - AG.fromWKT(wkt2) do geom2 - @test f(geom1, geom2) == result - end + @testset "Intersection" begin + test_method(AG.intersection, "POLYGON EMPTY", "POLYGON EMPTY", "POLYGON EMPTY") + test_method( + AG.intersection, + "POLYGON((1 1,1 5,5 5,5 1,1 1))", + "POINT(2 2)", + "POINT (2 2)", + ) + test_method( + AG.intersection, + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + "POLYGON((-1 1,-1 2,2 2,2 1,-1 1))", + "POLYGON ((0 2,2 2,2 1,0 1,0 2))", + ) + test_method( + AG.intersection, + "MULTIPOLYGON(((0 0,5 10,10 0,0 0),(1 1,1 2,2 2,2 1,1 1),(100 100,100 102,102 102,102 100,100 100)))", + "POLYGON((0 1,0 2,10 2,10 1,0 1))", + "GEOMETRYCOLLECTION (POLYGON ((0.5 1.0,1 2,1 1,0.5 1.0)),POLYGON ((2 2,9 2,9.5 1.0,2 1,2 2)),LINESTRING (2 1,1 1),LINESTRING (1 2,2 2))", + ) + end + + function test_predicate(f::Function, wkt1, wkt2, result::Bool) + AG.fromWKT(wkt1) do geom1 + AG.fromWKT(wkt2) do geom2 + @test f(geom1, geom2) == result + end + end end -end - -@testset "Intersects" begin - test_predicate(AG.intersects, - "POLYGON EMPTY", - "POLYGON EMPTY", - false) - test_predicate(AG.intersects, - "POLYGON((1 1,1 5,5 5,5 1,1 1))", - "POINT(2 2)", - true) - test_predicate(AG.intersects, - "POINT(2 2)", - "POLYGON((1 1,1 5,5 5,5 1,1 1))", - true) - test_predicate(AG.intersects, - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", - "POLYGON((1 1,1 2,2 2,2 1,1 1))", - true) - test_predicate(AG.intersects, - "POLYGON((1 1,1 2,2 2,2 1,1 1))", - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", - true) -end - -@testset "Within" begin - test_predicate(AG.within, - "POLYGON EMPTY", - "POLYGON EMPTY", - false) - test_predicate(AG.within, - "POLYGON((1 1,1 5,5 5,5 1,1 1))", - "POINT(2 2)", - false) - test_predicate(AG.within, - "POINT(2 2)", - "POLYGON((1 1,1 5,5 5,5 1,1 1))", - true) - test_predicate(AG.within, - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", - "POLYGON((1 1,1 2,2 2,2 1,1 1))", - false) - test_predicate(AG.within, - "POLYGON((1 1,1 2,2 2,2 1,1 1))", - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", - true) -end -@testset "Simplify" begin - AG.fromWKT("POLYGON((56.528666666700 25.2101666667, 56.529000000000 25.2105000000, 56.528833333300 25.2103333333, 56.528666666700 25.2101666667))") do g1 - AG.simplify(g1, 0.0) do g2 - @test AG.toWKT(g2) == "POLYGON EMPTY" + @testset "Intersects" begin + test_predicate(AG.intersects, "POLYGON EMPTY", "POLYGON EMPTY", false) + test_predicate(AG.intersects, "POLYGON((1 1,1 5,5 5,5 1,1 1))", "POINT(2 2)", true) + test_predicate(AG.intersects, "POINT(2 2)", "POLYGON((1 1,1 5,5 5,5 1,1 1))", true) + test_predicate( + AG.intersects, + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + "POLYGON((1 1,1 2,2 2,2 1,1 1))", + true, + ) + test_predicate( + AG.intersects, + "POLYGON((1 1,1 2,2 2,2 1,1 1))", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + true, + ) + end + + @testset "Within" begin + test_predicate(AG.within, "POLYGON EMPTY", "POLYGON EMPTY", false) + test_predicate(AG.within, "POLYGON((1 1,1 5,5 5,5 1,1 1))", "POINT(2 2)", false) + test_predicate(AG.within, "POINT(2 2)", "POLYGON((1 1,1 5,5 5,5 1,1 1))", true) + test_predicate( + AG.within, + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + "POLYGON((1 1,1 2,2 2,2 1,1 1))", + false, + ) + test_predicate( + AG.within, + "POLYGON((1 1,1 2,2 2,2 1,1 1))", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", + true, + ) + end + + @testset "Simplify" begin + AG.fromWKT( + "POLYGON((56.528666666700 25.2101666667, 56.529000000000 25.2105000000, 56.528833333300 25.2103333333, 56.528666666700 25.2101666667))", + ) do g1 + AG.simplify(g1, 0.0) do g2 + @test AG.toWKT(g2) == "POLYGON EMPTY" + end + @test AG.toWKT(AG.simplify(g1, 0.0)) == "POLYGON EMPTY" end - @test AG.toWKT(AG.simplify(g1, 0.0)) == "POLYGON EMPTY" - end - AG.fromWKT("POLYGON((56.528666666700 25.2101666667, 56.529000000000 25.2105000000, 56.528833333300 25.2103333333, 56.528666666700 25.2101666667))") do g1 - AG.simplifypreservetopology(g1, 43.2) do g2 - @test AG.toWKT(g2) == "POLYGON ((56.5286666667 25.2101666667,56.529 25.2105,56.5288333333 25.2103333333,56.5286666667 25.2101666667))" + AG.fromWKT( + "POLYGON((56.528666666700 25.2101666667, 56.529000000000 25.2105000000, 56.528833333300 25.2103333333, 56.528666666700 25.2101666667))", + ) do g1 + AG.simplifypreservetopology(g1, 43.2) do g2 + @test AG.toWKT(g2) == + "POLYGON ((56.5286666667 25.2101666667,56.529 25.2105,56.5288333333 25.2103333333,56.5286666667 25.2101666667))" + end + @test AG.toWKT(AG.simplifypreservetopology(g1, 43.2)) == + "POLYGON ((56.5286666667 25.2101666667,56.529 25.2105,56.5288333333 25.2103333333,56.5286666667 25.2101666667))" end - @test AG.toWKT(AG.simplifypreservetopology(g1, 43.2)) == "POLYGON ((56.5286666667 25.2101666667,56.529 25.2105,56.5288333333 25.2103333333,56.5286666667 25.2101666667))" end -end end diff --git a/test/test_geotransform.jl b/test/test_geotransform.jl index 004bb2ae..a474bee1 100644 --- a/test/test_geotransform.jl +++ b/test/test_geotransform.jl @@ -1,31 +1,21 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_geotransform.jl" begin - - f(gt, pixel, line) = [ - gt[1] + pixel * gt[2] + line * gt[3], - gt[4] + pixel * gt[5] + line * gt[6], - ] - gt1 = [ - -1111950.519667, 463.3127165279167, 0.0, - 6671703.118, 0.0, -463.3127165279165, - ] + + f(gt, pixel, line) = + [gt[1] + pixel * gt[2] + line * gt[3], gt[4] + pixel * gt[5] + line * gt[6]] + gt1 = [-1111950.519667, 463.3127165279167, 0.0, 6671703.118, 0.0, -463.3127165279165] for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) @test AG.applygeotransform(gt1, pixel, line) ≈ f(gt1, pixel, line) end gt2 = AG.invgeotransform(gt1) - @test gt2 ≈ [ - 2400.0, 0.0021583694216166533, 0.0, - 14400.0, 0.0, -0.002158369421616654, - ] + @test gt2 ≈ [2400.0, 0.0021583694216166533, 0.0, 14400.0, 0.0, -0.002158369421616654] gt3 = AG.composegeotransform(gt1, gt2) - @test gt3 ≈ [ - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - ] + @test gt3 ≈ [0.0, 1.0, 0.0, 0.0, 0.0, 1.0] for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) @test AG.applygeotransform(gt3, pixel, line) ≈ [pixel, line] diff --git a/test/test_images.jl b/test/test_images.jl index 4869650f..d479ebe5 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -1,76 +1,72 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; import ImageCore import ColorTypes @testset "test_images.jl" begin -@testset "Test Gray colors" begin - @test eltype(AG.imread("data/utmsmall.tif")) == - ColorTypes.Gray{ImageCore.N0f8} -end + @testset "Test Gray colors" begin + @test eltype(AG.imread("data/utmsmall.tif")) == ColorTypes.Gray{ImageCore.N0f8} + end -AG.read("gdalworkshop/world.tif") do dataset - @testset "Test RGB colors" begin - @test eltype(AG.imread(dataset)) == - ColorTypes.RGB{ImageCore.N0f8} + AG.read("gdalworkshop/world.tif") do dataset + @testset "Test RGB colors" begin + @test eltype(AG.imread(dataset)) == ColorTypes.RGB{ImageCore.N0f8} + end end -end -AG.create( + AG.create( AG.getdriver("MEM"), width = 2, height = 2, nbands = 4, dtype = UInt8, ) do dataset - @testset "Test RGBA colors" begin - AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_RedBand) - AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_GreenBand) - AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_BlueBand) - AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_AlphaBand) - @test eltype(AG.imread(dataset)) == - ColorTypes.RGBA{ImageCore.N0f8} - end - - @testset "Test HSL colors" begin - AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_HueBand) - AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_SaturationBand) - AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_LightnessBand) - @test_throws ErrorException AG.imread(dataset, 1:3) - end - - @testset "Test ColorTable colors" begin - AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_PaletteIndex) - AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_PaletteIndex) - AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_PaletteIndex) - AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_PaletteIndex) - - AG.createcolortable(AG.GPI_RGB) do ct - AG.setcolortable!(AG.getband(dataset, 1), ct) - AG.setcolortable!(AG.getband(dataset, 2), ct) - AG.setcolortable!(AG.getband(dataset, 3), ct) - AG.setcolortable!(AG.getband(dataset, 4), ct) + @testset "Test RGBA colors" begin + AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_RedBand) + AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_GreenBand) + AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_BlueBand) + AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_AlphaBand) + @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} end - @test eltype(AG.imread(dataset)) == - ColorTypes.RGBA{ImageCore.N0f8} - AG.createcolortable(AG.GPI_Gray) do ct - AG.setcolortable!(AG.getband(dataset, 1), ct) - AG.setcolortable!(AG.getband(dataset, 2), ct) - AG.setcolortable!(AG.getband(dataset, 3), ct) - AG.setcolortable!(AG.getband(dataset, 4), ct) + @testset "Test HSL colors" begin + AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_HueBand) + AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_SaturationBand) + AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_LightnessBand) + @test_throws ErrorException AG.imread(dataset, 1:3) end - @test eltype(AG.imread(dataset)) == - ColorTypes.Gray{ImageCore.N0f8} - AG.createcolortable(AG.GPI_CMYK) do ct # CMYK not supported yet - AG.setcolortable!(AG.getband(dataset, 1), ct) - AG.setcolortable!(AG.getband(dataset, 2), ct) - AG.setcolortable!(AG.getband(dataset, 3), ct) + @testset "Test ColorTable colors" begin + AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_PaletteIndex) + AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_PaletteIndex) + AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_PaletteIndex) + AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_PaletteIndex) + + AG.createcolortable(AG.GPI_RGB) do ct + AG.setcolortable!(AG.getband(dataset, 1), ct) + AG.setcolortable!(AG.getband(dataset, 2), ct) + AG.setcolortable!(AG.getband(dataset, 3), ct) + AG.setcolortable!(AG.getband(dataset, 4), ct) + end + @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} + + AG.createcolortable(AG.GPI_Gray) do ct + AG.setcolortable!(AG.getband(dataset, 1), ct) + AG.setcolortable!(AG.getband(dataset, 2), ct) + AG.setcolortable!(AG.getband(dataset, 3), ct) + AG.setcolortable!(AG.getband(dataset, 4), ct) + end + @test eltype(AG.imread(dataset)) == ColorTypes.Gray{ImageCore.N0f8} + + AG.createcolortable(AG.GPI_CMYK) do ct # CMYK not supported yet + AG.setcolortable!(AG.getband(dataset, 1), ct) + AG.setcolortable!(AG.getband(dataset, 2), ct) + AG.setcolortable!(AG.getband(dataset, 3), ct) + end + @test_throws ErrorException AG.imread(dataset, 1:3) end - @test_throws ErrorException AG.imread(dataset, 1:3) end -end end diff --git a/test/test_iterators.jl b/test/test_iterators.jl index c2527161..3e11e715 100644 --- a/test/test_iterators.jl +++ b/test/test_iterators.jl @@ -1,17 +1,18 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_iterators.jl" begin -@testset "Iterator interface Window Iterator" begin - ds = AG.readraster("ospy/data4/aster.img") - band = AG.getband(ds, 1) - window = AG.windows(band) - @test Base.IteratorSize(window) == Base.HasShape{2}() - @test Base.IteratorEltype(window) == Base.HasEltype() - @test eltype(window) == Tuple{UnitRange{Int},UnitRange{Int}} - @test size(window) == (79, 89) - @test length(window) == 7031 -end + @testset "Iterator interface Window Iterator" begin + ds = AG.readraster("ospy/data4/aster.img") + band = AG.getband(ds, 1) + window = AG.windows(band) + @test Base.IteratorSize(window) == Base.HasShape{2}() + @test Base.IteratorEltype(window) == Base.HasEltype() + @test eltype(window) == Tuple{UnitRange{Int},UnitRange{Int}} + @test size(window) == (79, 89) + @test length(window) == 7031 + end end diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index 1c4c1b1f..f5e936fe 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -1,469 +1,501 @@ using Test using Statistics -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_ospy_examples.jl" begin -""" -function to copy fields (not the data) from one layer to another -parameters: - fromLayer: layer object that contains the fields to copy - toLayer: layer object to copy the fields into -""" -function copyfields(fromlayer, tolayer) - featuredefn = AG.layerdefn(fromlayer) - for i in 0:(AG.nfield(featuredefn)-1) - fd = AG.getfielddefn(featuredefn, i) - if AG.gettype(fd) == OFTReal - # to deal with errors like - # ERROR: GDALError (Warning, code 1): - # Value 18740682.1600000001 of field SHAPE_AREA of - # feature 1 not successfully written. Possibly due - # to too larger number with respect to field width - fwidth = AG.getwidth(fd) - if fwidth != 0 - AG.setwidth!(fd, fwidth + 1) - end end - AG.createfield!(tolayer, fd) - end -end - -""" -function to copy attributes from one feature to another -(this assumes the features have the same attribute fields!) -parameters: - fromFeature: feature object that contains the data to copy - toFeature: feature object that the data is to be copied into -""" -function copyattributes(fromfeature, tofeature) - for i in 0:(AG.nfield(fromfeature)-1) - if AG.isfieldset(fromfeature, i) - try - AG.setfield!(tofeature, i, AG.getfield(fromfeature, i)) - catch - println(fromfeature) - println(tofeature) - println("$i: $(AG.getfield(fromfeature, i))") - end end end -end - -# function reproject(inFN, inEPSG, outEPSG) -# AG.fromEPSG(inEPSG) do inspatialref -# AG.fromEPSG(outEPSG) do outspatialref -# AG.createcoordtrans(inspatialref, outspatialref) do coordtrans -# AG.read(inFN) do inDS -# AG.create("", "MEMORY") do outDS -# inlayer = AG.getlayer(inDS, 0) -# outlayer = AG.createlayer( -# name = "outlayer", -# dataset = outDS, -# geom = AG.getgeomtype(AG.layerdefn(inlayer))) -# copyfields(inlayer, outlayer) -# featuredefn = AG.layerdefn(outlayer) -# for infeature in inlayer -# geom = AG.getgeom(infeature) -# AG.createfeature(featuredefn) do outfeature -# AG.setgeom!(outfeature, AG.transform!(geom, coordtrans)) -# copyattributes(infeature, outfeature) -# AG.createfeature(outlayer, outfeature) -# end end -# println(outlayer) -# end -# end -# end -# println(AG.toWKT(AG.morphtoESRI!(outspatialref))) -# end -# end -# end - -@testset "Homework 1" begin -AG.read("ospy/data1/sites.shp") do input - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw1a.py - for (i, feature) in enumerate(AG.getlayer(input, 0)) - id = AG.getfield(feature, 0); cover = AG.getfield(feature, 1) - (x,y) = AG.getpoint(AG.getgeom(feature, 0), 0) - @test id == i - @test 4e5 <= x <= 5e5 - @test 4.5e6 <= y <= 5e6 - @test cover in ("shrubs", "trees", "rocks", "grass", "bare", "water") + """ + function to copy fields (not the data) from one layer to another + parameters: + fromLayer: layer object that contains the fields to copy + toLayer: layer object to copy the fields into + """ + function copyfields(fromlayer, tolayer) + featuredefn = AG.layerdefn(fromlayer) + for i = 0:(AG.nfield(featuredefn)-1) + fd = AG.getfielddefn(featuredefn, i) + if AG.gettype(fd) == OFTReal + # to deal with errors like + # ERROR: GDALError (Warning, code 1): + # Value 18740682.1600000001 of field SHAPE_AREA of + # feature 1 not successfully written. Possibly due + # to too larger number with respect to field width + fwidth = AG.getwidth(fd) + if fwidth != 0 + AG.setwidth!(fd, fwidth + 1) + end + end + AG.createfield!(tolayer, fd) + end end - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw1b.py - # version 1 - AG.create(AG.getdriver("MEMORY")) do output - inlayer = AG.getlayer(input, 0) - outlayer = AG.createlayer( - name = "hw1b", - dataset = output, - geom = AG.wkbPoint - ) - inlayerdefn = AG.layerdefn(inlayer) - AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 0)) - AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 1)) - for infeature in inlayer - id = AG.getfield(infeature, 0) - @test AG.asint64(infeature, 0) == id - cover = AG.getfield(infeature, 1) - if cover == "trees" - AG.createfeature(outlayer) do outfeature - AG.setgeom!(outfeature, AG.getgeom(infeature)) - AG.setfield!(outfeature, 0, id) - AG.setfield!(outfeature, 1, cover) - end end end - @test sprint(print, output) == """ - GDAL Dataset (Driver: Memory/Memory) - File(s): - - Number of feature layers: 1 - Layer 0: hw1b (wkbPoint) - """ + """ + function to copy attributes from one feature to another + (this assumes the features have the same attribute fields!) + parameters: + fromFeature: feature object that contains the data to copy + toFeature: feature object that the data is to be copied into + """ + function copyattributes(fromfeature, tofeature) + for i = 0:(AG.nfield(fromfeature)-1) + if AG.isfieldset(fromfeature, i) + try + AG.setfield!(tofeature, i, AG.getfield(fromfeature, i)) + catch + println(fromfeature) + println(tofeature) + println("$i: $(AG.getfield(fromfeature, i))") + end + end + end end - # version 2 - AG.create(AG.getdriver("MEMORY")) do output - AG.executesql(input, """SELECT id, cover FROM sites - WHERE cover = 'trees' """) do results - @test sprint(print, results) == """ - Layer: sites - Geometry 0 (): [wkbPoint], POINT (449959.840851...), ... - Field 0 (id): [OFTInteger], 2, 6, 9, 14, 19, 20, 22, 26, 34, 36, 41 - Field 1 (cover): [OFTString], trees, trees, trees, trees, trees, trees, ... - """ - AG.copy(results, name = "hw1b", dataset = output) - end - @test sprint(print, output) == """ - GDAL Dataset (Driver: Memory/Memory) - File(s): + # function reproject(inFN, inEPSG, outEPSG) + # AG.fromEPSG(inEPSG) do inspatialref + # AG.fromEPSG(outEPSG) do outspatialref + # AG.createcoordtrans(inspatialref, outspatialref) do coordtrans + # AG.read(inFN) do inDS + # AG.create("", "MEMORY") do outDS + # inlayer = AG.getlayer(inDS, 0) + # outlayer = AG.createlayer( + # name = "outlayer", + # dataset = outDS, + # geom = AG.getgeomtype(AG.layerdefn(inlayer))) + # copyfields(inlayer, outlayer) + # featuredefn = AG.layerdefn(outlayer) + # for infeature in inlayer + # geom = AG.getgeom(infeature) + # AG.createfeature(featuredefn) do outfeature + # AG.setgeom!(outfeature, AG.transform!(geom, coordtrans)) + # copyattributes(infeature, outfeature) + # AG.createfeature(outlayer, outfeature) + # end end + # println(outlayer) + # end + # end + # end + # println(AG.toWKT(AG.morphtoESRI!(outspatialref))) + # end + # end + # end + + @testset "Homework 1" begin + AG.read("ospy/data1/sites.shp") do input + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw1a.py + for (i, feature) in enumerate(AG.getlayer(input, 0)) + id = AG.getfield(feature, 0) + cover = AG.getfield(feature, 1) + (x, y) = AG.getpoint(AG.getgeom(feature, 0), 0) + @test id == i + @test 4e5 <= x <= 5e5 + @test 4.5e6 <= y <= 5e6 + @test cover in ("shrubs", "trees", "rocks", "grass", "bare", "water") + end - Number of feature layers: 1 - Layer 0: hw1b (wkbPoint) - """ - end -end -end - -@testset "Homework 2" begin - # http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw2a.py - open("ospy/data2/ut_counties.txt", "r") do file - AG.create(AG.getdriver("MEMORY")) do output - layer = AG.createlayer( - name = "hw2a", - dataset = output, - geom = AG.wkbPolygon - ) - @test sprint(print, layer) == """ - Layer: hw2a - Geometry 0 (): [wkbPolygon] - """ - AG.createfielddefn("name", AG.OFTString) do fielddefn - AG.setwidth!(fielddefn, 30) - AG.addfielddefn!(layer, fielddefn) - end - @test sprint(print, layer) == """ - Layer: hw2a - Geometry 0 (): [wkbPolygon] - Field 0 (name): [OFTString] - """ - for line in readlines(file) - (name, coords) = split(line, ":") - coordlist = split(coords, ",") - AG.createfeature(layer) do feature - AG.setfield!(feature, 0, name) - AG.createpolygon() do poly - ring = AG.createlinearring() - for xy in map(split, coordlist) - AG.addpoint!(ring, parse(Float64, xy[1]), - parse(Float64, xy[2])) + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw1b.py + # version 1 + AG.create(AG.getdriver("MEMORY")) do output + inlayer = AG.getlayer(input, 0) + outlayer = + AG.createlayer(name = "hw1b", dataset = output, geom = AG.wkbPoint) + inlayerdefn = AG.layerdefn(inlayer) + AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 0)) + AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 1)) + for infeature in inlayer + id = AG.getfield(infeature, 0) + @test AG.asint64(infeature, 0) == id + cover = AG.getfield(infeature, 1) + if cover == "trees" + AG.createfeature(outlayer) do outfeature + AG.setgeom!(outfeature, AG.getgeom(infeature)) + AG.setfield!(outfeature, 0, id) + AG.setfield!(outfeature, 1, cover) + end end - AG.addgeom!(poly, ring) - AG.setgeom!(feature, poly) - end end end - @test sprint(print, layer) == """ - Layer: hw2a - Geometry 0 (): [wkbPolygon], POLYGON ((-111.50278...), ... - Field 0 (name): [OFTString], Cache, Box Elder, Rich, Weber, Morgan, ... - """ - - # input = output - # # http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw2b.py - # AG.fromEPSG(4269) do inspatialref - # AG.fromEPSG(26912) do outspatialref - # AG.createcoordtrans(inspatialref, outspatialref) do coordtrans - # AG.create("", "MEMORY") do output - # inlayer = AG.getlayer(input, 0) - # outlayer = AG.createlayer( - # name = "hw2b", - # dataset = output, - # geom = AG.wkbPolygon - # ) - # infeaturedefn = AG.layerdefn(inlayer) - # nameindex = AG.findfieldindex(infeaturedefn, "name") - # fielddefn = AG.getfielddefn(infeaturedefn, nameindex) - # AG.createfield!(outlayer, fielddefn) - # for infeature in inlayer - # AG.createfeature(outlayer) do outfeature - # geom = AG.getgeom(infeature) - # AG.setgeom!(outfeature, AG.transform!(geom, coordtrans)) - # AG.setfield!(outfeature,0,AG.getfield(infeature, nameindex)) - # println(outfeature) - # end end - # println(layer) - # end - # end - # println(AG.toWKT(AG.morphtoESRI!(outspatialref))) - # end - # end - end - end -end + end + @test sprint(print, output) == """ + GDAL Dataset (Driver: Memory/Memory) + File(s): -@testset "Homework 3" begin - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw3a.py - AG.read("ospy/data1/sites.shp") do sitesDS - AG.read("ospy/data3/cache_towns.shp") do townsDS - siteslayer = AG.getlayer(sitesDS, 0) - townslayer = AG.getlayer(townsDS, 0) - AG.setattributefilter!(townslayer, "NAME = 'Nibley'") - AG.getfeature(townslayer, 0) do nibleyFeature - AG.buffer(AG.getgeom(nibleyFeature), 1500) do bufferGeom - AG.setspatialfilter!(siteslayer, bufferGeom) - @test [AG.getfield(f, "ID") for f in siteslayer] == [26] - end end end end - - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw3b.py - # commented out until https://github.com/visr/GDAL.jl/issues/30 is resolved - # for inFN in readdir("./ospy/data3/") - # if endswith(inFN, ".shp") - # reproject("./ospy/data3/$(inFN)", 26912, 4269) - # end end -end + Number of feature layers: 1 + Layer 0: hw1b (wkbPoint) + """ + end -AG.read("ospy/data4/aster.img") do ds - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw4a.py - @testset "Homework 4a" begin - AG.read("ospy/data1/sites.shp") do shp - shplayer = AG.getlayer(shp, 0) - id = AG.findfieldindex(AG.layerdefn(shplayer), "ID") - - transform = AG.getgeotransform(ds) - xOrigin = transform[1]; yOrigin = transform[4] - pixelWidth = transform[2]; pixelHeight = transform[6] - - results = fill(0, 42, 3) - for (i,feature) in enumerate(shplayer) - geom = AG.getgeom(feature) - x = AG.getx(geom, 0); y = AG.gety(geom, 0) - # compute pixel offset - xOffset = round(Int, (x - xOrigin) / pixelWidth) - yOffset = round(Int, (y - yOrigin) / pixelHeight) - # create a string to print out - @test AG.getfield(feature, id) == i - for j in 1:AG.nraster(ds) - data = AG.read(ds, j, xOffset, yOffset, 1, 1) - results[i,j] = data[1,1] + # version 2 + AG.create(AG.getdriver("MEMORY")) do output + AG.executesql( + input, + """SELECT id, cover FROM sites + WHERE cover = 'trees' """, + ) do results + @test sprint(print, results) == """ + Layer: sites + Geometry 0 (): [wkbPoint], POINT (449959.840851...), ... + Field 0 (id): [OFTInteger], 2, 6, 9, 14, 19, 20, 22, 26, 34, 36, 41 + Field 1 (cover): [OFTString], trees, trees, trees, trees, trees, trees, ... + """ + AG.copy(results, name = "hw1b", dataset = output) end + @test sprint(print, output) == """ + GDAL Dataset (Driver: Memory/Memory) + File(s): + + Number of feature layers: 1 + Layer 0: hw1b (wkbPoint) + """ end - @test maximum(results) == 100 - @test minimum(results) == 0 - @test mean(results) ≈ 64.98412698412699 - @test std(results) ≈ 22.327734905980627 end end - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw4b.py - @testset "Homework 4b" begin - @testset "version 1" begin - count = 0 - total = 0 - data = AG.read(ds, 1) - for (cols,rows) in AG.windows(AG.getband(ds, 1)) - window = data[cols, rows] - count = count + sum(window .> 0) - total = total + sum(window) + @testset "Homework 2" begin + # http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw2a.py + open("ospy/data2/ut_counties.txt", "r") do file + AG.create(AG.getdriver("MEMORY")) do output + layer = + AG.createlayer(name = "hw2a", dataset = output, geom = AG.wkbPolygon) + @test sprint(print, layer) == """ + Layer: hw2a + Geometry 0 (): [wkbPolygon] + """ + AG.createfielddefn("name", AG.OFTString) do fielddefn + AG.setwidth!(fielddefn, 30) + AG.addfielddefn!(layer, fielddefn) + end + @test sprint(print, layer) == """ + Layer: hw2a + Geometry 0 (): [wkbPolygon] + Field 0 (name): [OFTString] + """ + for line in readlines(file) + (name, coords) = split(line, ":") + coordlist = split(coords, ",") + AG.createfeature(layer) do feature + AG.setfield!(feature, 0, name) + AG.createpolygon() do poly + ring = AG.createlinearring() + for xy in map(split, coordlist) + AG.addpoint!( + ring, + parse(Float64, xy[1]), + parse(Float64, xy[2]), + ) + end + AG.addgeom!(poly, ring) + AG.setgeom!(feature, poly) + end + end + end + @test sprint(print, layer) == """ + Layer: hw2a + Geometry 0 (): [wkbPolygon], POLYGON ((-111.50278...), ... + Field 0 (name): [OFTString], Cache, Box Elder, Rich, Weber, Morgan, ... + """ + + # input = output + # # http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw2b.py + # AG.fromEPSG(4269) do inspatialref + # AG.fromEPSG(26912) do outspatialref + # AG.createcoordtrans(inspatialref, outspatialref) do coordtrans + # AG.create("", "MEMORY") do output + # inlayer = AG.getlayer(input, 0) + # outlayer = AG.createlayer( + # name = "hw2b", + # dataset = output, + # geom = AG.wkbPolygon + # ) + # infeaturedefn = AG.layerdefn(inlayer) + # nameindex = AG.findfieldindex(infeaturedefn, "name") + # fielddefn = AG.getfielddefn(infeaturedefn, nameindex) + # AG.createfield!(outlayer, fielddefn) + # for infeature in inlayer + # AG.createfeature(outlayer) do outfeature + # geom = AG.getgeom(infeature) + # AG.setgeom!(outfeature, AG.transform!(geom, coordtrans)) + # AG.setfield!(outfeature,0,AG.getfield(infeature, nameindex)) + # println(outfeature) + # end end + # println(layer) + # end + # end + # println(AG.toWKT(AG.morphtoESRI!(outspatialref))) + # end + # end end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end + end - @testset "version 2" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)...) - for (cols,rows) in AG.windows(band) - AG.rasterio!(band, buffer, rows, cols) - data = buffer[1:length(cols),1:length(rows)] - count += sum(data .> 0) - total += sum(data) + @testset "Homework 3" begin + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw3a.py + AG.read("ospy/data1/sites.shp") do sitesDS + AG.read("ospy/data3/cache_towns.shp") do townsDS + siteslayer = AG.getlayer(sitesDS, 0) + townslayer = AG.getlayer(townsDS, 0) + AG.setattributefilter!(townslayer, "NAME = 'Nibley'") + AG.getfeature(townslayer, 0) do nibleyFeature + AG.buffer(AG.getgeom(nibleyFeature), 1500) do bufferGeom + AG.setspatialfilter!(siteslayer, bufferGeom) + @test [AG.getfield(f, "ID") for f in siteslayer] == [26] + end + end end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @testset "version 3" begin - count = 0 - total = 0 - # BufferIterator uses a single buffer, so this loop cannot be parallelized - for data in AG.bufferwindows(AG.getband(ds, 1)) - count += sum(data .> 0) - total += sum(data) + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw3b.py + # commented out until https://github.com/visr/GDAL.jl/issues/30 is resolved + # for inFN in readdir("./ospy/data3/") + # if endswith(inFN, ".shp") + # reproject("./ospy/data3/$(inFN)", 26912, 4269) + # end end + end + + AG.read("ospy/data4/aster.img") do ds + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw4a.py + @testset "Homework 4a" begin + AG.read("ospy/data1/sites.shp") do shp + shplayer = AG.getlayer(shp, 0) + id = AG.findfieldindex(AG.layerdefn(shplayer), "ID") + + transform = AG.getgeotransform(ds) + xOrigin = transform[1] + yOrigin = transform[4] + pixelWidth = transform[2] + pixelHeight = transform[6] + + results = fill(0, 42, 3) + for (i, feature) in enumerate(shplayer) + geom = AG.getgeom(feature) + x = AG.getx(geom, 0) + y = AG.gety(geom, 0) + # compute pixel offset + xOffset = round(Int, (x - xOrigin) / pixelWidth) + yOffset = round(Int, (y - yOrigin) / pixelHeight) + # create a string to print out + @test AG.getfield(feature, id) == i + for j = 1:AG.nraster(ds) + data = AG.read(ds, j, xOffset, yOffset, 1, 1) + results[i, j] = data[1, 1] + end + end + @test maximum(results) == 100 + @test minimum(results) == 0 + @test mean(results) ≈ 64.98412698412699 + @test std(results) ≈ 22.327734905980627 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - end - #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw5a.py - @testset "Homework 5a" begin - @time begin - rows = AG.height(ds); cols = AG.width(ds); bands = AG.nraster(ds) + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw4b.py + @testset "Homework 4b" begin + @testset "version 1" begin + count = 0 + total = 0 + data = AG.read(ds, 1) + for (cols, rows) in AG.windows(AG.getband(ds, 1)) + window = data[cols, rows] + count = count + sum(window .> 0) + total = total + sum(window) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - # get the band and block sizes - inband2 = AG.getband(ds, 2); inband3 = AG.getband(ds, 3) - (xbsize, ybsize) = AG.blocksize(inband2) + @testset "version 2" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)...) + for (cols, rows) in AG.windows(band) + AG.rasterio!(band, buffer, rows, cols) + data = buffer[1:length(cols), 1:length(rows)] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - buffer2 = Array{Float32}(undef, ybsize, xbsize) - buffer3 = Array{Float32}(undef, ybsize, xbsize) - ndvi = Array{Float32}(undef, ybsize, xbsize) - AG.create( + @testset "version 3" begin + count = 0 + total = 0 + # BufferIterator uses a single buffer, so this loop cannot be parallelized + for data in AG.bufferwindows(AG.getband(ds, 1)) + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end + end + + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw5a.py + @testset "Homework 5a" begin + @time begin + rows = AG.height(ds) + cols = AG.width(ds) + bands = AG.nraster(ds) + + # get the band and block sizes + inband2 = AG.getband(ds, 2) + inband3 = AG.getband(ds, 3) + (xbsize, ybsize) = AG.blocksize(inband2) + + buffer2 = Array{Float32}(undef, ybsize, xbsize) + buffer3 = Array{Float32}(undef, ybsize, xbsize) + ndvi = Array{Float32}(undef, ybsize, xbsize) + AG.create( AG.getdriver("MEM"), - width = cols, - height = rows, - nbands = 1, - dtype = Float32 + width = cols, + height = rows, + nbands = 1, + dtype = Float32, ) do outDS - for ((i,j),(nrows,ncols)) in AG.blocks(inband2) - AG.rasterio!(inband2, buffer2, j, i, ncols, nrows) - AG.rasterio!(inband3, buffer3, j, i, ncols, nrows) - data2 = buffer2[1:nrows,1:ncols] - data3 = buffer3[1:nrows,1:ncols] - for row in 1:nrows, col in 1:ncols - denominator = data2[row, col] + data3[row, col] - if denominator > 0 - numerator = data3[row, col] - data2[row, col] - ndvi[row, col] = numerator / denominator - else - ndvi[row, col] = -99 + for ((i, j), (nrows, ncols)) in AG.blocks(inband2) + AG.rasterio!(inband2, buffer2, j, i, ncols, nrows) + AG.rasterio!(inband3, buffer3, j, i, ncols, nrows) + data2 = buffer2[1:nrows, 1:ncols] + data3 = buffer3[1:nrows, 1:ncols] + for row = 1:nrows, col = 1:ncols + denominator = data2[row, col] + data3[row, col] + if denominator > 0 + numerator = data3[row, col] - data2[row, col] + ndvi[row, col] = numerator / denominator + else + ndvi[row, col] = -99 + end end + # write the data + AG.write!(outDS, ndvi, 1, j, i, ncols, nrows) end - # write the data - AG.write!(outDS, ndvi, 1, j, i, ncols, nrows) + @test sprint(print, outDS) == """ + GDAL Dataset (Driver: MEM/In Memory Raster) + File(s): + + Dataset (width x height): 5665 x 5033 (pixels) + Number of raster bands: 1 + [GA_Update] Band 1 (Undefined): 5665 x 5033 (Float32) + """ + # flush data to disk, set the NoData value and calculate stats + outband = AG.getband(outDS, 1) + @test sprint(print, outband) == """ + [GA_Update] Band 1 (Undefined): 5665 x 5033 (Float32) + blocksize: 5665×1, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + AG.setnodatavalue!(outband, -99) + # georeference the image and set the projection + AG.setgeotransform!(outDS, AG.getgeotransform(ds)) + AG.setproj!(outDS, AG.getproj(ds)) + + # build pyramids + # gdal.SetConfigOption('HFA_USE_RRD', 'YES') + # AG.buildoverviews!(outDS, + # Cint[2,4,8,16,32,64,128], # overview list + # # bandlist (omit to include all bands) + # resampling="NEAREST") # resampling method end - @test sprint(print, outDS) == """ - GDAL Dataset (Driver: MEM/In Memory Raster) - File(s): + end + end + end - Dataset (width x height): 5665 x 5033 (pixels) - Number of raster bands: 1 - [GA_Update] Band 1 (Undefined): 5665 x 5033 (Float32) - """ - # flush data to disk, set the NoData value and calculate stats - outband = AG.getband(outDS, 1) - @test sprint(print, outband) == """ - [GA_Update] Band 1 (Undefined): 5665 x 5033 (Float32) - blocksize: 5665×1, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - AG.setnodatavalue!(outband, -99) - # georeference the image and set the projection - AG.setgeotransform!(outDS, AG.getgeotransform(ds)) - AG.setproj!(outDS, AG.getproj(ds)) - - # build pyramids - # gdal.SetConfigOption('HFA_USE_RRD', 'YES') - # AG.buildoverviews!(outDS, - # Cint[2,4,8,16,32,64,128], # overview list - # # bandlist (omit to include all bands) - # resampling="NEAREST") # resampling method -end end end end - -#reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw5b.py -@testset "Homework 5b" begin - AG.read("ospy/data5/doq1.img") do ds1 - AG.read("ospy/data5/doq2.img") do ds2 - # read in doq1 and get info about it - band1 = AG.getband(ds1, 1) - rows1 = AG.height(ds1); cols1 = AG.width(ds1) - - # get the corner coordinates for doq1 - transform1 = AG.getgeotransform(ds1) - minX1 = transform1[1]; maxY1 = transform1[4] - pixelWidth1 = transform1[2]; pixelHeight1 = transform1[6] - maxX1 = minX1 + (cols1 * pixelWidth1) - minY1 = maxY1 + (rows1 * pixelHeight1) - - # read in doq2 and get info about it - band2 = AG.getband(ds2, 1) - rows2 = AG.height(ds2); cols2 = AG.width(ds2) - - # get the corner coordinates for doq1 - transform2 = AG.getgeotransform(ds2) - minX2 = transform1[1]; maxY2 = transform1[4] - pixelWidth2 = transform1[2]; pixelHeight2 = transform1[6] - maxX2 = minX2 + (cols2 * pixelWidth2) - minY2 = maxY2 + (rows2 * pixelHeight2) - - # get the corner coordinates for the output - minX = min(minX1, minX2); maxX = max(maxX1, maxX2) - minY = min(minY1, minY2); maxY = max(maxY1, maxY2) - - # get the number of rows and columns for the output - cols = round(Int, (maxX - minX) / pixelWidth1) - rows = round(Int, (maxY - minY) / abs(pixelHeight1)) - - # compute the origin (upper left) offset for doq1 - xOffset1 = round(Int, (minX1 - minX) / pixelWidth1) - yOffset1 = round(Int, (maxY1 - maxY) / pixelHeight1) - - # compute the origin (upper left) offset for doq2 - xOffset2 = round(Int, (minX2 - minX) / pixelWidth1) - yOffset2 = round(Int, (maxY2 - maxY) / pixelHeight1) - - dtype = AG.pixeltype(band1) - data1 = Array{dtype}(undef, rows, cols) - data2 = Array{dtype}(undef, rows, cols) - # create the output image - AG.create( + #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw5b.py + @testset "Homework 5b" begin + AG.read("ospy/data5/doq1.img") do ds1 + AG.read("ospy/data5/doq2.img") do ds2 + # read in doq1 and get info about it + band1 = AG.getband(ds1, 1) + rows1 = AG.height(ds1) + cols1 = AG.width(ds1) + + # get the corner coordinates for doq1 + transform1 = AG.getgeotransform(ds1) + minX1 = transform1[1] + maxY1 = transform1[4] + pixelWidth1 = transform1[2] + pixelHeight1 = transform1[6] + maxX1 = minX1 + (cols1 * pixelWidth1) + minY1 = maxY1 + (rows1 * pixelHeight1) + + # read in doq2 and get info about it + band2 = AG.getband(ds2, 1) + rows2 = AG.height(ds2) + cols2 = AG.width(ds2) + + # get the corner coordinates for doq1 + transform2 = AG.getgeotransform(ds2) + minX2 = transform1[1] + maxY2 = transform1[4] + pixelWidth2 = transform1[2] + pixelHeight2 = transform1[6] + maxX2 = minX2 + (cols2 * pixelWidth2) + minY2 = maxY2 + (rows2 * pixelHeight2) + + # get the corner coordinates for the output + minX = min(minX1, minX2) + maxX = max(maxX1, maxX2) + minY = min(minY1, minY2) + maxY = max(maxY1, maxY2) + + # get the number of rows and columns for the output + cols = round(Int, (maxX - minX) / pixelWidth1) + rows = round(Int, (maxY - minY) / abs(pixelHeight1)) + + # compute the origin (upper left) offset for doq1 + xOffset1 = round(Int, (minX1 - minX) / pixelWidth1) + yOffset1 = round(Int, (maxY1 - maxY) / pixelHeight1) + + # compute the origin (upper left) offset for doq2 + xOffset2 = round(Int, (minX2 - minX) / pixelWidth1) + yOffset2 = round(Int, (maxY2 - maxY) / pixelHeight1) + + dtype = AG.pixeltype(band1) + data1 = Array{dtype}(undef, rows, cols) + data2 = Array{dtype}(undef, rows, cols) + # create the output image + AG.create( AG.getdriver("MEM"), - width = cols, - height = rows, - nbands = 1, - dtype = AG.pixeltype(band1) + width = cols, + height = rows, + nbands = 1, + dtype = AG.pixeltype(band1), ) do dsout - # read in doq1 and write it to the output - AG.rasterio!(band1, data1, 0, 0, cols1, rows1) - AG.write!(dsout, data1, 1, xOffset1, yOffset1, cols, rows) - - # read in doq2 and write it to the output - AG.rasterio!(band2, data2, 0, 0, cols2, rows2) - AG.write!(dsout, data2, 1, xOffset2, yOffset2, cols, rows) - - @test sprint(print, dsout) == """ - GDAL Dataset (Driver: MEM/In Memory Raster) - File(s): - - Dataset (width x height): 4500 x 3000 (pixels) - Number of raster bands: 1 - [GA_Update] Band 1 (Undefined): 4500 x 3000 (UInt8) - """ - # compute statistics for the output - bandout = AG.getband(dsout, 1) - @test sprint(print, bandout) == """ - [GA_Update] Band 1 (Undefined): 4500 x 3000 (UInt8) - blocksize: 4500×1, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - - # set the geotransform and projection on the output - geotransform = [minX, pixelWidth1, 0, maxY, 0, pixelHeight1] - AG.setgeotransform!(dsout, geotransform) - AG.setproj!(dsout, AG.getproj(ds1)) - - # build pyramids for the output - # gdal.SetConfigOption('HFA_USE_RRD', 'YES') - # buildoverviews not supported for in-memory rasters - # AG.buildoverviews!(dsout, - # Cint[2,4,8,16], # overview list - # # bandlist (omit to include all bands) - # resampling="NEAREST") # resampling method -end end end end + # read in doq1 and write it to the output + AG.rasterio!(band1, data1, 0, 0, cols1, rows1) + AG.write!(dsout, data1, 1, xOffset1, yOffset1, cols, rows) + + # read in doq2 and write it to the output + AG.rasterio!(band2, data2, 0, 0, cols2, rows2) + AG.write!(dsout, data2, 1, xOffset2, yOffset2, cols, rows) + + @test sprint(print, dsout) == """ + GDAL Dataset (Driver: MEM/In Memory Raster) + File(s): + + Dataset (width x height): 4500 x 3000 (pixels) + Number of raster bands: 1 + [GA_Update] Band 1 (Undefined): 4500 x 3000 (UInt8) + """ + # compute statistics for the output + bandout = AG.getband(dsout, 1) + @test sprint(print, bandout) == """ + [GA_Update] Band 1 (Undefined): 4500 x 3000 (UInt8) + blocksize: 4500×1, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + + # set the geotransform and projection on the output + geotransform = [minX, pixelWidth1, 0, maxY, 0, pixelHeight1] + AG.setgeotransform!(dsout, geotransform) + AG.setproj!(dsout, AG.getproj(ds1)) + + # build pyramids for the output + # gdal.SetConfigOption('HFA_USE_RRD', 'YES') + # buildoverviews not supported for in-memory rasters + # AG.buildoverviews!(dsout, + # Cint[2,4,8,16], # overview list + # # bandlist (omit to include all bands) + # resampling="NEAREST") # resampling method + end + end + end + end end diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index 7de2fd27..bf5f19c9 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -1,105 +1,106 @@ using Test import GDAL -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_rasterattrtable.jl" begin -@testset "Testing Raster Attribute Tables" begin - AG.createRAT() do rat - @test AG.ncolumn(rat) == 0 - @test AG.nrow(rat) == 0 - @test AG.changesarewrittentofile(rat) == false - - AG.createcolumn!(rat, "col1", AG.GFT_Integer, AG.GFU_Generic) - @test AG.ncolumn(rat) == 1 - @test AG.columnname(rat, 0) == "col1" - @test AG.columnusage(rat, 0) == AG.GFU_Generic - @test AG.columntype(rat, 0) == AG.GFT_Integer - @test AG.findcolumnindex(rat, AG.GFU_Generic) == 0 - @test AG.findcolumnindex(rat, AG.GFU_Red) == -1 - - AG.createcolumn!(rat, "col2", AG.GFT_Real, AG.GFU_MinMax) - AG.createcolumn!(rat, "col3", AG.GFT_String, AG.GFU_PixelCount) - @test AG.ncolumn(rat) == 3 - @test AG.nrow(rat) == 0 - AG.setrowcount!(rat, 5) - @test AG.nrow(rat) == 5 - - @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Cint}(undef, 5)) == - fill(0,5) - @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Float64}(undef, 5)) == - fill(0,5) - @test AG.attributeio!(rat, AG.GF_Read, 1, 0, 5, Array{Float64}(undef, 5)) == - fill(0,5) - - @test AG.asstring(rat, 2, 0) == "0" - @test AG.asint(rat, 2, 0) == 0 - @test AG.asdouble(rat, 2, 0) == 0 - - AG.setvalue!(rat, 2, 0, "2") - @test AG.asstring(rat, 2, 0) == "2" - @test AG.asint(rat, 2, 0) == 2 - @test AG.asdouble(rat, 2, 0) == 2 - - AG.setvalue!(rat, 2, 0, 3) - @test AG.asstring(rat, 2, 0) == "3" - @test AG.asint(rat, 2, 0) == 3 - @test AG.asdouble(rat, 2, 0) == 3 - - AG.setvalue!(rat, 2, 0, 4.5) - @test AG.asstring(rat, 2, 0) == "4" - @test AG.asint(rat, 2, 0) == 4 - @test AG.asdouble(rat, 2, 0) == 4 - - @test AG.asstring(rat, 2, 1) == "0" - @test AG.asstring(rat, 2, 2) == "" - - @test AG.asstring(rat, 0, 2) == "" - @test AG.asstring(rat, 2, 2) == "" - @test AG.asstring(rat, 4, 2) == "" - AG.attributeio!(rat, AG.GF_Write, 2, 0, 5, fill("abc",5)) - @test AG.asstring(rat, 0, 2) == "abc" - @test AG.asstring(rat, 2, 2) == "abc" - @test AG.asstring(rat, 4, 2) == "abc" - - AG.clone(rat) do ratclone - @test AG.asstring(ratclone, 0, 2) == "abc" - @test AG.asstring(ratclone, 2, 2) == "abc" - @test AG.asstring(ratclone, 4, 2) == "abc" - @test AG.ncolumn(ratclone) == 3 - @test AG.nrow(ratclone) == 5 - @test AG.findcolumnindex(ratclone, AG.GFU_Generic) == 0 - @test AG.findcolumnindex(ratclone, AG.GFU_Red) == -1 - end + @testset "Testing Raster Attribute Tables" begin + AG.createRAT() do rat + @test AG.ncolumn(rat) == 0 + @test AG.nrow(rat) == 0 + @test AG.changesarewrittentofile(rat) == false - AG.setlinearbinning!(rat, 0, 10) - @test AG.getlinearbinning(rat) == (0,10) - AG.setlinearbinning!(rat, -1.5, 12.0) - @test AG.getlinearbinning(rat) == (-1.5,12.0) - - @test AG.findrowindex(rat, 0) == 0 - @test AG.findrowindex(rat, -1) == 0 - @test AG.findrowindex(rat, -1.5) == 0 - @test AG.findrowindex(rat, 7.5) == 0 - @test AG.findrowindex(rat, 12) == 1 - @test AG.findrowindex(rat, 13) == 1 - end -end + AG.createcolumn!(rat, "col1", AG.GFT_Integer, AG.GFU_Generic) + @test AG.ncolumn(rat) == 1 + @test AG.columnname(rat, 0) == "col1" + @test AG.columnusage(rat, 0) == AG.GFU_Generic + @test AG.columntype(rat, 0) == AG.GFT_Integer + @test AG.findcolumnindex(rat, AG.GFU_Generic) == 0 + @test AG.findcolumnindex(rat, AG.GFU_Red) == -1 -@testset ("Testing Color Tables") begin - AG.createcolortable(AG.GPI_RGB) do ct - @test sprint(print, ct) == "ColorTable[GPI_RGB]" - @test AG.paletteinterp(ct) == AG.GPI_RGB - AG.clone(ct) do ct1 - @test sprint(print, ct1) == "ColorTable[GPI_RGB]" - end - AG.clone(AG.ColorTable(C_NULL)) do ct2 - @test sprint(print, ct2) == "NULL ColorTable" + AG.createcolumn!(rat, "col2", AG.GFT_Real, AG.GFU_MinMax) + AG.createcolumn!(rat, "col3", AG.GFT_String, AG.GFU_PixelCount) + @test AG.ncolumn(rat) == 3 + @test AG.nrow(rat) == 0 + AG.setrowcount!(rat, 5) + @test AG.nrow(rat) == 5 + + @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Cint}(undef, 5)) == + fill(0, 5) + @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Float64}(undef, 5)) == + fill(0, 5) + @test AG.attributeio!(rat, AG.GF_Read, 1, 0, 5, Array{Float64}(undef, 5)) == + fill(0, 5) + + @test AG.asstring(rat, 2, 0) == "0" + @test AG.asint(rat, 2, 0) == 0 + @test AG.asdouble(rat, 2, 0) == 0 + + AG.setvalue!(rat, 2, 0, "2") + @test AG.asstring(rat, 2, 0) == "2" + @test AG.asint(rat, 2, 0) == 2 + @test AG.asdouble(rat, 2, 0) == 2 + + AG.setvalue!(rat, 2, 0, 3) + @test AG.asstring(rat, 2, 0) == "3" + @test AG.asint(rat, 2, 0) == 3 + @test AG.asdouble(rat, 2, 0) == 3 + + AG.setvalue!(rat, 2, 0, 4.5) + @test AG.asstring(rat, 2, 0) == "4" + @test AG.asint(rat, 2, 0) == 4 + @test AG.asdouble(rat, 2, 0) == 4 + + @test AG.asstring(rat, 2, 1) == "0" + @test AG.asstring(rat, 2, 2) == "" + + @test AG.asstring(rat, 0, 2) == "" + @test AG.asstring(rat, 2, 2) == "" + @test AG.asstring(rat, 4, 2) == "" + AG.attributeio!(rat, AG.GF_Write, 2, 0, 5, fill("abc", 5)) + @test AG.asstring(rat, 0, 2) == "abc" + @test AG.asstring(rat, 2, 2) == "abc" + @test AG.asstring(rat, 4, 2) == "abc" + + AG.clone(rat) do ratclone + @test AG.asstring(ratclone, 0, 2) == "abc" + @test AG.asstring(ratclone, 2, 2) == "abc" + @test AG.asstring(ratclone, 4, 2) == "abc" + @test AG.ncolumn(ratclone) == 3 + @test AG.nrow(ratclone) == 5 + @test AG.findcolumnindex(ratclone, AG.GFU_Generic) == 0 + @test AG.findcolumnindex(ratclone, AG.GFU_Red) == -1 + end + + AG.setlinearbinning!(rat, 0, 10) + @test AG.getlinearbinning(rat) == (0, 10) + AG.setlinearbinning!(rat, -1.5, 12.0) + @test AG.getlinearbinning(rat) == (-1.5, 12.0) + + @test AG.findrowindex(rat, 0) == 0 + @test AG.findrowindex(rat, -1) == 0 + @test AG.findrowindex(rat, -1.5) == 0 + @test AG.findrowindex(rat, 7.5) == 0 + @test AG.findrowindex(rat, 12) == 1 + @test AG.findrowindex(rat, 13) == 1 end - AG.createRAT(ct) do rat - @test sprint(print, AG.toColorTable(rat, 0)) == "ColorTable[GPI_RGB]" + end + + @testset ("Testing Color Tables") begin + AG.createcolortable(AG.GPI_RGB) do ct + @test sprint(print, ct) == "ColorTable[GPI_RGB]" + @test AG.paletteinterp(ct) == AG.GPI_RGB + AG.clone(ct) do ct1 + @test sprint(print, ct1) == "ColorTable[GPI_RGB]" + end + AG.clone(AG.ColorTable(C_NULL)) do ct2 + @test sprint(print, ct2) == "NULL ColorTable" + end + AG.createRAT(ct) do rat + @test sprint(print, AG.toColorTable(rat, 0)) == "ColorTable[GPI_RGB]" + end end end -end end diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index c34fc044..963f7644 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -1,146 +1,140 @@ using Test import GDAL -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_rasterband.jl" begin -@testset "Test methods for rasterband" begin - AG.read("data/utmsmall.tif") do dataset - ds_result = """ - GDAL Dataset (Driver: GTiff/GeoTIFF) - File(s): - data/utmsmall.tif + @testset "Test methods for rasterband" begin + AG.read("data/utmsmall.tif") do dataset + ds_result = """ + GDAL Dataset (Driver: GTiff/GeoTIFF) + File(s): + data/utmsmall.tif - Dataset (width x height): 100 x 100 (pixels) - Number of raster bands: 1 - [GA_ReadOnly] Band 1 (Gray): 100 x 100 (UInt8) - """ - @test sprint(print, dataset) == ds_result - rb = AG.getband(dataset, 1) - sprint(print, rb) == """ - [GA_ReadOnly] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: -1.0e10, units: 1.0px + 0.0 - overviews: """ - @test sprint(print, AG.getdataset(rb)) == ds_result + Dataset (width x height): 100 x 100 (pixels) + Number of raster bands: 1 + [GA_ReadOnly] Band 1 (Gray): 100 x 100 (UInt8) + """ + @test sprint(print, dataset) == ds_result + rb = AG.getband(dataset, 1) + sprint(print, rb) == """ + [GA_ReadOnly] Band 1 (Gray): 100 x 100 (UInt8) + blocksize: 100×81, nodata: -1.0e10, units: 1.0px + 0.0 + overviews: """ + @test sprint(print, AG.getdataset(rb)) == ds_result - @test AG.getunittype(rb) == "" - AG.setunittype!(rb,"ft") - @test AG.getunittype(rb) == "ft" - AG.setunittype!(rb,"") - @test AG.getunittype(rb) == "" + @test AG.getunittype(rb) == "" + AG.setunittype!(rb, "ft") + @test AG.getunittype(rb) == "ft" + AG.setunittype!(rb, "") + @test AG.getunittype(rb) == "" - @test AG.getoffset(rb) == 0 - AG.setoffset!(rb, 10) - @test AG.getoffset(rb) ≈ 10 - AG.setoffset!(rb, 0) - @test AG.getoffset(rb) ≈ 0 + @test AG.getoffset(rb) == 0 + AG.setoffset!(rb, 10) + @test AG.getoffset(rb) ≈ 10 + AG.setoffset!(rb, 0) + @test AG.getoffset(rb) ≈ 0 - @test AG.getscale(rb) == 1 - AG.setscale!(rb, 0.5) - @test AG.getscale(rb) ≈ 0.5 - AG.setscale!(rb, 2) - @test AG.getscale(rb) ≈ 2 - AG.setscale!(rb, 1) - @test AG.getscale(rb) ≈ 1 + @test AG.getscale(rb) == 1 + AG.setscale!(rb, 0.5) + @test AG.getscale(rb) ≈ 0.5 + AG.setscale!(rb, 2) + @test AG.getscale(rb) ≈ 2 + AG.setscale!(rb, 1) + @test AG.getscale(rb) ≈ 1 - @test isnothing(AG.getnodatavalue(rb)) - AG.setnodatavalue!(rb, -100) - @test AG.getnodatavalue(rb) ≈ -100 - AG.deletenodatavalue!(rb) - @test isnothing(AG.getnodatavalue(rb)) + @test isnothing(AG.getnodatavalue(rb)) + AG.setnodatavalue!(rb, -100) + @test AG.getnodatavalue(rb) ≈ -100 + AG.deletenodatavalue!(rb) + @test isnothing(AG.getnodatavalue(rb)) - AG.copy(dataset) do dest - destband = AG.getband(dest, 1) - AG.copywholeraster!(rb, destband) - @test sprint(print, destband) == """ - [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - @test AG.noverview(destband) == 0 - AG.buildoverviews!(dest, Cint[2, 4, 8]) - @test AG.noverview(destband) == 3 - @test sprint(print, destband) == """ - [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 - overviews: (0) 50x50 (1) 25x25 (2) 13x13 - """ - @test AG.getcolorinterp(destband) == AG.GCI_GrayIndex - AG.setcolorinterp!(destband, AG.GCI_RedBand) - @test AG.getcolorinterp(destband) == AG.GCI_RedBand + AG.copy(dataset) do dest + destband = AG.getband(dest, 1) + AG.copywholeraster!(rb, destband) + @test sprint(print, destband) == """ + [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + @test AG.noverview(destband) == 0 + AG.buildoverviews!(dest, Cint[2, 4, 8]) + @test AG.noverview(destband) == 3 + @test sprint(print, destband) == """ + [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + overviews: (0) 50x50 (1) 25x25 (2) 13x13 + """ + @test AG.getcolorinterp(destband) == AG.GCI_GrayIndex + AG.setcolorinterp!(destband, AG.GCI_RedBand) + @test AG.getcolorinterp(destband) == AG.GCI_RedBand - @test sprint(print, AG.sampleoverview(destband, 100)) == """ - [GA_Update] Band 1 (Gray): 13 x 13 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - @test sprint(print, AG.sampleoverview(destband, 200)) == """ - [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - @test sprint(print, AG.sampleoverview(destband, 500)) == """ - [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - AG.sampleoverview(destband, 1000) do result - @test sprint(print, result) == """ - [GA_Update] Band 1 (Gray): 50 x 50 (UInt8) + @test sprint(print, AG.sampleoverview(destband, 100)) == """ + [GA_Update] Band 1 (Gray): 13 x 13 (UInt8) blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 overviews: """ - end - @test sprint(print, AG.getmaskband(destband)) == """ - [GA_ReadOnly] Band 0 (Undefined): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 - overviews: """ - @test AG.maskflags(destband) == 1 - @test AG.maskflaginfo(rb) == ( - all_valid = true, - per_dataset = false, - alpha = false, - nodata = false - ) - AG.createmaskband!(destband, 3) - AG.getmaskband(destband) do maskband - @test sprint(print, maskband) == """ - [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) + @test sprint(print, AG.sampleoverview(destband, 200)) == """ + [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + @test sprint(print, AG.sampleoverview(destband, 500)) == """ + [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + AG.sampleoverview(destband, 1000) do result + @test sprint(print, result) == """ + [GA_Update] Band 1 (Gray): 50 x 50 (UInt8) + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + end + @test sprint(print, AG.getmaskband(destband)) == """ + [GA_ReadOnly] Band 0 (Undefined): 100 x 100 (UInt8) blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: """ - end - @test AG.maskflags(destband) == 3 - @test AG.maskflaginfo(destband) == ( - all_valid = true, - per_dataset = true, - alpha = false, - nodata = false - ) - AG.fillraster!(destband, 3) - AG.setcategorynames!(destband, ["foo", "bar"]) - @test AG.getcategorynames(destband) == ["foo", "bar"] + @test AG.maskflags(destband) == 1 + @test AG.maskflaginfo(rb) == + (all_valid = true, per_dataset = false, alpha = false, nodata = false) + AG.createmaskband!(destband, 3) + AG.getmaskband(destband) do maskband + @test sprint(print, maskband) == """ + [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + overviews: """ + end + @test AG.maskflags(destband) == 3 + @test AG.maskflaginfo(destband) == + (all_valid = true, per_dataset = true, alpha = false, nodata = false) + AG.fillraster!(destband, 3) + AG.setcategorynames!(destband, ["foo", "bar"]) + @test AG.getcategorynames(destband) == ["foo", "bar"] - AG.getoverview(destband, 0) do overview - AG.regenerateoverviews!(destband, [ - overview, - AG.getoverview(destband, 2) - ]) - end + AG.getoverview(destband, 0) do overview + AG.regenerateoverviews!( + destband, + [overview, AG.getoverview(destband, 2)], + ) + end - AG.createRAT() do rat - AG.setdefaultRAT!(destband, rat) - @test AG.getdefaultRAT(destband).ptr != rat.ptr - end - @test AG.getdefaultRAT(destband).ptr != GDAL.GDALRasterAttributeTableH(C_NULL) + AG.createRAT() do rat + AG.setdefaultRAT!(destband, rat) + @test AG.getdefaultRAT(destband).ptr != rat.ptr + end + @test AG.getdefaultRAT(destband).ptr != + GDAL.GDALRasterAttributeTableH(C_NULL) - AG.getcolortable(destband) do ct - @test ct.ptr == GDAL.GDALColorTableH(C_NULL) - end - AG.createcolortable(AG.GPI_RGB) do ct - @test ct.ptr != GDAL.GDALColorTableH(C_NULL) - AG.setcolortable!(destband, ct) - end - AG.clearcolortable!(destband) - AG.getcolortable(destband) do ct - @test ct.ptr == GDAL.GDALColorTableH(C_NULL) + AG.getcolortable(destband) do ct + @test ct.ptr == GDAL.GDALColorTableH(C_NULL) + end + AG.createcolortable(AG.GPI_RGB) do ct + @test ct.ptr != GDAL.GDALColorTableH(C_NULL) + AG.setcolortable!(destband, ct) + end + AG.clearcolortable!(destband) + AG.getcolortable(destband) do ct + @test ct.ptr == GDAL.GDALColorTableH(C_NULL) + end end end end -end end diff --git a/test/test_rasterio.jl b/test/test_rasterio.jl index 4dc87e5b..d1d658aa 100644 --- a/test/test_rasterio.jl +++ b/test/test_rasterio.jl @@ -1,234 +1,246 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_rasterio.jl" begin -AG.read("ospy/data4/aster.img") do ds - @testset "version 1" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) - for (cols,rows) in AG.windows(band) - AG.rasterio!(ds, buffer, [1], rows, cols) - data = buffer[1:length(cols), 1:length(rows)] - count += sum(data .> 0) - total += sum(data) + AG.read("ospy/data4/aster.img") do ds + @testset "version 1" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) + for (cols, rows) in AG.windows(band) + AG.rasterio!(ds, buffer, [1], rows, cols) + data = buffer[1:length(cols), 1:length(rows)] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "version 2" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) - for (cols,rows) in AG.windows(band) - AG.read!(ds, buffer, [1], rows, cols) - data = buffer[1:length(cols), 1:length(rows)] - count += sum(data .> 0) - total += sum(data) + @testset "version 2" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) + for (cols, rows) in AG.windows(band) + AG.read!(ds, buffer, [1], rows, cols) + data = buffer[1:length(cols), 1:length(rows)] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "version 3" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - buffer = Matrix{AG.pixeltype(band)}(undef, AG.blocksize(band)...) - for (cols,rows) in AG.windows(band) - AG.read!(ds, buffer, 1, rows, cols) - data = buffer[1:length(cols),1:length(rows)] - count += sum(data .> 0) - total += sum(data) + @testset "version 3" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + buffer = Matrix{AG.pixeltype(band)}(undef, AG.blocksize(band)...) + for (cols, rows) in AG.windows(band) + AG.read!(ds, buffer, 1, rows, cols) + data = buffer[1:length(cols), 1:length(rows)] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "version 4" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - buffer = Matrix{AG.pixeltype(band)}(undef, AG.blocksize(band)...) - for (cols,rows) in AG.windows(band) - AG.read!(band, buffer, rows, cols) - data = buffer[1:length(cols),1:length(rows)] - count += sum(data .> 0) - total += sum(data) + @testset "version 4" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + buffer = Matrix{AG.pixeltype(band)}(undef, AG.blocksize(band)...) + for (cols, rows) in AG.windows(band) + AG.read!(band, buffer, rows, cols) + data = buffer[1:length(cols), 1:length(rows)] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "version 5" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - xbsize, ybsize = AG.blocksize(band) - buffer = Matrix{AG.pixeltype(band)}(undef, ybsize, xbsize) - for ((i,j),(nrows,ncols)) in AG.blocks(band) - # AG.rasterio!(ds,buffer,[1],i,j,nrows,ncols) - # AG.read!(band, buffer, j, i, ncols, nrows) - AG.readblock!(band, j, i, buffer) - data = buffer[1:nrows, 1:ncols] - count += sum(data .> 0) - total += sum(data) + @testset "version 5" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + xbsize, ybsize = AG.blocksize(band) + buffer = Matrix{AG.pixeltype(band)}(undef, ybsize, xbsize) + for ((i, j), (nrows, ncols)) in AG.blocks(band) + # AG.rasterio!(ds,buffer,[1],i,j,nrows,ncols) + # AG.read!(band, buffer, j, i, ncols, nrows) + AG.readblock!(band, j, i, buffer) + data = buffer[1:nrows, 1:ncols] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "version 6" begin - band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) - AG.rasterio!(ds, buffer, [1]) - count = sum(buffer .> 0) - total = sum(buffer) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end + @testset "version 6" begin + band = AG.getband(ds, 1) + buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) + AG.rasterio!(ds, buffer, [1]) + count = sum(buffer .> 0) + total = sum(buffer) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - @testset "version 7" begin - band = AG.getband(ds, 1) - buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) - AG.read!(band, buffer) - count = sum(buffer .> 0) - total = sum(buffer) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end + @testset "version 7" begin + band = AG.getband(ds, 1) + buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) + AG.read!(band, buffer) + count = sum(buffer .> 0) + total = sum(buffer) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - @testset "version 8" begin - band = AG.getband(ds, 1) - buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) - AG.read!(ds, buffer, 1) - count = sum(buffer .> 0) - total = sum(buffer) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end + @testset "version 8" begin + band = AG.getband(ds, 1) + buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) + AG.read!(ds, buffer, 1) + count = sum(buffer .> 0) + total = sum(buffer) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - @testset "version 9" begin - band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) - AG.read!(ds, buffer, [1]) - count = sum(buffer .> 0) - total = sum(buffer) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end + @testset "version 9" begin + band = AG.getband(ds, 1) + buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) + AG.read!(ds, buffer, [1]) + count = sum(buffer .> 0) + total = sum(buffer) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - @testset "version 10" begin - band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 3) - AG.read!(ds, buffer) - count = sum(buffer[:,:,1] .> 0) - total = sum(buffer[:,:,1]) - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end + @testset "version 10" begin + band = AG.getband(ds, 1) + buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 3) + AG.read!(ds, buffer) + count = sum(buffer[:, :, 1] .> 0) + total = sum(buffer[:, :, 1]) + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + end - # check for calling with Tuple - @testset "version 11" begin - band = AG.getband(ds, 1) - count = 0 - total = 0 - buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) - for (cols,rows) in AG.windows(band) - AG.rasterio!(ds, buffer, (1,), rows, cols) - data = buffer[1:length(cols),1:length(rows)] - count += sum(data .> 0) - total += sum(data) + # check for calling with Tuple + @testset "version 11" begin + band = AG.getband(ds, 1) + count = 0 + total = 0 + buffer = Array{AG.pixeltype(band)}(undef, AG.blocksize(band)..., 1) + for (cols, rows) in AG.windows(band) + AG.rasterio!(ds, buffer, (1,), rows, cols) + data = buffer[1:length(cols), 1:length(rows)] + count += sum(data .> 0) + total += sum(data) + end + @test total / count ≈ 76.33891347095299 + @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 end - @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 - end - @testset "buffer size" begin - @test size(AG.read(ds, 1, 0, 0, 20, 10)) === (20, 10) - @test size(AG.read(ds, [1, 3], 0, 0, 20, 10)) === (20, 10, 2) - @test size(AG.read(ds, 1, 1:10, 31:50)) === (20, 10) - @test size(AG.read(ds, [1, 3], 1:10, 31:50)) === (20, 10, 2) - @test size(AG.read(ds, 1:2)) == (5665, 5033, 2) - band = AG.getband(ds, 1) - @test size(AG.read( band, 0, 0, 20, 10)) === (20, 10) - end + @testset "buffer size" begin + @test size(AG.read(ds, 1, 0, 0, 20, 10)) === (20, 10) + @test size(AG.read(ds, [1, 3], 0, 0, 20, 10)) === (20, 10, 2) + @test size(AG.read(ds, 1, 1:10, 31:50)) === (20, 10) + @test size(AG.read(ds, [1, 3], 1:10, 31:50)) === (20, 10, 2) + @test size(AG.read(ds, 1:2)) == (5665, 5033, 2) + band = AG.getband(ds, 1) + @test size(AG.read(band, 0, 0, 20, 10)) === (20, 10) + end - @testset "Writing to buffers" begin - band = AG.getband(ds, 1) - @test AG.pixeltype(band) == UInt8 - xbsize, ybsize = AG.blocksize(band) - AG.create( - AG.getdriver("MEM"), - width = AG.width(band), - height = AG.height(band), - nbands = 2, - dtype = AG.pixeltype(band) - ) do dsout - bandout = AG.getband(dsout, 1) - - @testset "writeblock!(rb::RasterBand, xoffset, yoffset, buffer)" begin - # We write everything to typemax(UInt8) - for ((i,j),(nrows,ncols)) in AG.blocks(bandout) - AG.writeblock!(bandout, j, i, fill(typemax(UInt8), ncols, nrows)) + @testset "Writing to buffers" begin + band = AG.getband(ds, 1) + @test AG.pixeltype(band) == UInt8 + xbsize, ybsize = AG.blocksize(band) + AG.create( + AG.getdriver("MEM"), + width = AG.width(band), + height = AG.height(band), + nbands = 2, + dtype = AG.pixeltype(band), + ) do dsout + bandout = AG.getband(dsout, 1) + + @testset "writeblock!(rb::RasterBand, xoffset, yoffset, buffer)" begin + # We write everything to typemax(UInt8) + for ((i, j), (nrows, ncols)) in AG.blocks(bandout) + AG.writeblock!(bandout, j, i, fill(typemax(UInt8), ncols, nrows)) + end + buffer = AG.read(bandout) + nnzero = sum(buffer .> 0) + @test nnzero == AG.height(bandout) * AG.width(bandout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + for ((i, j), (nrows, ncols)) in AG.blocks(bandout) + AG.writeblock!(bandout, j, i, fill(0x00, ncols, nrows)) + end + @test sum(AG.read(bandout) .> 0) == 0 end - buffer = AG.read(bandout) - nnzero = sum(buffer .> 0) - @test nnzero == AG.height(bandout) * AG.width(bandout) - @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) - - # Now we write everything to 0 - for ((i,j),(nrows,ncols)) in AG.blocks(bandout) - AG.writeblock!(bandout, j, i, fill(0x00, ncols, nrows)) - end - @test sum(AG.read(bandout) .> 0) == 0 - end - @testset "write!(rb::RasterBand, buffer::Matrix[, rows, cols])" begin - # We write everything to typemax(UInt8) - AG.write!(bandout, fill(typemax(UInt8), AG.height(bandout), AG.width(bandout))) - buffer = AG.read(bandout) - nnzero = sum(buffer .> 0) - @test nnzero == AG.height(bandout) * AG.width(bandout) - @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) - - # Now we write everything to 0 - AG.write!(bandout, fill(0x00, AG.height(bandout), AG.width(bandout))) - @test sum(AG.read(bandout) .> 0) == 0 - end + @testset "write!(rb::RasterBand, buffer::Matrix[, rows, cols])" begin + # We write everything to typemax(UInt8) + AG.write!( + bandout, + fill(typemax(UInt8), AG.height(bandout), AG.width(bandout)), + ) + buffer = AG.read(bandout) + nnzero = sum(buffer .> 0) + @test nnzero == AG.height(bandout) * AG.width(bandout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + AG.write!(bandout, fill(0x00, AG.height(bandout), AG.width(bandout))) + @test sum(AG.read(bandout) .> 0) == 0 + end - @testset "write!(dataset::Dataset, buffer::Matrix, i::Integer[, rows, cols])" begin - # We write everything to typemax(UInt8) - AG.write!(dsout, fill(typemax(UInt8), AG.height(bandout), AG.width(bandout)), 1) - buffer = AG.read(bandout) - nnzero = sum(buffer .> 0) - @test nnzero == AG.height(bandout) * AG.width(bandout) - @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) - - # Now we write everything to 0 - AG.write!(dsout, fill(0x00, AG.height(bandout), AG.width(bandout)), 1) - @test sum(AG.read(bandout) .> 0) == 0 - end + @testset "write!(dataset::Dataset, buffer::Matrix, i::Integer[, rows, cols])" begin + # We write everything to typemax(UInt8) + AG.write!( + dsout, + fill(typemax(UInt8), AG.height(bandout), AG.width(bandout)), + 1, + ) + buffer = AG.read(bandout) + nnzero = sum(buffer .> 0) + @test nnzero == AG.height(bandout) * AG.width(bandout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + AG.write!(dsout, fill(0x00, AG.height(bandout), AG.width(bandout)), 1) + @test sum(AG.read(bandout) .> 0) == 0 + end - @testset "write!(dataset::Dataset, buffer::Array, indices[, rows, cols])" begin - # We write everything to typemax(UInt8) - AG.write!(dsout, fill(typemax(UInt8), AG.height(dsout), AG.width(dsout), 2), 1:2) - buffer = AG.read(dsout) - nnzero = sum(buffer .> 0) - @test nnzero == 2 * AG.height(dsout) * AG.width(dsout) - @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) - - # Now we write everything to 0 - AG.write!(dsout, fill(0x00, AG.height(dsout), AG.width(dsout), 2), 1:2) - @test sum(AG.read(dsout) .> 0) == 0 + @testset "write!(dataset::Dataset, buffer::Array, indices[, rows, cols])" begin + # We write everything to typemax(UInt8) + AG.write!( + dsout, + fill(typemax(UInt8), AG.height(dsout), AG.width(dsout), 2), + 1:2, + ) + buffer = AG.read(dsout) + nnzero = sum(buffer .> 0) + @test nnzero == 2 * AG.height(dsout) * AG.width(dsout) + @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) + + # Now we write everything to 0 + AG.write!(dsout, fill(0x00, AG.height(dsout), AG.width(dsout), 2), 1:2) + @test sum(AG.read(dsout) .> 0) == 0 + end end end - end -end + end end diff --git a/test/test_spatialref.jl b/test/test_spatialref.jl index 0ef94f9c..28361dbb 100644 --- a/test/test_spatialref.jl +++ b/test/test_spatialref.jl @@ -1,83 +1,28 @@ using Test -import ArchGDAL; const AG = ArchGDAL -import GeoFormatTypes; const GFT = GeoFormatTypes +import ArchGDAL; +const AG = ArchGDAL; +import GeoFormatTypes; +const GFT = GeoFormatTypes; @testset "test_spatialref.jl" begin -@testset "Test Formats for Spatial Reference Systems" begin - proj4326 = "+proj=longlat +datum=WGS84 +no_defs" - proj26912 = "+proj=utm +zone=12 +datum=NAD83 +units=m +no_defs" - wkt4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" - wkt26912 = "PROJCS[\"NAD83 / UTM zone 12N\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-111],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"26912\"]]" - esri4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433],AXIS[\"Longitude\",EAST],AXIS[\"Latitude\",NORTH]]" - esri26912 = "PROJCS[\"NAD83 / UTM zone 12N\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-111],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]" - xml4326 = """ - GCS_WGS_1984 - - - ellipsoidal - - 6402 - - - - Geodetic latitude - - 9901 - - Lat - north - - - - - Geodetic longitude - - 9902 - - Lon - east - - - - - - - D_WGS_1984 - - - Greenwich - - 0 - - - - - - WGS_1984 - 6378137 - - 298.257223563 - - - - - - - """ - xml26912 = """ - NAD_1983_UTM_Zone_12N - - - GCS_North_American_1983 + @testset "Test Formats for Spatial Reference Systems" begin + proj4326 = "+proj=longlat +datum=WGS84 +no_defs" + proj26912 = "+proj=utm +zone=12 +datum=NAD83 +units=m +no_defs" + wkt4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" + wkt26912 = "PROJCS[\"NAD83 / UTM zone 12N\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-111],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"26912\"]]" + esri4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433],AXIS[\"Longitude\",EAST],AXIS[\"Latitude\",NORTH]]" + esri26912 = "PROJCS[\"NAD83 / UTM zone 12N\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-111],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]" + xml4326 = """ + GCS_WGS_1984 - + ellipsoidal 6402 - + Geodetic latitude 9901 @@ -87,7 +32,7 @@ import GeoFormatTypes; const GFT = GeoFormatTypes - + Geodetic longitude 9902 @@ -99,10 +44,10 @@ import GeoFormatTypes; const GFT = GeoFormatTypes - - D_North_American_1983 + + D_WGS_1984 - + Greenwich 0 @@ -110,157 +55,224 @@ import GeoFormatTypes; const GFT = GeoFormatTypes - - GRS_1980 + + WGS_1984 6378137 - 298.257222101 + 298.257223563 - - - - Transverse_Mercator - - - 0 - - - - -111 - - - - 0.9996 - - - - 500000 - - - - 0 - - - - - - - Cartesian - - 4400 - - - - Easting - - 9906 - - E - east - - - - - Northing - - 9907 - - N - north - - - - - - """ + """ + xml26912 = """ + NAD_1983_UTM_Zone_12N + + + GCS_North_American_1983 + + + ellipsoidal + + 6402 + + + + Geodetic latitude + + 9901 + + Lat + north + + + + + Geodetic longitude + + 9902 + + Lon + east + + + + + + + D_North_American_1983 + + + Greenwich + + 0 + + + + + + GRS_1980 + 6378137 + + 298.257222101 + + + + + + + + + + Transverse_Mercator + + + 0 + + + + -111 + + + + 0.9996 + + + + 500000 + + + + 0 + + + + + + + Cartesian + + 4400 + + + + Easting + + 9906 + + E + east + + + + + Northing + + 9907 + + N + north + + + + + + """ - @testset "PROJ4 Format" begin - AG.importPROJ4(proj4326) do spatialref - spatialref2 = AG.importPROJ4(proj26912) - @test AG.toPROJ4(spatialref2) == proj26912 - AG.importPROJ4!(spatialref2, AG.toPROJ4(spatialref)) - @test AG.toPROJ4(spatialref2) == proj4326 + @testset "PROJ4 Format" begin + AG.importPROJ4(proj4326) do spatialref + spatialref2 = AG.importPROJ4(proj26912) + @test AG.toPROJ4(spatialref2) == proj26912 + AG.importPROJ4!(spatialref2, AG.toPROJ4(spatialref)) + @test AG.toPROJ4(spatialref2) == proj4326 + end end - end - @testset "WKT Format" begin - AG.importWKT(wkt4326) do spatialref - spatialref2 = AG.importWKT(wkt26912) - @test AG.toWKT(spatialref2) == wkt26912 - AG.importWKT!(spatialref2, AG.toWKT(spatialref)) - @test AG.toWKT(spatialref2) == wkt4326 + @testset "WKT Format" begin + AG.importWKT(wkt4326) do spatialref + spatialref2 = AG.importWKT(wkt26912) + @test AG.toWKT(spatialref2) == wkt26912 + AG.importWKT!(spatialref2, AG.toWKT(spatialref)) + @test AG.toWKT(spatialref2) == wkt4326 + end end - end - @testset "ESRI Format" begin - AG.importESRI(esri4326) do spatialref - spatialref2 = AG.importESRI(esri26912) - @test AG.toWKT(spatialref2) == esri26912 - AG.importESRI!(spatialref2, AG.toWKT(spatialref)) - @test AG.toWKT(spatialref2) == esri4326 + @testset "ESRI Format" begin + AG.importESRI(esri4326) do spatialref + spatialref2 = AG.importESRI(esri26912) + @test AG.toWKT(spatialref2) == esri26912 + AG.importESRI!(spatialref2, AG.toWKT(spatialref)) + @test AG.toWKT(spatialref2) == esri4326 + end end - end - @testset "XML Format" begin - AG.importXML(xml4326) do spatialref - spatialref2 = AG.importXML(xml26912) - @test startswith(AG.toXML(spatialref2), "= v"1.6.0-" - @testset "URL Import" begin - url4326 = "http://spatialreference.org/ref/epsg/4326/ogcwkt/" - wkt4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" - urlsample = "http://spatialreference.org/ref/epsg/2039/esriwkt/" - wktsample = "PROJCS[\"Israel / Israeli TM Grid\",GEOGCS[\"Israel\",DATUM[\"Israel_1993\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6141\"]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",31.7343936111111],PARAMETER[\"central_meridian\",35.2045169444444],PARAMETER[\"scale_factor\",1.0000067],PARAMETER[\"false_easting\",219529.584],PARAMETER[\"false_northing\",626907.39],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]" - AG.importURL(url4326) do spatialref - spatialref2 = AG.importURL(urlsample) - @test AG.toWKT(spatialref2) == wktsample - AG.importURL!(spatialref2, url4326) - @test AG.toWKT(spatialref2) == wkt4326 + if VERSION >= v"1.6.0-" + @testset "URL Import" begin + url4326 = "http://spatialreference.org/ref/epsg/4326/ogcwkt/" + wkt4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" + urlsample = "http://spatialreference.org/ref/epsg/2039/esriwkt/" + wktsample = "PROJCS[\"Israel / Israeli TM Grid\",GEOGCS[\"Israel\",DATUM[\"Israel_1993\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6141\"]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",31.7343936111111],PARAMETER[\"central_meridian\",35.2045169444444],PARAMETER[\"scale_factor\",1.0000067],PARAMETER[\"false_easting\",219529.584],PARAMETER[\"false_northing\",626907.39],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]" + AG.importURL(url4326) do spatialref + spatialref2 = AG.importURL(urlsample) + @test AG.toWKT(spatialref2) == wktsample + AG.importURL!(spatialref2, url4326) + @test AG.toWKT(spatialref2) == wkt4326 + end end end - end - @testset "generic importCRS" begin - @test AG.toWKT(AG.importCRS(GFT.WellKnownText(GFT.CRS(), wkt4326))) == AG.toWKT(AG.importWKT(wkt4326)) - @test AG.toWKT(AG.importCRS(GFT.ESRIWellKnownText(GFT.CRS(), wkt4326))) == AG.toWKT(AG.importESRI(wkt4326)) - @test AG.toWKT(AG.importCRS(GFT.ProjString(proj4326))) == AG.toWKT(AG.importPROJ4(proj4326)) - @test AG.toWKT(AG.importCRS(GFT.EPSG(4326))) == AG.toWKT(AG.importEPSG(4326)) - @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :trad)) == AG.toWKT(AG.importEPSG(4326)) - @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :compliant)) == AG.toWKT(AG.importEPSG(4326)) - @test AG.toWKT(AG.importCRS(GFT.GML(xml4326))) == AG.toWKT(AG.importXML(xml4326)) - @test AG.toWKT(AG.importCRS(GFT.KML(""))) == AG.toWKT(AG.importEPSG(4326)) - @test_throws ArgumentError AG.importCRS(GFT.EPSG(4326), order = :unknown) + @testset "generic importCRS" begin + @test AG.toWKT(AG.importCRS(GFT.WellKnownText(GFT.CRS(), wkt4326))) == + AG.toWKT(AG.importWKT(wkt4326)) + @test AG.toWKT(AG.importCRS(GFT.ESRIWellKnownText(GFT.CRS(), wkt4326))) == + AG.toWKT(AG.importESRI(wkt4326)) + @test AG.toWKT(AG.importCRS(GFT.ProjString(proj4326))) == + AG.toWKT(AG.importPROJ4(proj4326)) + @test AG.toWKT(AG.importCRS(GFT.EPSG(4326))) == AG.toWKT(AG.importEPSG(4326)) + @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :trad)) == + AG.toWKT(AG.importEPSG(4326)) + @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :compliant)) == + AG.toWKT(AG.importEPSG(4326)) + @test AG.toWKT(AG.importCRS(GFT.GML(xml4326))) == + AG.toWKT(AG.importXML(xml4326)) + @test AG.toWKT(AG.importCRS(GFT.KML(""))) == AG.toWKT(AG.importEPSG(4326)) + @test_throws ArgumentError AG.importCRS(GFT.EPSG(4326), order = :unknown) + end end -end -@testset "Cloning NULL SRS" begin - @test sprint(print, AG.clone(AG.ISpatialRef())) == "NULL Spatial Reference System" - AG.clone(AG.ISpatialRef()) do spatialref - @test sprint(print, spatialref) == "NULL Spatial Reference System" + @testset "Cloning NULL SRS" begin + @test sprint(print, AG.clone(AG.ISpatialRef())) == "NULL Spatial Reference System" + AG.clone(AG.ISpatialRef()) do spatialref + @test sprint(print, spatialref) == "NULL Spatial Reference System" + end end -end -@testset "Getting and Setting Attribute Values" begin - AG.importEPSG(4326) do spatialref - @test AG.toWKT(spatialref) == "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" - @test sprint(print, spatialref) == "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" - AG.setattrvalue!(spatialref, "GEOGCS|AUTHORITY|EPSG") # tests seems to be broken in gdal 3.0 - @test AG.toWKT(spatialref) == "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" - AG.setattrvalue!(spatialref, "GEOGCS|NEWATTRIBUTE", "7031") # tests seems to be broken in gdal 3.0 - @test AG.toWKT(spatialref) == "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" - @test AG.getattrvalue(spatialref, "AUTHORITY", 0) == "EPSG" - @test AG.getattrvalue(spatialref, "AUTHORITY", 1) == "4326" + @testset "Getting and Setting Attribute Values" begin + AG.importEPSG(4326) do spatialref + @test AG.toWKT(spatialref) == + "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" + @test sprint(print, spatialref) == + "Spatial Reference System: +proj=longlat +datum=WGS84 +no_defs" + AG.setattrvalue!(spatialref, "GEOGCS|AUTHORITY|EPSG") # tests seems to be broken in gdal 3.0 + @test AG.toWKT(spatialref) == + "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" + AG.setattrvalue!(spatialref, "GEOGCS|NEWATTRIBUTE", "7031") # tests seems to be broken in gdal 3.0 + @test AG.toWKT(spatialref) == + "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" + @test AG.getattrvalue(spatialref, "AUTHORITY", 0) == "EPSG" + @test AG.getattrvalue(spatialref, "AUTHORITY", 1) == "4326" + end end -end end diff --git a/test/test_styletable.jl b/test/test_styletable.jl index f6d2aeab..6b2df874 100644 --- a/test/test_styletable.jl +++ b/test/test_styletable.jl @@ -1,72 +1,77 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_styletable.jl" begin -@testset "Testing StyleTable Methods" begin - AG.createstylemanager() do sm - @test AG.initialize!(sm) == true - @test AG.npart(sm) == 0 - @test AG.initialize!(sm, "PEN(w:2px,c:#000000,id:\"mapinfo-pen-2,ogr-pen-0\")") == true - AG.getpart(sm, 0) do st - @test AG.getstylestring(st) == "PEN(w:2px,c:#000000,id:\"mapinfo-pen-2,ogr-pen-0\")" - @test AG.toRGBA(st, "#123456") == (18, 52, 86, 255) - end - @test AG.npart(sm) == 1 - @test AG.addstyle!(sm, "name1", "style1") == false - @test AG.npart(sm) == 1 - @test AG.addstyle!(sm, "name2") == false - @test AG.npart(sm) == 1 + @testset "Testing StyleTable Methods" begin + AG.createstylemanager() do sm + @test AG.initialize!(sm) == true + @test AG.npart(sm) == 0 + @test AG.initialize!( + sm, + "PEN(w:2px,c:#000000,id:\"mapinfo-pen-2,ogr-pen-0\")", + ) == true + AG.getpart(sm, 0) do st + @test AG.getstylestring(st) == + "PEN(w:2px,c:#000000,id:\"mapinfo-pen-2,ogr-pen-0\")" + @test AG.toRGBA(st, "#123456") == (18, 52, 86, 255) + end + @test AG.npart(sm) == 1 + @test AG.addstyle!(sm, "name1", "style1") == false + @test AG.npart(sm) == 1 + @test AG.addstyle!(sm, "name2") == false + @test AG.npart(sm) == 1 - AG.createstyletool(AG.OGRSTCBrush) do st - @test AG.gettype(st) == AG.OGRSTCBrush - @test AG.getunit(st) == AG.OGRSTUMM - AG.setunit!(st, AG.OGRSTUPixel, 2.0) - @test AG.getunit(st) == AG.OGRSTUPixel + AG.createstyletool(AG.OGRSTCBrush) do st + @test AG.gettype(st) == AG.OGRSTCBrush + @test AG.getunit(st) == AG.OGRSTUMM + AG.setunit!(st, AG.OGRSTUPixel, 2.0) + @test AG.getunit(st) == AG.OGRSTUPixel - AG.setparam!(st, 0, 0) + AG.setparam!(st, 0, 0) @test AG.asint(st, 0) == 0 @test AG.asstring(st, 0) == "0" @test AG.asdouble(st, 0) == 0 - AG.setparam!(st, 1, 12) + AG.setparam!(st, 1, 12) @test AG.asint(st, 1) == 12 @test AG.asstring(st, 1) == "12" @test AG.asdouble(st, 1) == 12 - AG.setparam!(st, 2, "foo") + AG.setparam!(st, 2, "foo") @test AG.asstring(st, 2) == "foo" - AG.setparam!(st, 3, 0.5) + AG.setparam!(st, 3, 0.5) @test AG.asdouble(st, 3) ≈ 0.5 - @test AG.npart(sm) == 1 - AG.addpart!(sm, st) - @test AG.npart(sm) == 2 - @test AG.npart(sm, "some stylestring") == 1 - end + @test AG.npart(sm) == 1 + AG.addpart!(sm, st) + @test AG.npart(sm) == 2 + @test AG.npart(sm, "some stylestring") == 1 + end - AG.createstyletable() do stbl - AG.addstyle!(stbl, "name1", "style1") - AG.addstyle!(stbl, "name2", "style2") - AG.addstyle!(stbl, "name3", "style3") - AG.addstyle!(stbl, "name4", "style4") - @test AG.findstylestring(stbl, "name3") == "style3" - @test AG.laststyle(stbl) == "" - @test AG.nextstyle(stbl) == "style1" - @test AG.nextstyle(stbl) == "style2" - AG.resetreading!(stbl) - @test AG.nextstyle(stbl) == "style1" - AG.savestyletable(stbl, "tmp/styletable.txt") + AG.createstyletable() do stbl + AG.addstyle!(stbl, "name1", "style1") + AG.addstyle!(stbl, "name2", "style2") + AG.addstyle!(stbl, "name3", "style3") + AG.addstyle!(stbl, "name4", "style4") + @test AG.findstylestring(stbl, "name3") == "style3" + @test AG.laststyle(stbl) == "" + @test AG.nextstyle(stbl) == "style1" + @test AG.nextstyle(stbl) == "style2" + AG.resetreading!(stbl) + @test AG.nextstyle(stbl) == "style1" + AG.savestyletable(stbl, "tmp/styletable.txt") + end + AG.createstyletable() do stbl + AG.loadstyletable!(stbl, "tmp/styletable.txt") + @test AG.findstylestring(stbl, "name3") == "style3" + @test AG.laststyle(stbl) == "" + @test AG.nextstyle(stbl) == "style1" + @test AG.nextstyle(stbl) == "style2" + AG.resetreading!(stbl) + @test AG.nextstyle(stbl) == "style1" + end + rm("tmp/styletable.txt") end - AG.createstyletable() do stbl - AG.loadstyletable!(stbl, "tmp/styletable.txt") - @test AG.findstylestring(stbl, "name3") == "style3" - @test AG.laststyle(stbl) == "" - @test AG.nextstyle(stbl) == "style1" - @test AG.nextstyle(stbl) == "style2" - AG.resetreading!(stbl) - @test AG.nextstyle(stbl) == "style1" - end - rm("tmp/styletable.txt") end -end end diff --git a/test/test_tables.jl b/test/test_tables.jl index 81bcc514..4344a206 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -1,86 +1,101 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; using Tables @testset "test_tables.jl" begin -@testset "Tables Support" begin - dataset = AG.read(joinpath(@__DIR__, "data/point.geojson")) - dataset1 = AG.read(joinpath(@__DIR__, "data/multi_geom.csv"), options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"]) - dataset2 = AG.read(joinpath(@__DIR__, "data/missing_testcase.csv"), options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"]) - @test dataset isa ArchGDAL.IDataset - @test dataset1 isa ArchGDAL.IDataset - @test dataset2 isa ArchGDAL.IDataset - layer = AG.getlayer(dataset, 0) - layer1 = AG.getlayer(dataset1, 0) - layer2 = AG.getlayer(dataset2, 0) - gt = AG.Table(layer) - gt1 = AG.Table(layer1) - gt2 = AG.Table(layer2) + @testset "Tables Support" begin + dataset = AG.read(joinpath(@__DIR__, "data/point.geojson")) + dataset1 = AG.read( + joinpath(@__DIR__, "data/multi_geom.csv"), + options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"], + ) + dataset2 = AG.read( + joinpath(@__DIR__, "data/missing_testcase.csv"), + options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"], + ) + @test dataset isa ArchGDAL.IDataset + @test dataset1 isa ArchGDAL.IDataset + @test dataset2 isa ArchGDAL.IDataset + layer = AG.getlayer(dataset, 0) + layer1 = AG.getlayer(dataset1, 0) + layer2 = AG.getlayer(dataset2, 0) + gt = AG.Table(layer) + gt1 = AG.Table(layer1) + gt2 = AG.Table(layer2) - @testset "read layer to table" begin - @test sprint(print, gt) == "Table with 4 features\n" - @test sprint(print, gt1) == "Table with 2 features\n" - @test sprint(print, gt2) == "Table with 9 features\n" - end + @testset "read layer to table" begin + @test sprint(print, gt) == "Table with 4 features\n" + @test sprint(print, gt1) == "Table with 2 features\n" + @test sprint(print, gt2) == "Table with 9 features\n" + end - @testset "Tables methods" begin - @test Tables.schema(layer1) == Tables.Schema( - (:id, :zoom, :location, :point, :linestring), - (String, String, String, AG.IGeometry, AG.IGeometry) - ) - @test Tables.istable(AG.Table) == true - @test Tables.rowaccess(AG.Table) == true - @test Tables.rows(gt) isa AG.AbstractFeatureLayer - @test Tables.rows(gt1) isa AG.AbstractFeatureLayer - @test Tables.rows(gt2) isa AG.AbstractFeatureLayer + @testset "Tables methods" begin + @test Tables.schema(layer1) == Tables.Schema( + (:id, :zoom, :location, :point, :linestring), + (String, String, String, AG.IGeometry, AG.IGeometry), + ) + @test Tables.istable(AG.Table) == true + @test Tables.rowaccess(AG.Table) == true + @test Tables.rows(gt) isa AG.AbstractFeatureLayer + @test Tables.rows(gt1) isa AG.AbstractFeatureLayer + @test Tables.rows(gt2) isa AG.AbstractFeatureLayer - features = collect(Tables.rows(gt1)) - @test length(features) == 2 - - @test Tables.columnnames(features[1]) == (:id, :zoom, :location, :point, :linestring) - @test Tables.getcolumn(features[2], -5) == nothing - @test Tables.getcolumn(features[2], 0) == nothing - @test Tables.getcolumn(features[1], 1) == "5.1" - @test Tables.getcolumn(features[1], 2) == "1.0" - @test Tables.getcolumn(features[1], 3) == "Mumbai" - @test AG.toWKT(Tables.getcolumn(features[1], 4)) == "POINT (30 10)" - @test AG.toWKT(Tables.getcolumn(features[1], 5)) == "LINESTRING (30 10,10 30,40 40)" - @test Tables.getcolumn(features[1], :id) == "5.1" - @test Tables.getcolumn(features[1], :zoom) == "1.0" - @test Tables.getcolumn(features[1], :location) == "Mumbai" - @test AG.toWKT(Tables.getcolumn(features[1], :point)) == "POINT (30 10)" - @test AG.toWKT(Tables.getcolumn(features[1], :linestring)) == "LINESTRING (30 10,10 30,40 40)" - @test isnothing(Tables.getcolumn(features[1], :fake)) - - @test Tables.columnnames(features[2]) == (:id, :zoom, :location, :point, :linestring) - @test Tables.getcolumn(features[2], -5) == nothing - @test Tables.getcolumn(features[2], 0) == nothing - @test Tables.getcolumn(features[2], 1) == "5.2" - @test Tables.getcolumn(features[2], 2) == "2.0" - @test Tables.getcolumn(features[2], 3) == "New Delhi" - @test AG.toWKT(Tables.getcolumn(features[2], 4)) == "POINT (35 15)" - @test AG.toWKT(Tables.getcolumn(features[2], 5)) == "LINESTRING (35 15,15 35,45 45)" - @test Tables.getcolumn(features[2], :id) == "5.2" - @test Tables.getcolumn(features[2], :zoom) == "2.0" - @test Tables.getcolumn(features[2], :location) == "New Delhi" - @test AG.toWKT(Tables.getcolumn(features[2], :point)) == "POINT (35 15)" - @test AG.toWKT(Tables.getcolumn(features[2], :linestring)) == "LINESTRING (35 15,15 35,45 45)" - @test isnothing(Tables.getcolumn(features[2], :fake)) - end + features = collect(Tables.rows(gt1)) + @test length(features) == 2 - @testset "Misc. methods" begin - AG.resetreading!(layer) - AG.resetreading!(layer1) + @test Tables.columnnames(features[1]) == + (:id, :zoom, :location, :point, :linestring) + @test Tables.getcolumn(features[2], -5) == nothing + @test Tables.getcolumn(features[2], 0) == nothing + @test Tables.getcolumn(features[1], 1) == "5.1" + @test Tables.getcolumn(features[1], 2) == "1.0" + @test Tables.getcolumn(features[1], 3) == "Mumbai" + @test AG.toWKT(Tables.getcolumn(features[1], 4)) == "POINT (30 10)" + @test AG.toWKT(Tables.getcolumn(features[1], 5)) == + "LINESTRING (30 10,10 30,40 40)" + @test Tables.getcolumn(features[1], :id) == "5.1" + @test Tables.getcolumn(features[1], :zoom) == "1.0" + @test Tables.getcolumn(features[1], :location) == "Mumbai" + @test AG.toWKT(Tables.getcolumn(features[1], :point)) == "POINT (30 10)" + @test AG.toWKT(Tables.getcolumn(features[1], :linestring)) == + "LINESTRING (30 10,10 30,40 40)" + @test isnothing(Tables.getcolumn(features[1], :fake)) - schema_names = AG.schema_names(AG.layerdefn(layer)) - schema_names1 = AG.schema_names(AG.layerdefn(layer1)) - - for i in 1:4 - @test schema_names[i] isa Base.Generator || schema_names[i] isa ArchGDAL.IFeatureDefnView - @test schema_names1[i] isa Base.Generator || schema_names1[i] isa ArchGDAL.IFeatureDefnView + @test Tables.columnnames(features[2]) == + (:id, :zoom, :location, :point, :linestring) + @test Tables.getcolumn(features[2], -5) == nothing + @test Tables.getcolumn(features[2], 0) == nothing + @test Tables.getcolumn(features[2], 1) == "5.2" + @test Tables.getcolumn(features[2], 2) == "2.0" + @test Tables.getcolumn(features[2], 3) == "New Delhi" + @test AG.toWKT(Tables.getcolumn(features[2], 4)) == "POINT (35 15)" + @test AG.toWKT(Tables.getcolumn(features[2], 5)) == + "LINESTRING (35 15,15 35,45 45)" + @test Tables.getcolumn(features[2], :id) == "5.2" + @test Tables.getcolumn(features[2], :zoom) == "2.0" + @test Tables.getcolumn(features[2], :location) == "New Delhi" + @test AG.toWKT(Tables.getcolumn(features[2], :point)) == "POINT (35 15)" + @test AG.toWKT(Tables.getcolumn(features[2], :linestring)) == + "LINESTRING (35 15,15 35,45 45)" + @test isnothing(Tables.getcolumn(features[2], :fake)) + end + + @testset "Misc. methods" begin + AG.resetreading!(layer) + AG.resetreading!(layer1) + + schema_names = AG.schema_names(AG.layerdefn(layer)) + schema_names1 = AG.schema_names(AG.layerdefn(layer1)) + + for i = 1:4 + @test schema_names[i] isa Base.Generator || + schema_names[i] isa ArchGDAL.IFeatureDefnView + @test schema_names1[i] isa Base.Generator || + schema_names1[i] isa ArchGDAL.IFeatureDefnView + end end end -end end diff --git a/test/test_types.jl b/test/test_types.jl index 71ba5e6f..186c09a9 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -1,132 +1,133 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; import ImageCore @testset "test_types.jl" begin -@testset "Testing GDAL Type Methods" begin - @testset "GDAL Open Flags" begin - @test AG.OF_READONLY | 0x04 == 0x04 - @test 0x06 | AG.OF_READONLY == 0x06 - @test AG.OF_READONLY | AG.OF_GNM == AG.OF_READONLY | AG.OF_GNM - end + @testset "Testing GDAL Type Methods" begin + @testset "GDAL Open Flags" begin + @test AG.OF_READONLY | 0x04 == 0x04 + @test 0x06 | AG.OF_READONLY == 0x06 + @test AG.OF_READONLY | AG.OF_GNM == AG.OF_READONLY | AG.OF_GNM + end - @testset "GDAL Data Types" begin - @test AG.typesize(AG.GDT_UInt16) == 16 - @test AG.typename(AG.GDT_UInt16) == "UInt16" - @test AG.gettype("UInt16") == AG.GDT_UInt16 + @testset "GDAL Data Types" begin + @test AG.typesize(AG.GDT_UInt16) == 16 + @test AG.typename(AG.GDT_UInt16) == "UInt16" + @test AG.gettype("UInt16") == AG.GDT_UInt16 - @test AG.typeunion(AG.GDT_UInt16, AG.GDT_Byte) == AG.GDT_UInt16 - @test AG.iscomplex(AG.GDT_Float32) == false + @test AG.typeunion(AG.GDT_UInt16, AG.GDT_Byte) == AG.GDT_UInt16 + @test AG.iscomplex(AG.GDT_Float32) == false - @test Base.convert(AG.GDALDataType, UInt8) == AG.GDT_Byte - @test_throws ErrorException Base.convert(AG.GDALDataType, Int64) - @test_throws ErrorException Base.convert(DataType, AG.GDT_TypeCount) - @test_throws MethodError Base.convert(ImageCore.Normed, AG.GDT_Float32) - end + @test Base.convert(AG.GDALDataType, UInt8) == AG.GDT_Byte + @test_throws ErrorException Base.convert(AG.GDALDataType, Int64) + @test_throws ErrorException Base.convert(DataType, AG.GDT_TypeCount) + @test_throws MethodError Base.convert(ImageCore.Normed, AG.GDT_Float32) + end - @testset "GDAL Colors and Palettes" begin - @test AG.getname(AG.GARIO_COMPLETE) == "COMPLETE" - @test AG.asyncstatustype("COMPLETE") == AG.GARIO_COMPLETE - @test AG.asyncstatustype("ERROR") == AG.GARIO_ERROR - @test AG.asyncstatustype("PENDING") == AG.GARIO_PENDING - @test AG.asyncstatustype("UPDATE") == AG.GARIO_UPDATE + @testset "GDAL Colors and Palettes" begin + @test AG.getname(AG.GARIO_COMPLETE) == "COMPLETE" + @test AG.asyncstatustype("COMPLETE") == AG.GARIO_COMPLETE + @test AG.asyncstatustype("ERROR") == AG.GARIO_ERROR + @test AG.asyncstatustype("PENDING") == AG.GARIO_PENDING + @test AG.asyncstatustype("UPDATE") == AG.GARIO_UPDATE - @test AG.colorinterp("Hue") == AG.GCI_HueBand - @test AG.colorinterp("Red") == AG.GCI_RedBand - @test AG.colorinterp("Blue") == AG.GCI_BlueBand + @test AG.colorinterp("Hue") == AG.GCI_HueBand + @test AG.colorinterp("Red") == AG.GCI_RedBand + @test AG.colorinterp("Blue") == AG.GCI_BlueBand - @test AG.getname(AG.GPI_Gray) == "Gray" - @test AG.getname(AG.GPI_RGB) == "RGB" - @test AG.getname(AG.GPI_CMYK) == "CMYK" - @test AG.getname(AG.GPI_HLS) == "HLS" - end + @test AG.getname(AG.GPI_Gray) == "Gray" + @test AG.getname(AG.GPI_RGB) == "RGB" + @test AG.getname(AG.GPI_CMYK) == "CMYK" + @test AG.getname(AG.GPI_HLS) == "HLS" + end - @testset "GDAL Field Types" begin - @test AG.getname(AG.OFTString) == "String" - @test AG.getname(AG.OFTIntegerList) == "IntegerList" - @test AG.getname(AG.OFSTBoolean) == "Boolean" - @test AG.getname(AG.OFSTFloat32) == "Float32" + @testset "GDAL Field Types" begin + @test AG.getname(AG.OFTString) == "String" + @test AG.getname(AG.OFTIntegerList) == "IntegerList" + @test AG.getname(AG.OFSTBoolean) == "Boolean" + @test AG.getname(AG.OFSTFloat32) == "Float32" - @test AG.arecompatible(AG.OFTReal, AG.OFSTNone) == true - @test AG.arecompatible(AG.OFTReal, AG.OFSTBoolean) == false - @test AG.arecompatible(AG.OFTReal, AG.OFSTInt16) == false - @test AG.arecompatible(AG.OFTReal, AG.OFSTFloat32) == true - end + @test AG.arecompatible(AG.OFTReal, AG.OFSTNone) == true + @test AG.arecompatible(AG.OFTReal, AG.OFSTBoolean) == false + @test AG.arecompatible(AG.OFTReal, AG.OFSTInt16) == false + @test AG.arecompatible(AG.OFTReal, AG.OFSTFloat32) == true + end - @testset "Base Geometry Types" begin - @test AG.basetype(AG.wkbUnknown) == AG.wkbUnknown - @test AG.basetype(AG.wkbPoint) == AG.wkbPoint - @test AG.basetype(AG.wkbLineString) == AG.wkbLineString - @test AG.basetype(AG.wkbPolygon) == AG.wkbPolygon - @test AG.basetype(AG.wkbMultiPoint) == AG.wkbMultiPoint - @test AG.basetype(AG.wkbMultiLineString) == AG.wkbMultiLineString - @test AG.basetype(AG.wkbMultiPolygon) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollection) == AG.wkbGeometryCollection - @test AG.basetype(AG.wkbCircularString) == AG.wkbCircularString - @test AG.basetype(AG.wkbCompoundCurve) == AG.wkbCompoundCurve - @test AG.basetype(AG.wkbCurvePolygon) == AG.wkbCurvePolygon - @test AG.basetype(AG.wkbMultiCurve) == AG.wkbMultiCurve - @test AG.basetype(AG.wkbMultiSurface) == AG.wkbMultiSurface - @test AG.basetype(AG.wkbCurve) == AG.wkbCurve - @test AG.basetype(AG.wkbSurface) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurface) == AG.wkbPolyhedralSurface - @test AG.basetype(AG.wkbTIN) == AG.wkbTIN - @test AG.basetype(AG.wkbTriangle) == AG.wkbTriangle - @test AG.basetype(AG.wkbNone) == AG.wkbNone - @test AG.basetype(AG.wkbLinearRing) == AG.wkbLinearRing - @test AG.basetype(AG.wkbCircularStringZ) == AG.wkbCircularString - @test AG.basetype(AG.wkbCompoundCurveZ) == AG.wkbCompoundCurve - @test AG.basetype(AG.wkbCurvePolygonZ) == AG.wkbCurvePolygon - @test AG.basetype(AG.wkbMultiCurveZ) == AG.wkbMultiCurve - @test AG.basetype(AG.wkbMultiSurfaceZ) == AG.wkbMultiSurface - @test AG.basetype(AG.wkbCurveZ) == AG.wkbCurve - @test AG.basetype(AG.wkbSurfaceZ) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurfaceZ) == AG.wkbPolyhedralSurface - @test AG.basetype(AG.wkbTINZ) == AG.wkbTIN - @test AG.basetype(AG.wkbTriangleZ) == AG.wkbTriangle - @test AG.basetype(AG.wkbPointM) == AG.wkbPoint - @test AG.basetype(AG.wkbLineStringM) == AG.wkbLineString - @test AG.basetype(AG.wkbPolygonM) == AG.wkbPolygon - @test AG.basetype(AG.wkbMultiPointM) == AG.wkbMultiPoint - @test AG.basetype(AG.wkbMultiLineStringM) == AG.wkbMultiLineString - @test AG.basetype(AG.wkbMultiPolygonM) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollectionM) == AG.wkbGeometryCollection - @test AG.basetype(AG.wkbCircularStringM) == AG.wkbCircularString - @test AG.basetype(AG.wkbCompoundCurveM) == AG.wkbCompoundCurve - @test AG.basetype(AG.wkbCurvePolygonM) == AG.wkbCurvePolygon - @test AG.basetype(AG.wkbMultiCurveM) == AG.wkbMultiCurve - @test AG.basetype(AG.wkbMultiSurfaceM) == AG.wkbMultiSurface - @test AG.basetype(AG.wkbCurveM) == AG.wkbCurve - @test AG.basetype(AG.wkbSurfaceM) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurfaceM) == AG.wkbPolyhedralSurface - @test AG.basetype(AG.wkbTINM) == AG.wkbTIN - @test AG.basetype(AG.wkbTriangleM) == AG.wkbTriangle - @test AG.basetype(AG.wkbPointZM) == AG.wkbPoint - @test AG.basetype(AG.wkbLineStringZM) == AG.wkbLineString - @test AG.basetype(AG.wkbPolygonZM) == AG.wkbPolygon - @test AG.basetype(AG.wkbMultiPointZM) == AG.wkbMultiPoint - @test AG.basetype(AG.wkbMultiLineStringZM) == AG.wkbMultiLineString - @test AG.basetype(AG.wkbMultiPolygonZM) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollectionZM) == AG.wkbGeometryCollection - @test AG.basetype(AG.wkbCircularStringZM) == AG.wkbCircularString - @test AG.basetype(AG.wkbCompoundCurveZM) == AG.wkbCompoundCurve - @test AG.basetype(AG.wkbCurvePolygonZM) == AG.wkbCurvePolygon - @test AG.basetype(AG.wkbMultiCurveZM) == AG.wkbMultiCurve - @test AG.basetype(AG.wkbMultiSurfaceZM) == AG.wkbMultiSurface - @test AG.basetype(AG.wkbCurveZM) == AG.wkbCurve - @test AG.basetype(AG.wkbSurfaceZM) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurfaceZM) == AG.wkbPolyhedralSurface - @test AG.basetype(AG.wkbTINZM) == AG.wkbTIN - @test AG.basetype(AG.wkbTriangleZM) == AG.wkbTriangle - @test AG.basetype(AG.wkbPoint25D) == AG.wkbPoint - @test AG.basetype(AG.wkbLineString25D) == AG.wkbLineString - @test AG.basetype(AG.wkbPolygon25D) == AG.wkbPolygon - @test AG.basetype(AG.wkbMultiPoint25D) == AG.wkbMultiPoint - @test AG.basetype(AG.wkbMultiLineString25D) == AG.wkbMultiLineString - @test AG.basetype(AG.wkbMultiPolygon25D) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollection25D) == AG.wkbGeometryCollection + @testset "Base Geometry Types" begin + @test AG.basetype(AG.wkbUnknown) == AG.wkbUnknown + @test AG.basetype(AG.wkbPoint) == AG.wkbPoint + @test AG.basetype(AG.wkbLineString) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygon) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPoint) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineString) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygon) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollection) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbCircularString) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurve) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygon) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurve) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurface) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurve) == AG.wkbCurve + @test AG.basetype(AG.wkbSurface) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurface) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTIN) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangle) == AG.wkbTriangle + @test AG.basetype(AG.wkbNone) == AG.wkbNone + @test AG.basetype(AG.wkbLinearRing) == AG.wkbLinearRing + @test AG.basetype(AG.wkbCircularStringZ) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurveZ) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygonZ) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurveZ) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurfaceZ) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurveZ) == AG.wkbCurve + @test AG.basetype(AG.wkbSurfaceZ) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceZ) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTINZ) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangleZ) == AG.wkbTriangle + @test AG.basetype(AG.wkbPointM) == AG.wkbPoint + @test AG.basetype(AG.wkbLineStringM) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygonM) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPointM) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineStringM) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygonM) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollectionM) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbCircularStringM) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurveM) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygonM) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurveM) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurfaceM) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurveM) == AG.wkbCurve + @test AG.basetype(AG.wkbSurfaceM) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceM) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTINM) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangleM) == AG.wkbTriangle + @test AG.basetype(AG.wkbPointZM) == AG.wkbPoint + @test AG.basetype(AG.wkbLineStringZM) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygonZM) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPointZM) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineStringZM) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygonZM) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollectionZM) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbCircularStringZM) == AG.wkbCircularString + @test AG.basetype(AG.wkbCompoundCurveZM) == AG.wkbCompoundCurve + @test AG.basetype(AG.wkbCurvePolygonZM) == AG.wkbCurvePolygon + @test AG.basetype(AG.wkbMultiCurveZM) == AG.wkbMultiCurve + @test AG.basetype(AG.wkbMultiSurfaceZM) == AG.wkbMultiSurface + @test AG.basetype(AG.wkbCurveZM) == AG.wkbCurve + @test AG.basetype(AG.wkbSurfaceZM) == AG.wkbSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceZM) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbTINZM) == AG.wkbTIN + @test AG.basetype(AG.wkbTriangleZM) == AG.wkbTriangle + @test AG.basetype(AG.wkbPoint25D) == AG.wkbPoint + @test AG.basetype(AG.wkbLineString25D) == AG.wkbLineString + @test AG.basetype(AG.wkbPolygon25D) == AG.wkbPolygon + @test AG.basetype(AG.wkbMultiPoint25D) == AG.wkbMultiPoint + @test AG.basetype(AG.wkbMultiLineString25D) == AG.wkbMultiLineString + @test AG.basetype(AG.wkbMultiPolygon25D) == AG.wkbMultiPolygon + @test AG.basetype(AG.wkbGeometryCollection25D) == AG.wkbGeometryCollection + end end -end end diff --git a/test/test_utils.jl b/test/test_utils.jl index 47301330..3569becb 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -1,13 +1,14 @@ using Test -import ArchGDAL; const AG = ArchGDAL +import ArchGDAL; +const AG = ArchGDAL; @testset "test_utils.jl" begin -@testset "metadataitem" begin - driver = AG.getdriver("DERIVED") - @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "" - driver = AG.getdriver("GTiff") - @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "tif tiff" -end + @testset "metadataitem" begin + driver = AG.getdriver("DERIVED") + @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "" + driver = AG.getdriver("GTiff") + @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "tif tiff" + end end From 4ac61847b97362d37c4d3003677e2fe1dd5a87f0 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 1 May 2021 19:21:09 -0700 Subject: [PATCH 095/169] Add github workflow for running JuliaFormatter --- .github/workflows/format_pr.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/format_pr.yml diff --git a/.github/workflows/format_pr.yml b/.github/workflows/format_pr.yml new file mode 100644 index 00000000..95fc1b0b --- /dev/null +++ b/.github/workflows/format_pr.yml @@ -0,0 +1,30 @@ +name: format-pr +on: + schedule: + - cron: '0 0 * * *' +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install JuliaFormatter and format + run: | + julia -e 'import Pkg; Pkg.add("JuliaFormatter")' + julia -e 'using JuliaFormatter; format(".")' + + # https://github.com/marketplace/actions/create-pull-request + # https://github.com/peter-evans/create-pull-request#reference-example + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Format .jl files + title: 'Automatic JuliaFormatter.jl run' + branch: auto-juliaformatter-pr + delete-branch: true + labels: formatting, automated pr, no changelog + - name: Check outputs + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" From 582d02690618271c87f870960d264f89c90616d8 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 11:40:45 -0700 Subject: [PATCH 096/169] Add format configurations --- .JuliaFormatter.toml | 8 + src/base/display.jl | 32 ++-- src/base/iterators.jl | 17 ++- src/context.jl | 9 +- src/convert.jl | 65 +++++--- src/dataset.jl | 60 ++++++-- src/driver.jl | 15 +- src/geointerface.jl | 26 +++- src/geotransform.jl | 10 +- src/ogr/feature.jl | 62 ++++++-- src/ogr/featuredefn.jl | 35 +++-- src/ogr/featurelayer.jl | 67 +++++++-- src/ogr/fielddefn.jl | 28 +++- src/ogr/geometry.jl | 233 ++++++++++++++++++++--------- src/ogr/styletable.jl | 53 +++++-- src/raster/array.jl | 22 ++- src/raster/colortable.jl | 3 +- src/raster/images.jl | 15 +- src/raster/rasterattributetable.jl | 41 ++++- src/raster/rasterband.jl | 61 +++++--- src/raster/rasterio.jl | 51 +++++-- src/spatialref.jl | 100 ++++++++++--- src/tables.jl | 29 ++-- src/types.jl | 14 +- src/utils.jl | 26 +++- test/runtests.jl | 1 + test/test_array.jl | 28 ++-- test/test_convert.jl | 4 +- test/test_cookbook_geometry.jl | 20 +-- test/test_cookbook_projection.jl | 34 +++-- test/test_dataset.jl | 24 ++- test/test_display.jl | 4 +- test/test_drivers.jl | 2 - test/test_feature.jl | 34 +++-- test/test_featurelayer.jl | 26 +++- test/test_fielddefn.jl | 27 ++-- test/test_gdal_tutorials.jl | 22 ++- test/test_geometry.jl | 194 ++++++++++++++++++++---- 38 files changed, 1098 insertions(+), 404 deletions(-) create mode 100644 .JuliaFormatter.toml diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 00000000..a700a076 --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,8 @@ +# Configuration file for JuliaFormatter.jl +# For more information, see: https://domluna.github.io/JuliaFormatter.jl/stable/config/ + +always_for_in = true +always_use_return = true +margin = 80 +remove_extra_newlines = true +short_to_long_function_def = true diff --git a/src/base/display.jl b/src/base/display.jl index 1deb2e3e..6a0a4136 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -26,7 +26,7 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO print(io, "\nDataset (width x height): ") println(io, "$(width(dataset)) x $(height(dataset)) (pixels)") println(io, "Number of raster bands: $nrasters") - for i = 1:min(nrasters, 3) + for i in 1:min(nrasters, 3) print(io, " ") summarize(io, getband(dataset, i)) end @@ -37,14 +37,14 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO if nlayers > 0 println(io, "\nNumber of feature layers: $nlayers") ndisplay = min(nlayers, 5) # display up to 5 layers - for i = 1:ndisplay + for i in 1:ndisplay layer = getlayer(dataset, i - 1) layergeomtype = getgeomtype(layer) println(io, " Layer $(i - 1): $(getname(layer)) ($layergeomtype)") end if nlayers > 5 print(io, " Remaining layers:\n ") - for i = 6:nlayers + for i in 6:nlayers print(io, "$(getname(getlayer(dataset, i - 1))), ") # display up to 5 layer names per line if i % 5 == 0 && i < nlayers @@ -59,7 +59,8 @@ end #Add method to avoid show from DiskArrays Base.show(io::IO, raster::RasterDataset)::IO = show(io, raster.ds) -Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::IO = show(io, raster.ds) +Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::IO = + show(io, raster.ds) function summarize(io::IO, rasterband::AbstractRasterBand)::IO if rasterband.ptr == C_NULL @@ -76,9 +77,14 @@ function summarize(io::IO, rasterband::AbstractRasterBand)::IO return io end -Base.show(io::IO, rasterband::AbstractRasterBand)::IO = show(io, "text/plain", rasterband) +Base.show(io::IO, rasterband::AbstractRasterBand)::IO = + show(io, "text/plain", rasterband) -function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand)::IO +function Base.show( + io::IO, + ::MIME"text/plain", + rasterband::AbstractRasterBand, +)::IO summarize(io, rasterband) if rasterband.ptr == C_NULL return io @@ -92,7 +98,7 @@ function Base.show(io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand):: print(io, " blocksize: $(x)×$(y), nodata: $nv, ") println(io, "units: $(sc)px + $ofs$ut") print(io, " overviews: ") - for i = 1:norvw + for i in 1:norvw ovr_band = getoverview(rasterband, i - 1) print(io, "($(i - 1)) $(width(ovr_band))x$(height(ovr_band)) ") i % 3 == 0 && print(io, "\n ") @@ -113,7 +119,7 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO # Print Geometries n = ngeom(featuredefn) ngeomdisplay = min(n, 3) - for i = 1:ngeomdisplay + for i in 1:ngeomdisplay gfd = getgeomdefn(featuredefn, i - 1) display = " Geometry $(i - 1) ($(getname(gfd))): [$(gettype(gfd))]" if length(display) > 75 @@ -141,7 +147,7 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO # Print Features n = nfield(featuredefn) nfielddisplay = min(n, 5) - for i = 1:nfielddisplay + for i in 1:nfielddisplay fd = getfielddefn(featuredefn, i - 1) display = " Field $(i - 1) ($(getname(fd))): [$(gettype(fd))]" if length(display) > 75 @@ -173,7 +179,7 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO end n = ngeom(featuredefn) ngeomdisplay = min(n, 3) - for i = 1:ngeomdisplay + for i in 1:ngeomdisplay gfd = getgeomdefn(featuredefn, i - 1) println(io, " Geometry (index $(i - 1)): $gfd") end @@ -181,7 +187,7 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO n = nfield(featuredefn) nfielddisplay = min(n, 5) - for i = 1:nfielddisplay + for i in 1:nfielddisplay fd = getfielddefn(featuredefn, i - 1) println(io, " Field (index $(i - 1)): $fd") end @@ -214,13 +220,13 @@ function Base.show(io::IO, feature::Feature)::IO end println(io, "Feature") n = ngeom(feature) - for i = 1:min(n, 3) + for i in 1:min(n, 3) displayname = geomname(getgeom(feature, i - 1)) println(io, " (index $(i - 1)) geom => $displayname") end n > 3 && println(io, "...\n Number of geometries: $n") n = nfield(feature) - for i = 1:min(n, 10) + for i in 1:min(n, 10) displayname = getname(getfielddefn(feature, i - 1)) print(io, " (index $(i - 1)) $displayname => ") println(io, "$(getfield(feature, i - 1))") diff --git a/src/base/iterators.jl b/src/base/iterators.jl index 299232a1..2d8348b6 100644 --- a/src/base/iterators.jl +++ b/src/base/iterators.jl @@ -27,7 +27,10 @@ struct BlockIterator{T<:Integer} ybsize::T end -function blocks(::Type{T}, raster::AbstractRasterBand)::BlockIterator{T} where {T<:Integer} +function blocks( + ::Type{T}, + raster::AbstractRasterBand, +)::BlockIterator{T} where {T<:Integer} (xbsize, ybsize) = blocksize(raster) rows = T(height(raster)) cols = T(width(raster)) @@ -85,7 +88,8 @@ function windows( return WindowIterator{T}(blocks(T, raster)) end -windows(raster::AbstractRasterBand)::WindowIterator{Int64} = windows(Int64, raster) +windows(raster::AbstractRasterBand)::WindowIterator{Int64} = + windows(Int64, raster) function Base.iterate( obj::WindowIterator{T}, @@ -95,7 +99,10 @@ function Base.iterate( next = Base.iterate(handle, iter) next == nothing && return nothing (((i, j), (nrows, ncols)), iter) = next - return (((1:ncols) .+ j * handle.xbsize, (1:nrows) .+ i * handle.ybsize), iter) + return ( + ((1:ncols) .+ j * handle.xbsize, (1:nrows) .+ i * handle.ybsize), + iter, + ) end mutable struct BufferIterator{R<:Real,T<:Integer} @@ -115,7 +122,9 @@ function bufferwindows( ) end -function bufferwindows(raster::AbstractRasterBand)::BufferIterator{pixeltype(raster),Int64} +function bufferwindows( + raster::AbstractRasterBand, +)::BufferIterator{pixeltype(raster),Int64} return bufferwindows(Int64, raster) end diff --git a/src/context.jl b/src/context.jl index 35de4b77..483de305 100644 --- a/src/context.jl +++ b/src/context.jl @@ -1,4 +1,8 @@ -function environment(f::Function; globalconfig::Vector = [], threadconfig::Vector = []) +function environment( + f::Function; + globalconfig::Vector = [], + threadconfig::Vector = [], +) # Save the current settings # # CPLGetConfigOption() will return the value of the config option, be it @@ -10,7 +14,8 @@ function environment(f::Function; globalconfig::Vector = [], threadconfig::Vecto # # (ref https://github.com/mapbox/rasterio/pull/997#issuecomment-287117289) globalsettings = Dict(k => getconfigoption(k) for (k, v) in globalconfig) - localsettings = Dict(k => getthreadconfigoption(k) for (k, v) in threadconfig) + localsettings = + Dict(k => getthreadconfigoption(k) for (k, v) in threadconfig) for (k, v) in threadconfig setthreadconfigoption(k, v) end diff --git a/src/convert.jl b/src/convert.jl index 7786b5e9..56393754 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -33,12 +33,21 @@ end Convert `GeoFormat` geometry data to an ArchGDAL `Geometry` type """ -Base.convert(::Type{<:AbstractGeometry}, source::GFT.AbstractWellKnownText) = - fromWKT(GFT.val(source)) -Base.convert(::Type{<:AbstractGeometry}, source::GFT.WellKnownBinary) = - fromWKB(GFT.val(source)) -Base.convert(::Type{<:AbstractGeometry}, source::GFT.GeoJSON) = fromJSON(GFT.val(source)) -Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) = fromGML(GFT.val(source)) +function Base.convert( + ::Type{<:AbstractGeometry}, + source::GFT.AbstractWellKnownText, +) + return fromWKT(GFT.val(source)) +end +function Base.convert(::Type{<:AbstractGeometry}, source::GFT.WellKnownBinary) + return fromWKB(GFT.val(source)) +end +function Base.convert(::Type{<:AbstractGeometry}, source::GFT.GeoJSON) + return fromJSON(GFT.val(source)) +end +function Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) + return fromGML(GFT.val(source)) +end """ convert(::Type{<:GeoFormatTypes.AbstractWellKnownText}, @@ -51,14 +60,24 @@ Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) = fromGML(GFT.val(sour Convert `AbstractGeometry` data to any geometry `GeoFormat`. """ -Base.convert(::Type{<:GFT.AbstractWellKnownText}, source::AbstractGeometry) = - GFT.WellKnownText(GFT.Geom(), toWKT(source)) -Base.convert(::Type{<:GFT.WellKnownBinary}, source::AbstractGeometry) = - GFT.WellKnownBinary(GFT.Geom(), toWKB(source)) -Base.convert(::Type{<:GFT.GeoJSON}, source::AbstractGeometry) = GFT.GeoJSON(toJSON(source)) -Base.convert(::Type{<:GFT.GML}, source::AbstractGeometry) = - GFT.GML(GFT.Geom(), toGML(source)) -Base.convert(::Type{<:GFT.KML}, source::AbstractGeometry) = GFT.KML(toKML(source)) +function Base.convert( + ::Type{<:GFT.AbstractWellKnownText}, + source::AbstractGeometry, +) + return GFT.WellKnownText(GFT.Geom(), toWKT(source)) +end +function Base.convert(::Type{<:GFT.WellKnownBinary}, source::AbstractGeometry) + return GFT.WellKnownBinary(GFT.Geom(), toWKB(source)) +end +function Base.convert(::Type{<:GFT.GeoJSON}, source::AbstractGeometry) + return GFT.GeoJSON(toJSON(source)) +end +function Base.convert(::Type{<:GFT.GML}, source::AbstractGeometry) + return GFT.GML(GFT.Geom(), toGML(source)) +end +function Base.convert(::Type{<:GFT.KML}, source::AbstractGeometry) + return GFT.KML(toKML(source)) +end """ convert(target::Type{<:GeoFormatTypes.GeoFormat}, mode::CRS, @@ -75,10 +94,16 @@ function Base.convert( return unsafe_convertcrs(target, importCRS(source)) end -unsafe_convertcrs(::Type{<:GFT.CoordSys}, crsref) = GFT.CoordSys(toMICoordSys(crsref)) -unsafe_convertcrs(::Type{<:GFT.ProjString}, crsref) = GFT.ProjString(toPROJ4(crsref)) -unsafe_convertcrs(::Type{<:GFT.WellKnownText}, crsref) = - GFT.WellKnownText(GFT.CRS(), toWKT(crsref)) -unsafe_convertcrs(::Type{<:GFT.ESRIWellKnownText}, crsref) = - GFT.ESRIWellKnownText(GFT.CRS(), toWKT(morphtoESRI!(crsref))) +function unsafe_convertcrs(::Type{<:GFT.CoordSys}, crsref) + return GFT.CoordSys(toMICoordSys(crsref)) +end +function unsafe_convertcrs(::Type{<:GFT.ProjString}, crsref) + return GFT.ProjString(toPROJ4(crsref)) +end +function unsafe_convertcrs(::Type{<:GFT.WellKnownText}, crsref) + return GFT.WellKnownText(GFT.CRS(), toWKT(crsref)) +end +function unsafe_convertcrs(::Type{<:GFT.ESRIWellKnownText}, crsref) + return GFT.ESRIWellKnownText(GFT.CRS(), toWKT(morphtoESRI!(crsref))) +end unsafe_convertcrs(::Type{<:GFT.GML}, crsref) = GFT.GML(toXML(crsref)) diff --git a/src/dataset.jl b/src/dataset.jl index 9cf816ae..06f6f58e 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -173,7 +173,11 @@ end Writes the dataset to the designated filename. """ -function write(dataset::AbstractDataset, filename::AbstractString; kwargs...)::Nothing +function write( + dataset::AbstractDataset, + filename::AbstractString; + kwargs..., +)::Nothing destroy(unsafe_copy(dataset, filename = filename; kwargs...)) return nothing end @@ -382,7 +386,13 @@ function unsafe_read( options = StringList(C_NULL), siblingfiles = StringList(C_NULL), )::Dataset - result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, siblingfiles) + result = GDAL.gdalopenex( + filename, + Int(flags), + alloweddrivers, + options, + siblingfiles, + ) return Dataset(result) end @@ -428,7 +438,13 @@ function read( options = StringList(C_NULL), siblingfiles = StringList(C_NULL), )::IDataset - result = GDAL.gdalopenex(filename, Int(flags), alloweddrivers, options, siblingfiles) + result = GDAL.gdalopenex( + filename, + Int(flags), + alloweddrivers, + options, + siblingfiles, + ) return IDataset(result) end @@ -454,21 +470,24 @@ height(dataset::AbstractDataset)::Integer = GDAL.gdalgetrasterysize(dataset.ptr) Fetch the number of raster bands on this dataset. """ -nraster(dataset::AbstractDataset)::Integer = GDAL.gdalgetrastercount(dataset.ptr) +nraster(dataset::AbstractDataset)::Integer = + GDAL.gdalgetrastercount(dataset.ptr) """ nlayer(dataset::AbstractDataset) Fetch the number of feature layers on this dataset. """ -nlayer(dataset::AbstractDataset)::Integer = GDAL.gdaldatasetgetlayercount(dataset.ptr) +nlayer(dataset::AbstractDataset)::Integer = + GDAL.gdaldatasetgetlayercount(dataset.ptr) """ getdriver(dataset::AbstractDataset) Fetch the driver that the dataset was created with """ -getdriver(dataset::AbstractDataset)::Driver = Driver(GDAL.gdalgetdatasetdriver(dataset.ptr)) +getdriver(dataset::AbstractDataset)::Driver = + Driver(GDAL.gdalgetdatasetdriver(dataset.ptr)) """ filelist(dataset::AbstractDataset) @@ -483,7 +502,8 @@ list is owned by the caller and should be deallocated with `CSLDestroy()`. The returned filenames will normally be relative or absolute paths depending on the path used to originally open the dataset. The strings will be UTF-8 encoded """ -filelist(dataset::AbstractDataset)::Vector{String} = GDAL.gdalgetfilelist(dataset.ptr) +filelist(dataset::AbstractDataset)::Vector{String} = + GDAL.gdalgetfilelist(dataset.ptr) """ getlayer(dataset::AbstractDataset, i::Integer) @@ -574,7 +594,9 @@ function listcapability( GDAL.ODsCEmulatedTransactions, ), )::Dict{String,Bool} - return Dict{String,Bool}(c => testcapability(dataset, c) for c in capabilities) + return Dict{String,Bool}( + c => testcapability(dataset, c) for c in capabilities + ) end """ @@ -615,7 +637,12 @@ function unsafe_executesql( spatialfilter::Geometry = Geometry(C_NULL), )::FeatureLayer return FeatureLayer( - GDAL.gdaldatasetexecutesql(dataset.ptr, query, spatialfilter.ptr, dialect), + GDAL.gdaldatasetexecutesql( + dataset.ptr, + query, + spatialfilter.ptr, + dialect, + ), ) end @@ -632,7 +659,10 @@ before destroying the `Dataset` may cause errors. * `dataset`: the dataset handle. * `layer`: the result of a previous ExecuteSQL() call. """ -function releaseresultset(dataset::AbstractDataset, layer::FeatureLayer)::Nothing +function releaseresultset( + dataset::AbstractDataset, + layer::FeatureLayer, +)::Nothing GDAL.gdaldatasetreleaseresultset(dataset.ptr, layer.ptr) destroy(layer) return nothing @@ -721,14 +751,18 @@ It should be suitable for use with the OGRSpatialReference class. When a projection definition is not available an empty (but not `NULL`) string is returned. """ -getproj(dataset::AbstractDataset)::String = GDAL.gdalgetprojectionref(dataset.ptr) +getproj(dataset::AbstractDataset)::String = + GDAL.gdalgetprojectionref(dataset.ptr) """ setproj!(dataset::AbstractDataset, projstring::AbstractString) Set the projection reference string for this dataset. """ -function setproj!(dataset::T, projstring::AbstractString)::T where {T<:AbstractDataset} +function setproj!( + dataset::T, + projstring::AbstractString, +)::T where {T<:AbstractDataset} result = GDAL.gdalsetprojection(dataset.ptr, projstring) @cplerr result "Could not set projection" return dataset @@ -790,7 +824,7 @@ in a raster dataset. """ function pixeltype(ds::AbstractDataset)::DataType alldatatypes = map(1:nraster(ds)) do i - pixeltype(getband(ds, i)) + return pixeltype(getband(ds, i)) end return reduce(promote_type, alldatatypes) end diff --git a/src/driver.jl b/src/driver.jl index 3ac64665..a313d5cb 100644 --- a/src/driver.jl +++ b/src/driver.jl @@ -68,7 +68,7 @@ ndriver()::Integer = GDAL.gdalgetdrivercount() Returns a listing of all registered drivers. """ listdrivers()::Dict{String,String} = Dict{String,String}( - [shortname(getdriver(i)) => longname(getdriver(i)) for i = 0:(ndriver()-1)], + [shortname(getdriver(i)) => longname(getdriver(i)) for i in 0:(ndriver()-1)], ) """ @@ -112,7 +112,10 @@ in the list of creation options are compatible with the capabilities declared by the `GDAL_DMD_CREATIONOPTIONLIST` metadata item. In case of incompatibility a (non fatal) warning will be emited and ``false`` will be returned. """ -function validate(drv::Driver, options::Vector{T})::Bool where {T<:AbstractString} +function validate( + drv::Driver, + options::Vector{T}, +)::Bool where {T<:AbstractString} return Bool(GDAL.gdalvalidatecreationoptions(drv.ptr, options)) end @@ -124,7 +127,11 @@ Copy all the files associated with a dataset. """ function copyfiles end -function copyfiles(drv::Driver, new::AbstractString, old::AbstractString)::Nothing +function copyfiles( + drv::Driver, + new::AbstractString, + old::AbstractString, +)::Nothing result = GDAL.gdalcopydatasetfiles(drv.ptr, new, old) @cplerr result "Failed to copy dataset files" return nothing @@ -147,7 +154,7 @@ by GDAL, with their respective drivers' `shortname`s. """ function extensions()::Dict{String,String} extdict = Dict{String,String}() - for i = 1:ndriver() + for i in 1:ndriver() driver = getdriver(i) if !(driver.ptr == C_NULL) # exts is a space-delimited list in a String, so split it diff --git a/src/geointerface.jl b/src/geointerface.jl index a3a94fe2..46936d23 100644 --- a/src/geointerface.jl +++ b/src/geointerface.jl @@ -1,6 +1,8 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), - multipointtypes = (wkbMultiPoint, wkbMultiPoint25D, wkbMultiPointM, wkbMultiPointZM), - linetypes = (wkbLineString, wkbLineString25D, wkbLineStringM, wkbLineStringZM), + multipointtypes = + (wkbMultiPoint, wkbMultiPoint25D, wkbMultiPointM, wkbMultiPointZM), + linetypes = + (wkbLineString, wkbLineString25D, wkbLineStringM, wkbLineStringZM), multilinetypes = ( wkbMultiLineString, wkbMultiLineString25D, @@ -8,8 +10,12 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), wkbMultiLineStringZM, ), polygontypes = (wkbPolygon, wkbPolygon25D, wkbPolygonM, wkbPolygonZM), - multipolygontypes = - (wkbMultiPolygon, wkbMultiPolygon25D, wkbMultiPolygonM, wkbMultiPolygonZM), + multipolygontypes = ( + wkbMultiPolygon, + wkbMultiPolygon25D, + wkbMultiPolygonM, + wkbMultiPolygonZM, + ), collectiontypes = ( wkbGeometryCollection, wkbGeometryCollection25D, @@ -53,16 +59,20 @@ let pointtypes = (wkbPoint, wkbPoint25D, wkbPointM, wkbPointZM), error("getcoorddim($g) returned $ndim: expected 2 or 3") end elseif gtype in multipointtypes - Vector{Float64}[GeoInterface.coordinates(getgeom(g, i - 1)) for i = 1:ngeom(g)] + Vector{Float64}[ + GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) + ] elseif gtype in linetypes || gtype == wkbLinearRing - Vector{Float64}[collect(getpoint(g, i - 1)[1:ndim]) for i = 1:ngeom(g)] + Vector{Float64}[ + collect(getpoint(g, i - 1)[1:ndim]) for i in 1:ngeom(g) + ] elseif gtype in multilinetypes || gtype in polygontypes Vector{Vector{Float64}}[ - GeoInterface.coordinates(getgeom(g, i - 1)) for i = 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) ] elseif gtype in multipolygontypes Vector{Vector{Vector{Float64}}}[ - GeoInterface.coordinates(getgeom(g, i - 1)) for i = 1:ngeom(g) + GeoInterface.coordinates(getgeom(g, i - 1)) for i in 1:ngeom(g) ] end end diff --git a/src/geotransform.jl b/src/geotransform.jl index d73876d1..96434c1a 100644 --- a/src/geotransform.jl +++ b/src/geotransform.jl @@ -13,7 +13,10 @@ converts the equation from being pixel to geo to being geo to pixel. ### Returns `gt_out` """ -function invgeotransform!(gt_in::Vector{Float64}, gt_out::Vector{Float64})::Vector{Float64} +function invgeotransform!( + gt_in::Vector{Float64}, + gt_out::Vector{Float64}, +)::Vector{Float64} result = Bool(GDAL.gdalinvgeotransform(pointer(gt_in), pointer(gt_out))) result || error("Geotransform coefficients is uninvertable") return gt_out @@ -74,6 +77,9 @@ function composegeotransform!( return gtout end -function composegeotransform(gt1::Vector{Float64}, gt2::Vector{Float64})::Vector{Float64} +function composegeotransform( + gt1::Vector{Float64}, + gt2::Vector{Float64}, +)::Vector{Float64} return composegeotransform!(gt1, gt2, Vector{Float64}(undef, 6)) end diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index b78e5714..3813d71c 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -111,7 +111,10 @@ the field index, or -1 if no matching field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. """ -function findfieldindex(feature::Feature, name::Union{AbstractString,Symbol})::Integer +function findfieldindex( + feature::Feature, + name::Union{AbstractString,Symbol}, +)::Integer return GDAL.ogr_f_getfieldindex(feature.ptr, name) end @@ -124,7 +127,8 @@ Test if a field has ever been assigned a value or not. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -isfieldset(feature::Feature, i::Integer)::Bool = Bool(GDAL.ogr_f_isfieldset(feature.ptr, i)) +isfieldset(feature::Feature, i::Integer)::Bool = + Bool(GDAL.ogr_f_isfieldset(feature.ptr, i)) """ unsetfield!(feature::Feature, i::Integer) @@ -165,7 +169,8 @@ Fetch field value as integer. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asint(feature::Feature, i::Integer)::Int32 = GDAL.ogr_f_getfieldasinteger(feature.ptr, i) +asint(feature::Feature, i::Integer)::Int32 = + GDAL.ogr_f_getfieldasinteger(feature.ptr, i) """ asint64(feature::Feature, i::Integer) @@ -200,7 +205,8 @@ Fetch field value as a string. * `feature`: the feature that owned the field. * `i`: the field to fetch, from 0 to GetFieldCount()-1. """ -asstring(feature::Feature, i::Integer)::String = GDAL.ogr_f_getfieldasstring(feature.ptr, i) +asstring(feature::Feature, i::Integer)::String = + GDAL.ogr_f_getfieldasstring(feature.ptr, i) """ asintlist(feature::Feature, i::Integer) @@ -462,7 +468,11 @@ function setfield!(feature::Feature, i::Integer, value::Vector{Int64})::Feature return feature end -function setfield!(feature::Feature, i::Integer, value::Vector{Float64})::Feature +function setfield!( + feature::Feature, + i::Integer, + value::Vector{Float64}, +)::Feature GDAL.ogr_f_setfielddoublelist(feature.ptr, i, length(value), value) return feature end @@ -496,7 +506,12 @@ function setfield!(feature::Feature, i::Integer, value::Vector{UInt8})::Feature return feature end -function setfield!(feature::Feature, i::Integer, dt::DateTime, tzflag::Int = 0)::Feature +function setfield!( + feature::Feature, + i::Integer, + dt::DateTime, + tzflag::Int = 0, +)::Feature GDAL.ogr_f_setfielddatetime( feature.ptr, i, @@ -552,7 +567,10 @@ the geometry field index, or -1 if no matching geometry field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetGeomFieldIndex()` method. """ -function findgeomindex(feature::Feature, name::Union{AbstractString,Symbol} = "")::Integer +function findgeomindex( + feature::Feature, + name::Union{AbstractString,Symbol} = "", +)::Integer return GDAL.ogr_f_getgeomfieldindex(feature.ptr, name) end @@ -583,7 +601,10 @@ function unsafe_getgeom(feature::Feature, i::Integer)::Geometry end end -function getgeom(feature::Feature, name::Union{AbstractString,Symbol})::IGeometry +function getgeom( + feature::Feature, + name::Union{AbstractString,Symbol}, +)::IGeometry i = findgeomindex(feature, name) return if i == -1 IGeometry() @@ -592,7 +613,10 @@ function getgeom(feature::Feature, name::Union{AbstractString,Symbol})::IGeometr end end -function unsafe_getgeom(feature::Feature, name::Union{AbstractString,Symbol})::Geometry +function unsafe_getgeom( + feature::Feature, + name::Union{AbstractString,Symbol}, +)::Geometry i = findgeomindex(feature, name) return if i == -1 Geometry() @@ -677,7 +701,11 @@ otherwise an error code. """ function setfrom! end -function setfrom!(feature1::Feature, feature2::Feature, forgiving::Bool = false)::Feature +function setfrom!( + feature1::Feature, + feature2::Feature, + forgiving::Bool = false, +)::Feature result = GDAL.ogr_f_setfrom(feature1.ptr, feature2.ptr, forgiving) @ogrerr result "OGRErr $result: Failed to set feature" return feature1 @@ -689,18 +717,23 @@ function setfrom!( indices::Vector{Cint}, forgiving::Bool = false, )::Feature - result = GDAL.ogr_f_setfromwithmap(feature1.ptr, feature2.ptr, forgiving, indices) + result = GDAL.ogr_f_setfromwithmap( + feature1.ptr, + feature2.ptr, + forgiving, + indices, + ) @ogrerr result "OGRErr $result: Failed to set feature with map" return feature1 end - """ getstylestring(feature::Feature) Fetch style string for this feature. """ -getstylestring(feature::Feature)::String = GDAL.ogr_f_getstylestring(feature.ptr) +getstylestring(feature::Feature)::String = + GDAL.ogr_f_getstylestring(feature.ptr) """ setstylestring!(feature::Feature, style::AbstractString) @@ -778,7 +811,8 @@ The native media type is the identifier for the format of the native data. It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type), e.g. \"application/vnd.geo+json\" for JSON. """ -getmediatype(feature::Feature)::String = GDAL.ogr_f_getnativemediatype(feature.ptr) +getmediatype(feature::Feature)::String = + GDAL.ogr_f_getnativemediatype(feature.ptr) """ setmediatype!(feature::Feature, mediatype::AbstractString) diff --git a/src/ogr/featuredefn.jl b/src/ogr/featuredefn.jl index 0a69bb29..bc7e40ec 100644 --- a/src/ogr/featuredefn.jl +++ b/src/ogr/featuredefn.jl @@ -19,14 +19,16 @@ The count is used to track the number of `Feature`s referencing this definition. ### Returns The updated reference count. """ -reference(featuredefn::FeatureDefn)::Integer = GDAL.ogr_fd_reference(featuredefn.ptr) +reference(featuredefn::FeatureDefn)::Integer = + GDAL.ogr_fd_reference(featuredefn.ptr) """ dereference(featuredefn::FeatureDefn) Decrements the reference count by one, and returns the updated count. """ -dereference(featuredefn::FeatureDefn)::Integer = GDAL.ogr_fd_dereference(featuredefn.ptr) +dereference(featuredefn::FeatureDefn)::Integer = + GDAL.ogr_fd_dereference(featuredefn.ptr) """ nreference(featuredefn::AbstractFeatureDefn) @@ -64,7 +66,8 @@ end Get name of the OGRFeatureDefn passed as an argument. """ -getname(featuredefn::AbstractFeatureDefn)::String = GDAL.ogr_fd_getname(featuredefn.ptr) +getname(featuredefn::AbstractFeatureDefn)::String = + GDAL.ogr_fd_getname(featuredefn.ptr) """ nfield(featuredefn::AbstractFeatureDefn) @@ -124,7 +127,10 @@ This function should only be called while there are no OGRFeature objects in existence based on this OGRFeatureDefn. The OGRFieldDefn passed in is copied, and remains the responsibility of the caller. """ -function addfielddefn!(featuredefn::FeatureDefn, fielddefn::FieldDefn)::FeatureDefn +function addfielddefn!( + featuredefn::FeatureDefn, + fielddefn::FieldDefn, +)::FeatureDefn GDAL.ogr_fd_addfielddefn(featuredefn.ptr, fielddefn.ptr) return featuredefn end @@ -164,13 +170,15 @@ existence based on this OGRFeatureDefn. at position `i` after reordering, its position before reordering was `indices[i]`. """ -function reorderfielddefns!(featuredefn::FeatureDefn, indices::Vector{Cint})::FeatureDefn +function reorderfielddefns!( + featuredefn::FeatureDefn, + indices::Vector{Cint}, +)::FeatureDefn result = GDAL.ogr_fd_reorderfielddefns(featuredefn.ptr, indices) @ogrerr result "Failed to reorder $indices in the feature definition" return featuredefn end - """ getgeomtype(featuredefn::AbstractFeatureDefn) @@ -199,7 +207,10 @@ type. The default upon creation is `wkbUnknown` which allows for any geometry type. The geometry type should generally not be changed after any OGRFeatures have been created against this definition. """ -function setgeomtype!(featuredefn::FeatureDefn, etype::OGRwkbGeometryType)::FeatureDefn +function setgeomtype!( + featuredefn::FeatureDefn, + etype::OGRwkbGeometryType, +)::FeatureDefn GDAL.ogr_fd_setgeomtype(featuredefn.ptr, etype) return featuredefn end @@ -277,7 +288,10 @@ name (case insensitively) is returned. ### Returns the geometry field index, or -1 if no match found. """ -function findgeomindex(featuredefn::AbstractFeatureDefn, name::AbstractString = "")::Integer +function findgeomindex( + featuredefn::AbstractFeatureDefn, + name::AbstractString = "", +)::Integer return GDAL.ogr_fd_getgeomfieldindex(featuredefn.ptr, name) end @@ -327,7 +341,10 @@ end Test if the feature definition is identical to the other one. """ -function issame(featuredefn1::AbstractFeatureDefn, featuredefn2::AbstractFeatureDefn)::Bool +function issame( + featuredefn1::AbstractFeatureDefn, + featuredefn2::AbstractFeatureDefn, +)::Bool return Bool(GDAL.ogr_fd_issame(featuredefn1.ptr, featuredefn2.ptr)) end diff --git a/src/ogr/featurelayer.jl b/src/ogr/featurelayer.jl index 139892e6..cb94db29 100644 --- a/src/ogr/featurelayer.jl +++ b/src/ogr/featurelayer.jl @@ -34,7 +34,13 @@ function createlayer(; options = StringList(C_NULL), )::IFeatureLayer return IFeatureLayer( - GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, options), + GDAL.gdaldatasetcreatelayer( + dataset.ptr, + name, + spatialref.ptr, + geom, + options, + ), ownedby = dataset, spatialref = spatialref, ) @@ -48,7 +54,13 @@ function unsafe_createlayer(; options = StringList(C_NULL), )::FeatureLayer return FeatureLayer( - GDAL.gdaldatasetcreatelayer(dataset.ptr, name, spatialref.ptr, geom, options), + GDAL.gdaldatasetcreatelayer( + dataset.ptr, + name, + spatialref.ptr, + geom, + options, + ), ) end @@ -86,7 +98,9 @@ function unsafe_copy( name::AbstractString = "copy($(getname(layer)))", options = StringList(C_NULL), )::FeatureLayer - return FeatureLayer(GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options)) + return FeatureLayer( + GDAL.gdaldatasetcopylayer(dataset.ptr, layer.ptr, name, options), + ) end """ @@ -176,7 +190,10 @@ In the future this may be generalized. Note that only the last spatial filter set is applied, even if several successive calls are done with different iGeomField values. """ -function setspatialfilter!(layer::L, geom::Geometry)::L where {L<:AbstractFeatureLayer} +function setspatialfilter!( + layer::L, + geom::Geometry, +)::L where {L<:AbstractFeatureLayer} # This method makes an internal copy of `geom`. The input `geom` remains # the responsibility of the caller, and may be safely destroyed. GDAL.ogr_l_setspatialfilter(layer.ptr, geom.ptr) @@ -254,7 +271,10 @@ function setspatialfilter!( return layer end -function clearspatialfilter!(layer::L, i::Integer)::L where {L<:AbstractFeatureLayer} +function clearspatialfilter!( + layer::L, + i::Integer, +)::L where {L<:AbstractFeatureLayer} GDAL.ogr_l_setspatialfilterex(layer.ptr, i, C_NULL) return layer end @@ -392,7 +412,10 @@ then calls `nextfeature()` `i` times is used. To determine if fast seeking is available on the layer, use the `testcapability()` method with a value of `OLCFastSetNextByIndex`. """ -function setnextbyindex!(layer::L, i::Integer)::L where {L<:AbstractFeatureLayer} +function setnextbyindex!( + layer::L, + i::Integer, +)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_setnextbyindex(layer.ptr, i) @ogrerr result "Failed to move the cursor to index $i" return layer @@ -462,7 +485,10 @@ OGRNullFID, then the native implementation may use that as the feature id of the new feature, but not necessarily. Upon successful return the passed feature will have been updated with the new feature id. """ -function addfeature!(layer::L, feature::Feature)::L where {L<:AbstractFeatureLayer} +function addfeature!( + layer::L, + feature::Feature, +)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_createfeature(layer.ptr, feature.ptr) @ogrerr result "Failed to create and write feature in layer." return layer @@ -614,7 +640,10 @@ function envelope( return envelope[] end -function envelope(layer::AbstractFeatureLayer, force::Bool = false)::GDAL.OGREnvelope +function envelope( + layer::AbstractFeatureLayer, + force::Bool = false, +)::GDAL.OGREnvelope envelope = Ref{GDAL.OGREnvelope}(GDAL.OGREnvelope(0, 0, 0, 0)) result = GDAL.ogr_l_getextent(layer.ptr, envelope, force) @ogrerr result "Extent not known" @@ -734,7 +763,9 @@ function listcapability( GDAL.OLCMeasuredGeometries, ), )::Dict{String,Bool} - return Dict{String,Bool}([c => testcapability(layer, c) for c in capabilities]) + return Dict{String,Bool}( + [c => testcapability(layer, c) for c in capabilities], + ) end # TODO use syntax below once v0.4 support is dropped (not in Compat.jl) @@ -1009,7 +1040,8 @@ Increment layer reference count. ### Returns The reference count after incrementing. """ -reference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_reference(layer.ptr) +reference(layer::AbstractFeatureLayer)::Integer = + GDAL.ogr_l_reference(layer.ptr) """ dereference(layer::AbstractFeatureLayer) @@ -1019,14 +1051,16 @@ Decrement layer reference count. ### Returns The reference count after decrementing. """ -dereference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_dereference(layer.ptr) +dereference(layer::AbstractFeatureLayer)::Integer = + GDAL.ogr_l_dereference(layer.ptr) """ nreference(layer::AbstractFeatureLayer) The current reference count for the layer object itself. """ -nreference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_getrefcount(layer.ptr) +nreference(layer::AbstractFeatureLayer)::Integer = + GDAL.ogr_l_getrefcount(layer.ptr) # """ # Flush pending changes to disk. @@ -1064,7 +1098,8 @@ nreference(layer::AbstractFeatureLayer)::Integer = GDAL.ogr_l_getrefcount(layer. The name of the FID column in the database, or \"\" if not supported. """ -fidcolumnname(layer::AbstractFeatureLayer)::String = GDAL.ogr_l_getfidcolumn(layer.ptr) +fidcolumnname(layer::AbstractFeatureLayer)::String = + GDAL.ogr_l_getfidcolumn(layer.ptr) """ geomcolumnname(layer::AbstractFeatureLayer) @@ -1094,7 +1129,10 @@ Besides field names of the layers, the following special fields can be passed: By default, no fields are ignored. """ -function setignoredfields!(layer::L, fieldnames)::L where {L<:AbstractFeatureLayer} +function setignoredfields!( + layer::L, + fieldnames, +)::L where {L<:AbstractFeatureLayer} result = GDAL.ogr_l_setignoredfields(layer.ptr, fieldnames) # OGRERR_NONE if all field names have been resolved (even if the driver # does not support this method) @@ -1102,7 +1140,6 @@ function setignoredfields!(layer::L, fieldnames)::L where {L<:AbstractFeatureLay return layer end - # """ # Intersection of two layers. diff --git a/src/ogr/fielddefn.jl b/src/ogr/fielddefn.jl index 30b71279..5f60bdb3 100644 --- a/src/ogr/fielddefn.jl +++ b/src/ogr/fielddefn.jl @@ -27,10 +27,12 @@ function setname!(fielddefn::FieldDefn, name::AbstractString)::FieldDefn end "Fetch the name of this field." -getname(fielddefn::AbstractFieldDefn)::String = GDAL.ogr_fld_getnameref(fielddefn.ptr) +getname(fielddefn::AbstractFieldDefn)::String = + GDAL.ogr_fld_getnameref(fielddefn.ptr) "Fetch the type of this field." -gettype(fielddefn::AbstractFieldDefn)::OGRFieldType = GDAL.ogr_fld_gettype(fielddefn.ptr) +gettype(fielddefn::AbstractFieldDefn)::OGRFieldType = + GDAL.ogr_fld_gettype(fielddefn.ptr) "Set the type of this field." function settype!(fielddefn::FieldDefn, etype::OGRFieldType)::FieldDefn @@ -86,7 +88,10 @@ Set the justification for this field. Note: no driver is know to use the concept of field justification. """ -function setjustify!(fielddefn::FieldDefn, ejustify::OGRJustification)::FieldDefn +function setjustify!( + fielddefn::FieldDefn, + ejustify::OGRJustification, +)::FieldDefn GDAL.ogr_fld_setjustify(fielddefn.ptr, ejustify) return fielddefn end @@ -99,7 +104,8 @@ Get the formatting width for this field. ### Returns the width, zero means no specified width. """ -getwidth(fielddefn::AbstractFieldDefn)::Integer = GDAL.ogr_fld_getwidth(fielddefn.ptr) +getwidth(fielddefn::AbstractFieldDefn)::Integer = + GDAL.ogr_fld_getwidth(fielddefn.ptr) """ setwidth!(fielddefn::FieldDefn, width::Integer) @@ -166,7 +172,8 @@ end Return whether this field should be omitted when fetching features. """ -isignored(fielddefn::AbstractFieldDefn)::Bool = Bool(GDAL.ogr_fld_isignored(fielddefn.ptr)) +isignored(fielddefn::AbstractFieldDefn)::Bool = + Bool(GDAL.ogr_fld_isignored(fielddefn.ptr)) """ setignored!(fielddefn::FieldDefn, ignore::Bool) @@ -215,7 +222,8 @@ end Get default field value """ function getdefault(fielddefn::AbstractFieldDefn)::String - result = @gdal(OGR_Fld_GetDefault::Cstring, fielddefn.ptr::GDAL.OGRFieldDefnH) + result = + @gdal(OGR_Fld_GetDefault::Cstring, fielddefn.ptr::GDAL.OGRFieldDefnH) return if result == C_NULL "" else @@ -295,14 +303,18 @@ function setname!(geomdefn::GeomFieldDefn, name::AbstractString)::GeomFieldDefn end "Fetch name of this field." -getname(geomdefn::AbstractGeomFieldDefn)::String = GDAL.ogr_gfld_getnameref(geomdefn.ptr) +getname(geomdefn::AbstractGeomFieldDefn)::String = + GDAL.ogr_gfld_getnameref(geomdefn.ptr) "Fetch geometry type of this field." gettype(geomdefn::AbstractGeomFieldDefn)::OGRwkbGeometryType = GDAL.ogr_gfld_gettype(geomdefn.ptr) "Set the geometry type of this field." -function settype!(geomdefn::GeomFieldDefn, etype::OGRwkbGeometryType)::GeomFieldDefn +function settype!( + geomdefn::GeomFieldDefn, + etype::OGRwkbGeometryType, +)::GeomFieldDefn GDAL.ogr_gfld_settype(geomdefn.ptr, etype) return geomdefn end diff --git a/src/ogr/geometry.jl b/src/ogr/geometry.jl index 4ee4487e..0d4d4037 100644 --- a/src/ogr/geometry.jl +++ b/src/ogr/geometry.jl @@ -71,7 +71,8 @@ end fromWKT(data::String, args...)::IGeometry = fromWKT([data], args...) -unsafe_fromWKT(data::String, args...)::Geometry = unsafe_fromWKT([data], args...) +unsafe_fromWKT(data::String, args...)::Geometry = + unsafe_fromWKT([data], args...) """ Destroy geometry object. @@ -145,7 +146,9 @@ function forceto( targettype::OGRwkbGeometryType, options = StringList(C_NULL), )::IGeometry - return IGeometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options)) + return IGeometry( + GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options), + ) end function unsafe_forceto( @@ -153,7 +156,9 @@ function unsafe_forceto( targettype::OGRwkbGeometryType, options = StringList(C_NULL), )::Geometry - return Geometry(GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options)) + return Geometry( + GDAL.ogr_g_forceto(unsafe_clone(geom).ptr, targettype, options), + ) end """ @@ -175,7 +180,8 @@ Get the dimension of the coordinates in this geometry. ### Returns This will return 2 or 3. """ -getcoorddim(geom::AbstractGeometry)::Integer = GDAL.ogr_g_getcoordinatedimension(geom.ptr) +getcoorddim(geom::AbstractGeometry)::Integer = + GDAL.ogr_g_getcoordinatedimension(geom.ptr) """ setcoorddim!(geom::AbstractGeometry, dim::Integer) @@ -243,7 +249,10 @@ Convert a geometry well known binary format. * `geom`: handle on the geometry to convert to a well know binary data from. * `order`: One of wkbXDR or [wkbNDR] indicating MSB or LSB byte order resp. """ -function toWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = wkbNDR)::Vector{Cuchar} +function toWKB( + geom::AbstractGeometry, + order::OGRwkbByteOrder = wkbNDR, +)::Vector{Cuchar} buffer = Vector{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttowkb(geom.ptr, order, buffer) @ogrerr result "Failed to export geometry to WKB" @@ -259,7 +268,10 @@ Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format. * `geom`: handle on the geometry to convert to a well know binary data from. * `order`: One of wkbXDR or [wkbNDR] indicating MSB or LSB byte order resp. """ -function toISOWKB(geom::AbstractGeometry, order::OGRwkbByteOrder = wkbNDR)::Vector{Cuchar} +function toISOWKB( + geom::AbstractGeometry, + order::OGRwkbByteOrder = wkbNDR, +)::Vector{Cuchar} buffer = Array{Cuchar}(undef, wkbsize(geom)) result = GDAL.ogr_g_exporttoisowkb(geom.ptr, order, buffer) @ogrerr result "Failed to export geometry to ISO WKB" @@ -402,9 +414,11 @@ toJSON(geom::AbstractGeometry, options::Vector{String})::String = Create a geometry object from its GeoJSON representation. """ -fromJSON(data::String)::IGeometry = IGeometry(GDAL.ogr_g_creategeometryfromjson(data)) +fromJSON(data::String)::IGeometry = + IGeometry(GDAL.ogr_g_creategeometryfromjson(data)) -unsafe_fromJSON(data::String)::Geometry = Geometry(GDAL.ogr_g_creategeometryfromjson(data)) +unsafe_fromJSON(data::String)::Geometry = + Geometry(GDAL.ogr_g_creategeometryfromjson(data)) # """ # Assign spatial reference to this object. @@ -465,7 +479,10 @@ Apply arbitrary coordinate transformation to geometry. * `geom`: handle on the geometry to apply the transform to. * `coordtransform`: handle on the transformation to apply. """ -function transform!(geom::G, coordtransform::CoordTransform)::G where {G<:AbstractGeometry} +function transform!( + geom::G, + coordtransform::CoordTransform, +)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_transform(geom.ptr, coordtransform.ptr) @ogrerr result "Failed to transform geometry" return geom @@ -650,9 +667,11 @@ Returns the boundary of the geometry. A new geometry object is created and returned containing the boundary of the geometry on which the method is invoked. """ -boundary(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_boundary(geom.ptr)) +boundary(geom::AbstractGeometry)::IGeometry = + IGeometry(GDAL.ogr_g_boundary(geom.ptr)) -unsafe_boundary(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_boundary(geom.ptr)) +unsafe_boundary(geom::AbstractGeometry)::Geometry = + Geometry(GDAL.ogr_g_boundary(geom.ptr)) """ convexhull(geom::AbstractGeometry) @@ -662,7 +681,8 @@ Returns the convex hull of the geometry. A new geometry object is created and returned containing the convex hull of the geometry on which the method is invoked. """ -convexhull(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_convexhull(geom.ptr)) +convexhull(geom::AbstractGeometry)::IGeometry = + IGeometry(GDAL.ogr_g_convexhull(geom.ptr)) unsafe_convexhull(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_convexhull(geom.ptr)) @@ -693,7 +713,11 @@ accuracy of the result. buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30)::IGeometry = IGeometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) -function unsafe_buffer(geom::AbstractGeometry, dist::Real, quadsegs::Integer = 30)::Geometry +function unsafe_buffer( + geom::AbstractGeometry, + dist::Real, + quadsegs::Integer = 30, +)::Geometry return Geometry(GDAL.ogr_g_buffer(geom.ptr, dist, quadsegs)) end @@ -804,7 +828,10 @@ multipoint, linestring, geometrycollection such as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces (polygons). SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons). """ -function centroid!(geom::AbstractGeometry, centroid::G)::G where {G<:AbstractGeometry} +function centroid!( + geom::AbstractGeometry, + centroid::G, +)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_centroid(geom.ptr, centroid.ptr) @ogrerr result "Failed to compute the geometry centroid" return centroid @@ -905,7 +932,8 @@ reassembled Polygons: NULL will be returned if the input collection doesn't correspond to a MultiLinestring, or when reassembling Edges into Polygons is impossible due to topological inconsistencies. """ -polygonize(geom::AbstractGeometry)::IGeometry = IGeometry(GDAL.ogr_g_polygonize(geom.ptr)) +polygonize(geom::AbstractGeometry)::IGeometry = + IGeometry(GDAL.ogr_g_polygonize(geom.ptr)) unsafe_polygonize(geom::AbstractGeometry)::Geometry = Geometry(GDAL.ogr_g_polygonize(geom.ptr)) @@ -940,7 +968,6 @@ unsafe_polygonize(geom::AbstractGeometry)::Geometry = # nZStride) # end - """ getx(geom::AbstractGeometry, i::Integer) @@ -1018,7 +1045,12 @@ function setpoint!( return geom end -function setpoint!(geom::G, i::Integer, x::Real, y::Real)::G where {G<:AbstractGeometry} +function setpoint!( + geom::G, + i::Integer, + x::Real, + y::Real, +)::G where {G<:AbstractGeometry} GDAL.ogr_g_setpoint_2d(geom.ptr, i, x, y) return geom end @@ -1037,7 +1069,12 @@ Add a point to a geometry (line string or point). """ function addpoint! end -function addpoint!(geom::G, x::Real, y::Real, z::Real)::G where {G<:AbstractGeometry} +function addpoint!( + geom::G, + x::Real, + y::Real, + z::Real, +)::G where {G<:AbstractGeometry} GDAL.ogr_g_addpoint(geom.ptr, x, y, z) return geom end @@ -1075,7 +1112,6 @@ end # nYStride,pabyZ,nZStride) # end - """ ngeom(geom::AbstractGeometry) @@ -1091,7 +1127,7 @@ This corresponds to """ function ngeom(geom::AbstractGeometry)::Integer n = GDAL.ogr_g_getpointcount(geom.ptr) - n == 0 ? GDAL.ogr_g_getgeometrycount(geom.ptr) : n + return n == 0 ? GDAL.ogr_g_getgeometrycount(geom.ptr) : n end """ @@ -1222,7 +1258,10 @@ Remove all geometries from an exiting geometry container. The default is `true` as the existing geometry is considered to own the geometries in it. """ -function removeallgeoms!(geom::G, todelete::Bool = true)::G where {G<:AbstractGeometry} +function removeallgeoms!( + geom::G, + todelete::Bool = true, +)::G where {G<:AbstractGeometry} result = GDAL.ogr_g_removegeometry(geom.ptr, -1, todelete) @ogrerr result "Failed to remove all geometries." return geom @@ -1257,12 +1296,24 @@ MULTICURVE or MULTISURFACE in it, by approximating curve geometries. See OGRGeometryFactory::curveToLineString() for valid options. """ -function lineargeom(geom::AbstractGeometry, stepsize::Real = 0; kwargs...)::IGeometry +function lineargeom( + geom::AbstractGeometry, + stepsize::Real = 0; + kwargs..., +)::IGeometry return lineargeom(geom, String["$k=$v" for (k, v) in kwargs], stepsize) end -function unsafe_lineargeom(geom::AbstractGeometry, stepsize::Real = 0; kwargs...)::Geometry - return unsafe_lineargeom(geom, String["$k=$v" for (k, v) in kwargs], stepsize) +function unsafe_lineargeom( + geom::AbstractGeometry, + stepsize::Real = 0; + kwargs..., +)::Geometry + return unsafe_lineargeom( + geom, + String["$k=$v" for (k, v) in kwargs], + stepsize, + ) end function lineargeom( @@ -1323,7 +1374,13 @@ function polygonfromedges( autoclose::Bool = false, )::IGeometry perr = Ref{GDAL.OGRErr}() - result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, tol, perr) + result = GDAL.ogrbuildpolygonfromedges( + lines.ptr, + besteffort, + autoclose, + tol, + perr, + ) @ogrerr perr[] "Failed to build polygon from edges." return IGeometry(result) end @@ -1335,7 +1392,13 @@ function unsafe_polygonfromedges( autoclose::Bool = false, )::Geometry perr = Ref{GDAL.OGRErr}() - result = GDAL.ogrbuildpolygonfromedges(lines.ptr, besteffort, autoclose, tol, perr) + result = GDAL.ogrbuildpolygonfromedges( + lines.ptr, + besteffort, + autoclose, + tol, + perr, + ) @ogrerr perr[] "Failed to build polygon from edges." return Geometry(result) end @@ -1387,10 +1450,13 @@ for (geom, wkbgeom) in ( (:point, wkbPoint), (:polygon, wkbPolygon), ) - eval(quote - $(Symbol("create$geom"))()::IGeometry = creategeom($wkbgeom) - $(Symbol("unsafe_create$geom"))()::Geometry = unsafe_creategeom($wkbgeom) - end) + eval( + quote + $(Symbol("create$geom"))()::IGeometry = creategeom($wkbgeom) + $(Symbol("unsafe_create$geom"))()::Geometry = + unsafe_creategeom($wkbgeom) + end, + ) end for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) @@ -1411,7 +1477,11 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) ((:xs, :ys), (:(xs::Vector{Cdouble}), :(ys::Vector{Cdouble}))), ( (:xs, :ys, :zs), - (:(xs::Vector{Cdouble}), :(ys::Vector{Cdouble}), :(zs::Vector{Cdouble})), + ( + :(xs::Vector{Cdouble}), + :(ys::Vector{Cdouble}), + :(zs::Vector{Cdouble}), + ), ), ) for geom in (:linestring, :linearring) @@ -1427,33 +1497,45 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end for (geom, component) in ((:polygon, :linearring),) - eval(quote - function $(Symbol("$f$geom"))($(typedargs...))::$rt - geom = $(Symbol("$f$geom"))() - subgeom = $(Symbol("unsafe_create$component"))($(args...)) - result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) - @ogrerr result "Failed to add $component." - return geom - end - end) + eval( + quote + function $(Symbol("$f$geom"))($(typedargs...))::$rt + geom = $(Symbol("$f$geom"))() + subgeom = + $(Symbol("unsafe_create$component"))($(args...)) + result = GDAL.ogr_g_addgeometrydirectly( + geom.ptr, + subgeom.ptr, + ) + @ogrerr result "Failed to add $component." + return geom + end + end, + ) end for (geom, component) in ((:multipoint, :point),) - eval(quote - function $(Symbol("$f$geom"))($(typedargs...))::$rt - geom = $(Symbol("$f$geom"))() - for pt in zip($(args...)) - subgeom = $(Symbol("unsafe_create$component"))(pt) - result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) - @ogrerr result "Failed to add point." + eval( + quote + function $(Symbol("$f$geom"))($(typedargs...))::$rt + geom = $(Symbol("$f$geom"))() + for pt in zip($(args...)) + subgeom = $(Symbol("unsafe_create$component"))(pt) + result = GDAL.ogr_g_addgeometrydirectly( + geom.ptr, + subgeom.ptr, + ) + @ogrerr result "Failed to add point." + end + return geom end - return geom - end - end) + end, + ) end end - for typeargs in (Vector{<:Real}, Tuple{<:Real,<:Real}, Tuple{<:Real,<:Real,<:Real}) + for typeargs in + (Vector{<:Real}, Tuple{<:Real,<:Real}, Tuple{<:Real,<:Real,<:Real}) eval(quote function $(Symbol("$(f)point"))(coords::$typeargs)::$rt geom = $(Symbol("$(f)point"))() @@ -1481,15 +1563,20 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) end for (geom, component) in ((:polygon, :linearring),) - eval(quote - function $(Symbol("$f$geom"))(coords::$typeargs)::$rt - geom = $(Symbol("$f$geom"))() - subgeom = $(Symbol("unsafe_create$component"))(coords) - result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) - @ogrerr result "Failed to add $component." - return geom - end - end) + eval( + quote + function $(Symbol("$f$geom"))(coords::$typeargs)::$rt + geom = $(Symbol("$f$geom"))() + subgeom = $(Symbol("unsafe_create$component"))(coords) + result = GDAL.ogr_g_addgeometrydirectly( + geom.ptr, + subgeom.ptr, + ) + @ogrerr result "Failed to add $component." + return geom + end + end, + ) end end @@ -1524,17 +1611,23 @@ for (f, rt) in ((:create, :IGeometry), (:unsafe_create, :Geometry)) ), ) for typearg in typeargs, (geom, component) in variants - eval(quote - function $(Symbol("$f$geom"))(coords::$typearg)::$rt - geom = $(Symbol("$f$geom"))() - for coord in coords - subgeom = $(Symbol("unsafe_create$component"))(coord) - result = GDAL.ogr_g_addgeometrydirectly(geom.ptr, subgeom.ptr) - @ogrerr result "Failed to add $component." + eval( + quote + function $(Symbol("$f$geom"))(coords::$typearg)::$rt + geom = $(Symbol("$f$geom"))() + for coord in coords + subgeom = + $(Symbol("unsafe_create$component"))(coord) + result = GDAL.ogr_g_addgeometrydirectly( + geom.ptr, + subgeom.ptr, + ) + @ogrerr result "Failed to add $component." + end + return geom end - return geom - end - end) + end, + ) end end end diff --git a/src/ogr/styletable.jl b/src/ogr/styletable.jl index b348727f..3f94b9ff 100644 --- a/src/ogr/styletable.jl +++ b/src/ogr/styletable.jl @@ -9,7 +9,9 @@ OGRStyleMgr factory. ### Returns an handle to the new style manager object. """ -function unsafe_createstylemanager(styletable::StyleTable = StyleTable())::StyleManager +function unsafe_createstylemanager( + styletable::StyleTable = StyleTable(), +)::StyleManager return StyleManager(GDAL.ogr_sm_create(styletable.ptr)) end @@ -84,7 +86,7 @@ function unsafe_getpart( id::Integer, stylestring = C_NULL, )::StyleTool - StyleTool(GDAL.ogr_sm_getpart(stylemanager.ptr, id, stylestring)) + return StyleTool(GDAL.ogr_sm_getpart(stylemanager.ptr, id, stylestring)) end """ @@ -191,7 +193,11 @@ Set Style Tool units. * `newunit`: the new unit. * `scale`: ground to paper scale factor. """ -function setunit!(styletool::StyleTool, newunit::OGRSTUnitId, scale::Real)::StyleTool +function setunit!( + styletool::StyleTool, + newunit::OGRSTUnitId, + scale::Real, +)::StyleTool GDAL.ogr_st_setunit(styletool.ptr, newunit, scale) return styletool end @@ -216,7 +222,8 @@ the parameter value as a string and sets `nullflag`. asstring(styletool::StyleTool, id::Integer, nullflag::Ref{Cint})::String = GDAL.ogr_st_getparamstr(styletool.ptr, id, nullflag) -asstring(styletool::StyleTool, id::Integer)::String = asstring(styletool, id, Ref{Cint}(0)) +asstring(styletool::StyleTool, id::Integer)::String = + asstring(styletool, id, Ref{Cint}(0)) """ asint(styletool::StyleTool, id::Integer, nullflag = Ref{Cint}(0)) @@ -234,7 +241,11 @@ Get Style Tool parameter value as an integer. ### Returns the parameter value as an integer and sets `nullflag`. """ -function asint(styletool::StyleTool, id::Integer, nullflag::Ref{Cint} = Ref{Cint}(0))::Int32 +function asint( + styletool::StyleTool, + id::Integer, + nullflag::Ref{Cint} = Ref{Cint}(0), +)::Int32 return GDAL.ogr_st_getparamnum(styletool.ptr, id, nullflag) end @@ -276,7 +287,11 @@ Set Style Tool parameter value. """ function setparam! end -function setparam!(styletool::StyleTool, id::Integer, value::AbstractString)::StyleTool +function setparam!( + styletool::StyleTool, + id::Integer, + value::AbstractString, +)::StyleTool GDAL.ogr_st_setparamstr(styletool.ptr, id, value) return styletool end @@ -302,7 +317,8 @@ Get the style string for this Style Tool. ### Returns the style string for this style tool or "" if the styletool is invalid. """ -getstylestring(styletool::StyleTool)::String = GDAL.ogr_st_getstylestring(styletool.ptr) +getstylestring(styletool::StyleTool)::String = + GDAL.ogr_st_getstylestring(styletool.ptr) """ toRGBA(styletool::StyleTool, color::AbstractString) @@ -316,13 +332,24 @@ Return the r,g,b,a components of a color encoded in #RRGGBB[AA] format. ### Returns (R,G,B,A) tuple of Cints. """ -function toRGBA(styletool::StyleTool, color::AbstractString)::Tuple{Int32,Int32,Int32,Int32} +function toRGBA( + styletool::StyleTool, + color::AbstractString, +)::Tuple{Int32,Int32,Int32,Int32} red = Ref{Int32}(0) green = Ref{Int32}(0) blue = Ref{Int32}(0) alpha = Ref{Int32}(0) - result = - Bool(GDAL.ogr_st_getrgbfromstring(styletool.ptr, color, red, green, blue, alpha)) + result = Bool( + GDAL.ogr_st_getrgbfromstring( + styletool.ptr, + color, + red, + green, + blue, + alpha, + ), + ) result || error("Error in getting RGBA from Styletool") return (red[], green[], blue[], alpha[]) end @@ -439,7 +466,8 @@ Get the next style string from the table. ### Returns the next style string or NULL on error. """ -nextstyle(styletable::StyleTable)::String = GDAL.ogr_stbl_getnextstyle(styletable.ptr) +nextstyle(styletable::StyleTable)::String = + GDAL.ogr_stbl_getnextstyle(styletable.ptr) """ laststyle(styletable::StyleTable) @@ -452,4 +480,5 @@ Get the style name of the last style string fetched with OGR_STBL_GetNextStyle. ### Returns the Name of the last style string or NULL on error. """ -laststyle(styletable::StyleTable)::String = GDAL.ogr_stbl_getlaststylename(styletable.ptr) +laststyle(styletable::StyleTable)::String = + GDAL.ogr_stbl_getlaststylename(styletable.ptr) diff --git a/src/raster/array.jl b/src/raster/array.jl index 69f00f2e..b237d401 100644 --- a/src/raster/array.jl +++ b/src/raster/array.jl @@ -26,7 +26,9 @@ struct RasterDataset{T,DS<:AbstractDataset} <: AbstractDiskArray{T,3} size::Tuple{Int,Int,Int} end -function RasterDataset(ds::AbstractDataset)::RasterDataset{pixeltype(ds),typeof(ds)} +function RasterDataset( + ds::AbstractDataset, +)::RasterDataset{pixeltype(ds),typeof(ds)} if iszero(nraster(ds)) throw(ArgumentError("The Dataset does not contain any raster bands")) end @@ -58,7 +60,9 @@ for f in ( :metadata, :metadatadomainlist, ) - eval(:($(f)(x::RasterDataset, args...; kwargs...) = $(f)(x.ds, args...; kwargs...))) + eval(:(function $(f)(x::RasterDataset, args...; kwargs...) + return $(f)(x.ds, args...; kwargs...) + end)) end # Here we need to special-case, to avoid a method ambiguity @@ -104,7 +108,7 @@ function _common_size(ds::AbstractDataset) nr = nraster(ds) allsizes = map(1:nr) do i b = getband(ds, i) - size(b) + return size(b) end s = unique(allsizes) if length(s) != 1 @@ -129,7 +133,8 @@ function returns a `RasterDataset`, which is a subtype of `AbstractDiskArray{T,3}`, so that users can operate on the array using direct indexing. """ -readraster(s::String; kwargs...)::RasterDataset = RasterDataset(read(s; kwargs...)) +readraster(s::String; kwargs...)::RasterDataset = + RasterDataset(read(s; kwargs...)) function DiskArrays.eachchunk(ds::RasterDataset)::DiskArrays.GridChunks subchunks = DiskArrays.eachchunk(getband(ds, 1)) @@ -137,10 +142,12 @@ function DiskArrays.eachchunk(ds::RasterDataset)::DiskArrays.GridChunks end DiskArrays.haschunks(::RasterDataset)::DiskArrays.Chunked = DiskArrays.Chunked() -DiskArrays.haschunks(::AbstractRasterBand)::DiskArrays.Chunked = DiskArrays.Chunked() +DiskArrays.haschunks(::AbstractRasterBand)::DiskArrays.Chunked = + DiskArrays.Chunked() -Base.size(band::AbstractRasterBand)::Tuple{T,T} where {T<:Integer} = - (width(band), height(band)) +function Base.size(band::AbstractRasterBand) + return (width(band), height(band)) +end function DiskArrays.eachchunk(band::AbstractRasterBand)::DiskArrays.GridChunks wI = windows(band) @@ -172,7 +179,6 @@ function DiskArrays.writeblock!( return buffer end - # AbstractDataset indexing Base.size(dataset::RasterDataset)::Tuple{Int,Int,Int} = dataset.size diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index e428efdf..7b6bb0f3 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -34,4 +34,5 @@ Fetch palette interpretation. ### Returns palette interpretation enumeration value, usually `GPI_RGB`. """ -paletteinterp(ct::ColorTable)::GDALPaletteInterp = GDAL.gdalgetpaletteinterpretation(ct.ptr) +paletteinterp(ct::ColorTable)::GDALPaletteInterp = + GDAL.gdalgetpaletteinterpretation(ct.ptr) diff --git a/src/raster/images.jl b/src/raster/images.jl index ba96e187..3bddcaad 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -1,6 +1,6 @@ function imread(colortable::ColorTable, dataset::AbstractDataset, indices) palette = getcolortable(getband(dataset, indices[1])) do ct - paletteinterp(ct) + return paletteinterp(ct) end colortype = if palette == GPI_Gray ColorTypes.Gray @@ -21,7 +21,10 @@ function imread( indices::NTuple{1,<:Integer}, ) return ImageCore.PermutedDimsArray( - ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, indices[1]))), + ImageCore.colorview( + colortype, + ImageCore.normedview(read(dataset, indices[1])), + ), (2, 1), ) end @@ -60,13 +63,15 @@ function imread( end function imread(dataset::AbstractDataset, indices) - gci = unique(GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices]) + gci = unique( + GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices], + ) gciorder = sort(gci) return if gciorder == [GCI_GrayIndex] imread(ColorTypes.Gray, dataset, Tuple(indices[sortperm(gci)])) elseif gciorder == [GCI_PaletteIndex] getcolortable(getband(dataset, 1)) do ct - imread(ct, dataset, indices) + return imread(ct, dataset, indices) end elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand] imread(ColorTypes.RGB, dataset, Tuple(indices[sortperm(gci)])) @@ -84,6 +89,6 @@ imread(dataset::AbstractDataset) = imread(dataset, 1:nraster(dataset)) function imread(filename::String) return read(filename) do dataset - imread(dataset) + return imread(dataset) end end diff --git a/src/raster/rasterattributetable.jl b/src/raster/rasterattributetable.jl index 05c36ecd..dca5e62a 100644 --- a/src/raster/rasterattributetable.jl +++ b/src/raster/rasterattributetable.jl @@ -3,14 +3,16 @@ Construct empty table. """ -unsafe_createRAT()::RasterAttrTable = RasterAttrTable(GDAL.gdalcreaterasterattributetable()) +unsafe_createRAT()::RasterAttrTable = + RasterAttrTable(GDAL.gdalcreaterasterattributetable()) """ unsafe_createRAT(ct::ColorTable) Construct table from an existing colortable. """ -unsafe_createRAT(ct::ColorTable)::RasterAttrTable = initializeRAT!(unsafe_createRAT(), ct) +unsafe_createRAT(ct::ColorTable)::RasterAttrTable = + initializeRAT!(unsafe_createRAT(), ct) "Destroys a RAT." function destroy(rat::RasterAttrTable)::Nothing @@ -37,7 +39,8 @@ Fetch name of indicated column. ### Returns the column name or an empty string for invalid column numbers. """ -columnname(rat::RasterAttrTable, i::Integer)::String = GDAL.gdalratgetnameofcol(rat.ptr, i) +columnname(rat::RasterAttrTable, i::Integer)::String = + GDAL.gdalratgetnameofcol(rat.ptr, i) """ columnusage(rat::RasterAttrTable, i::Integer) @@ -208,7 +211,14 @@ function attributeio!( nrows::Integer, data::Vector{Float64}, )::Vector{Float64} - result = GDAL.gdalratvaluesioasdouble(rat.ptr, access, col, startrow, nrows, data) + result = GDAL.gdalratvaluesioasdouble( + rat.ptr, + access, + col, + startrow, + nrows, + data, + ) @cplerr result "Failed to $access at column $col starting at $startrow" return data end @@ -221,7 +231,14 @@ function attributeio!( nrows::Integer, data::Vector{Cint}, )::Vector{Cint} - result = GDAL.gdalratvaluesioasinteger(rat.ptr, access, col, startrow, nrows, data) + result = GDAL.gdalratvaluesioasinteger( + rat.ptr, + access, + col, + startrow, + nrows, + data, + ) @cplerr result "Failed to $access at column $col starting at $startrow" return data end @@ -234,7 +251,14 @@ function attributeio!( nrows::Integer, data::Vector{T}, )::Vector{T} where {T<:AbstractString} - result = GDAL.gdalratvaluesioasstring(rat.ptr, access, col, startrow, nrows, data) + result = GDAL.gdalratvaluesioasstring( + rat.ptr, + access, + col, + startrow, + nrows, + data, + ) @cplerr result "Failed to $access at column $col starting at $startrow" return data end @@ -330,7 +354,10 @@ The raster attribute table must be empty before calling `initializeRAT!()`. The Value fields are set based on the implicit assumption with color tables that entry 0 applies to pixel value 0, 1 to 1, etc. """ -function initializeRAT!(rat::RasterAttrTable, colortable::ColorTable)::RasterAttrTable +function initializeRAT!( + rat::RasterAttrTable, + colortable::ColorTable, +)::RasterAttrTable result = GDAL.gdalratinitializefromcolortable(rat.ptr, colortable.ptr) @cplerr result "Failed to initialize RAT from color table" return rat diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 07782f56..e6571c46 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -56,14 +56,16 @@ width(band::AbstractRasterBand)::Integer = GDAL.gdalgetrasterbandxsize(band.ptr) Fetch the height in pixels of this band. """ -height(band::AbstractRasterBand)::Integer = GDAL.gdalgetrasterbandysize(band.ptr) +height(band::AbstractRasterBand)::Integer = + GDAL.gdalgetrasterbandysize(band.ptr) """ accessflag(band::AbstractRasterBand) Return the access flag (e.g. `OF_READONLY` or `OF_UPDATE`) for this band. """ -accessflag(band::AbstractRasterBand)::GDALAccess = GDAL.gdalgetrasteraccess(band.ptr) +accessflag(band::AbstractRasterBand)::GDALAccess = + GDAL.gdalgetrasteraccess(band.ptr) """ indexof(band::AbstractRasterBand) @@ -83,7 +85,8 @@ Fetch the handle to its dataset handle, or `NULL` if this cannot be determined. Note that some `RasterBand`s are not considered to be a part of a dataset, such as overviews or other "freestanding" bands. """ -getdataset(band::AbstractRasterBand)::Dataset = Dataset(GDAL.gdalgetbanddataset(band.ptr)) +getdataset(band::AbstractRasterBand)::Dataset = + Dataset(GDAL.gdalgetbanddataset(band.ptr)) # ↑ GDAL wrapper checks null by default, but it is a valid result in this case """ @@ -92,7 +95,8 @@ getdataset(band::AbstractRasterBand)::Dataset = Dataset(GDAL.gdalgetbanddataset( Return a name for the units of this raster's values. For instance, it might be "m" for an elevation model in meters, or "ft" for feet. """ -getunittype(band::AbstractRasterBand)::String = GDAL.gdalgetrasterunittype(band.ptr) +getunittype(band::AbstractRasterBand)::String = + GDAL.gdalgetrasterunittype(band.ptr) """ setunittype!(band::AbstractRasterBand, unitstring::AbstractString) @@ -103,7 +107,10 @@ Values should be one of \"\" (the default indicating it is unknown), \"m\" indicating meters, or \"ft\" indicating feet, though other nonstandard values are allowed. """ -function setunittype!(band::T, unitstring::AbstractString)::T where {T<:AbstractRasterBand} +function setunittype!( + band::T, + unitstring::AbstractString, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrasterunittype(band.ptr, unitstring) @cplerr result "Failed to set unit type" return band @@ -122,7 +129,8 @@ elevations in `GUInt16` bands with a precision of 0.1, starting from -100. For file formats that don't know this intrinsically, a value of 0 is returned. """ -getoffset(band::AbstractRasterBand)::Real = GDAL.gdalgetrasteroffset(band.ptr, C_NULL) +getoffset(band::AbstractRasterBand)::Real = + GDAL.gdalgetrasteroffset(band.ptr, C_NULL) """ setoffset!(band::AbstractRasterBand, value::Real) @@ -149,7 +157,8 @@ and starting from -100. For file formats that don't know this intrinsically a value of one is returned. """ -getscale(band::AbstractRasterBand)::Real = GDAL.gdalgetrasterscale(band.ptr, C_NULL) +getscale(band::AbstractRasterBand)::Real = + GDAL.gdalgetrasterscale(band.ptr, C_NULL) """ setscale!(band::AbstractRasterBand, ratio::Real) @@ -210,14 +219,16 @@ end Fetch the minimum value for this band. """ -minimum(band::AbstractRasterBand)::Real = GDAL.gdalgetrasterminimum(band.ptr, C_NULL) +minimum(band::AbstractRasterBand)::Real = + GDAL.gdalgetrasterminimum(band.ptr, C_NULL) """ maximum(band::AbstractRasterBand) Fetch the maximum value for this band. """ -maximum(band::AbstractRasterBand)::Real = GDAL.gdalgetrastermaximum(band.ptr, C_NULL) +maximum(band::AbstractRasterBand)::Real = + GDAL.gdalgetrastermaximum(band.ptr, C_NULL) """ getdefaultRAT(band::AbstractRasterBand) @@ -238,7 +249,10 @@ Associates a default RAT with the band. If not implemented for the format a CPLE_NotSupported error will be issued. If successful a copy of the RAT is made, the original remains owned by the caller. """ -function setdefaultRAT!(band::T, rat::RasterAttrTable)::T where {T<:AbstractRasterBand} +function setdefaultRAT!( + band::T, + rat::RasterAttrTable, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetdefaultrat(band.ptr, rat.ptr) @cplerr result "Failed to set default raster attribute table" return band @@ -291,7 +305,8 @@ end Return the number of overview layers available, zero if none. """ -noverview(band::AbstractRasterBand)::Integer = GDAL.gdalgetoverviewcount(band.ptr) +noverview(band::AbstractRasterBand)::Integer = + GDAL.gdalgetoverviewcount(band.ptr) """ getoverview(band::IRasterBand, i::Integer) @@ -338,7 +353,10 @@ getcolorinterp(band::AbstractRasterBand)::GDALColorInterp = Set color interpretation of a band. """ -function setcolorinterp!(band::T, color::GDALColorInterp)::T where {T<:AbstractRasterBand} +function setcolorinterp!( + band::T, + color::GDALColorInterp, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercolorinterpretation(band.ptr, color) @cplerr result "Failed to set color interpretation" return band @@ -367,7 +385,10 @@ owned by the caller after the call. ### Parameters * `colortable` color table to apply (where supported). """ -function setcolortable!(band::T, colortable::ColorTable)::T where {T<:AbstractRasterBand} +function setcolortable!( + band::T, + colortable::ColorTable, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercolortable(band.ptr, colortable.ptr) @cplwarn result "CPLError $(result): action is unsupported by the driver" return band @@ -415,7 +436,8 @@ function regenerateoverviews!( # progressfunc::Function = GDAL.gdaldummyprogress, progressdata = C_NULL, )::T where {T<:AbstractRasterBand} - cfunc = @cfunction(GDAL.gdaldummyprogress, Cint, (Cdouble, Cstring, Ptr{Cvoid})) + cfunc = + @cfunction(GDAL.gdaldummyprogress, Cint, (Cdouble, Cstring, Ptr{Cvoid})) result = GDAL.gdalregenerateoverviews( band.ptr, length(overviewbands), @@ -459,7 +481,10 @@ getcategorynames(band::AbstractRasterBand)::Vector{String} = Set the category names for this band. """ -function setcategorynames!(band::T, names::Vector{String})::T where {T<:AbstractRasterBand} +function setcategorynames!( + band::T, + names::Vector{String}, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalsetrastercategorynames(band.ptr, names) @cplerr result "Failed to set category names for this band" return band @@ -581,7 +606,6 @@ a valid mask band. """ maskflags(band::AbstractRasterBand)::Cint = GDAL.gdalgetmaskflags(band.ptr) - """ maskflaginfo(band::AbstractRasterBand) @@ -627,7 +651,10 @@ invalidated by `CreateMaskBand()`. So you have to call `GetMaskBand()` again. See also: http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask """ -function createmaskband!(band::T, nflags::Integer)::T where {T<:AbstractRasterBand} +function createmaskband!( + band::T, + nflags::Integer, +)::T where {T<:AbstractRasterBand} result = GDAL.gdalcreatemaskband(band.ptr, nflags) @cplerr result "Failed to create mask band" return band diff --git a/src/raster/rasterio.jl b/src/raster/rasterio.jl index 0b45401a..41f45fd8 100644 --- a/src/raster/rasterio.jl +++ b/src/raster/rasterio.jl @@ -282,8 +282,9 @@ function read!( return buffer end -read(rb::AbstractRasterBand) = - rasterio!(rb, Array{pixeltype(rb)}(undef, width(rb), height(rb))) +function read(rb::AbstractRasterBand) + return rasterio!(rb, Array{pixeltype(rb)}(undef, width(rb), height(rb))) +end function read( rb::AbstractRasterBand, @@ -329,12 +330,20 @@ function write!( return buffer end -function read!(dataset::AbstractDataset, buffer::T, i::Integer)::T where {T<:Matrix{<:Any}} +function read!( + dataset::AbstractDataset, + buffer::T, + i::Integer, +)::T where {T<:Matrix{<:Any}} read!(getband(dataset, i), buffer) return buffer end -function read!(dataset::AbstractDataset, buffer::T, indices)::T where {T<:Array{<:Any,3}} +function read!( + dataset::AbstractDataset, + buffer::T, + indices, +)::T where {T<:Array{<:Any,3}} rasterio!(dataset, buffer, indices, GF_Read) return buffer end @@ -397,15 +406,23 @@ end read(dataset::AbstractDataset, i::Integer) = read(getband(dataset, i)) function read(dataset::AbstractDataset, indices)::Array{pixeltype(dataset),3} - buffer = - Array{pixeltype(dataset)}(undef, width(dataset), height(dataset), length(indices)) + buffer = Array{pixeltype(dataset)}( + undef, + width(dataset), + height(dataset), + length(indices), + ) rasterio!(dataset, buffer, indices) return buffer end function read(dataset::AbstractDataset)::Array{pixeltype(dataset),3} - buffer = - Array{pixeltype(dataset)}(undef, width(dataset), height(dataset), nraster(dataset)) + buffer = Array{pixeltype(dataset)}( + undef, + width(dataset), + height(dataset), + nraster(dataset), + ) read!(dataset, buffer) return buffer end @@ -453,7 +470,12 @@ function read( rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, )::Array{pixeltype(dataset),3} - buffer = Array{pixeltype(dataset),3}(undef, length(cols), length(rows), length(indices)) + buffer = Array{pixeltype(dataset),3}( + undef, + length(cols), + length(rows), + length(indices), + ) rasterio!(dataset, buffer, indices, rows, cols) return buffer end @@ -480,7 +502,16 @@ function write!( xsize::Integer, ysize::Integer, )::T where {T<:AbstractDataset} - rasterio!(dataset, buffer, indices, xoffset, yoffset, xsize, ysize, GF_Write) + rasterio!( + dataset, + buffer, + indices, + xoffset, + yoffset, + xsize, + ysize, + GF_Write, + ) return dataset end diff --git a/src/spatialref.jl b/src/spatialref.jl index faef8360..d8ebbe2c 100644 --- a/src/spatialref.jl +++ b/src/spatialref.jl @@ -27,17 +27,26 @@ function importCRS!(spref::T, x::GFT.EPSG)::T where {T<:AbstractSpatialRef} return spref end -function importCRS!(spref::T, x::GFT.AbstractWellKnownText)::T where {T<:AbstractSpatialRef} +function importCRS!( + spref::T, + x::GFT.AbstractWellKnownText, +)::T where {T<:AbstractSpatialRef} importWKT!(spref, GFT.val(x)) return spref end -function importCRS!(spref::T, x::GFT.ESRIWellKnownText)::T where {T<:AbstractSpatialRef} +function importCRS!( + spref::T, + x::GFT.ESRIWellKnownText, +)::T where {T<:AbstractSpatialRef} importESRI!(spref, GFT.val(x)) return spref end -function importCRS!(spref::T, x::GFT.ProjString)::T where {T<:AbstractSpatialRef} +function importCRS!( + spref::T, + x::GFT.ProjString, +)::T where {T<:AbstractSpatialRef} importPROJ4!(spref, GFT.val(x)) return spref end @@ -115,7 +124,12 @@ function reproject( kwargs..., ) return GeoInterface.coordinates.( - reproject([createpoint(c...) for c in coords], sourcecrs, targetcrs; kwargs...), + reproject( + [createpoint(c...) for c in coords], + sourcecrs, + targetcrs; + kwargs..., + ), ) end @@ -140,7 +154,7 @@ function reproject( kwargs..., ) return crs2transform(sourcecrs, targetcrs; kwargs...) do transform - transform!(geom, transform) + return transform!(geom, transform) end end @@ -151,7 +165,7 @@ function reproject( kwargs..., ) return crs2transform(sourcecrs, targetcrs; kwargs...) do transform - transform!.(geoms, Ref(transform)) + return transform!.(geoms, Ref(transform)) end end @@ -174,7 +188,7 @@ function crs2transform( return importCRS(sourcecrs; kwargs...) do sourcecrs_ref importCRS(targetcrs; kwargs...) do targetcrs_ref createcoordtrans(sourcecrs_ref, targetcrs_ref) do transform - f(transform) + return f(transform) end end end @@ -190,17 +204,38 @@ Construct a Spatial Reference System from its WKT. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) = - maybesetaxisorder!(ISpatialRef(GDAL.osrnewspatialreference(wkt)), order) +function newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) + return maybesetaxisorder!( + ISpatialRef(GDAL.osrnewspatialreference(wkt)), + order, + ) +end -unsafe_newspatialref(wkt::AbstractString = ""; order::Symbol = :compliant) = - maybesetaxisorder!(SpatialRef(GDAL.osrnewspatialreference(wkt)), order) +function unsafe_newspatialref( + wkt::AbstractString = ""; + order::Symbol = :compliant, +) + return maybesetaxisorder!( + SpatialRef(GDAL.osrnewspatialreference(wkt)), + order, + ) +end -function maybesetaxisorder!(spref::T, order::Symbol)::T where {T<:AbstractSpatialRef} +function maybesetaxisorder!( + spref::T, + order::Symbol, +)::T where {T<:AbstractSpatialRef} if order == :trad - GDAL.osrsetaxismappingstrategy(spref.ptr, GDAL.OAMS_TRADITIONAL_GIS_ORDER) + GDAL.osrsetaxismappingstrategy( + spref.ptr, + GDAL.OAMS_TRADITIONAL_GIS_ORDER, + ) elseif order != :compliant - throw(ArgumentError("order $order is not supported. Use :trad or :compliant")) + throw( + ArgumentError( + "order $order is not supported. Use :trad or :compliant", + ), + ) end return spref end @@ -330,7 +365,10 @@ contents of the passed WKT string. Only as much of the input string as needed to construct this SRS is consumed from the input string, and the input string pointer is then updated to point to the remaining (unused) input. """ -function importWKT!(spref::T, wktstr::AbstractString)::T where {T<:AbstractSpatialRef} +function importWKT!( + spref::T, + wktstr::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromwkt(spref.ptr, [wktstr]) @ogrerr result "Failed to initialize SRS based on WKT string" return spref @@ -346,7 +384,8 @@ Create SRS from its WKT string. axis ordering in any actions done with the crs. `:compliant`, will use axis ordering compliant with the relevant CRS authority. """ -importWKT(wktstr::AbstractString; kwargs...)::ISpatialRef = newspatialref(wktstr; kwargs...) +importWKT(wktstr::AbstractString; kwargs...)::ISpatialRef = + newspatialref(wktstr; kwargs...) unsafe_importWKT(wktstr::AbstractString; kwargs...)::SpatialRef = unsafe_newspatialref(wktstr; kwargs...) @@ -373,7 +412,10 @@ back to PROJ.4 format\". For example: `\"+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext\"` """ -function importPROJ4!(spref::T, projstr::AbstractString)::T where {T<:AbstractSpatialRef} +function importPROJ4!( + spref::T, + projstr::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromproj4(spref.ptr, projstr) @ogrerr result "Failed to initialize SRS based on PROJ4 string" return spref @@ -417,7 +459,10 @@ At this time there is no equivalent `exportToESRI()` method. Writing old style and `exportToWkt()` methods can be used to generate output suitable to write to new style (Arc 8) .prj files. """ -function importESRI!(spref::T, esristr::AbstractString)::T where {T<:AbstractSpatialRef} +function importESRI!( + spref::T, + esristr::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromesri(spref.ptr, [esristr]) @ogrerr result "Failed to initialize SRS based on ESRI string" return spref @@ -442,7 +487,10 @@ unsafe_importESRI(esristr::AbstractString; kwargs...)::SpatialRef = Import SRS from XML format (GML only currently). """ -function importXML!(spref::T, xmlstr::AbstractString)::T where {T<:AbstractSpatialRef} +function importXML!( + spref::T, + xmlstr::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromxml(spref.ptr, xmlstr) @ogrerr result "Failed to initialize SRS based on XML string" return spref @@ -475,7 +523,10 @@ Set spatial reference from a URL. This method will download the spatial reference at a given URL and feed it into SetFromUserInput for you. """ -function importURL!(spref::T, url::AbstractString)::T where {T<:AbstractSpatialRef} +function importURL!( + spref::T, + url::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrimportfromurl(spref.ptr, url) @ogrerr result "Failed to initialize SRS from URL" return spref @@ -644,7 +695,10 @@ function setattrvalue!( return spref end -function setattrvalue!(spref::T, path::AbstractString)::T where {T<:AbstractSpatialRef} +function setattrvalue!( + spref::T, + path::AbstractString, +)::T where {T<:AbstractSpatialRef} result = GDAL.osrsetattrvalue(spref.ptr, path, C_NULL) @ogrerr result "Failed to set attribute path" return spref @@ -692,7 +746,9 @@ function unsafe_createcoordtrans( source::AbstractSpatialRef, target::AbstractSpatialRef, )::CoordTransform - return CoordTransform(GDAL.octnewcoordinatetransformation(source.ptr, target.ptr)) + return CoordTransform( + GDAL.octnewcoordinatetransformation(source.ptr, target.ptr), + ) end "OGRCoordinateTransformation destructor." diff --git a/src/tables.jl b/src/tables.jl index 6f6a9c12..64bdb2b5 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -8,12 +8,17 @@ struct Table{T<:AbstractFeatureLayer} end function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema - field_names, geom_names, featuredefn, fielddefns = schema_names(layerdefn(layer)) + field_names, geom_names, featuredefn, fielddefns = + schema_names(layerdefn(layer)) ngeom = ArchGDAL.ngeom(featuredefn) - geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i = 0:ngeom-1) - field_types = (convert(DataType, gettype(fielddefn)) for fielddefn in fielddefns) - geom_types = (IGeometry for i = 1:ngeom) - Tables.Schema((field_names..., geom_names...), (field_types..., geom_types...)) + geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) + field_types = + (convert(DataType, gettype(fielddefn)) for fielddefn in fielddefns) + geom_types = (IGeometry for i in 1:ngeom) + return Tables.Schema( + (field_names..., geom_names...), + (field_types..., geom_types...), + ) end Tables.istable(::Type{<:Table})::Bool = true @@ -45,20 +50,24 @@ function Tables.getcolumn(row::Feature, name::Symbol) return nothing end -function Tables.columnnames(row::Feature)::NTuple{Int64(nfield(row) + ngeom(row)),Symbol} +function Tables.columnnames( + row::Feature, +)::NTuple{Int64(nfield(row) + ngeom(row)),Symbol} field_names, geom_names = schema_names(getfeaturedefn(row)) return (field_names..., geom_names...) end function schema_names(featuredefn::IFeatureDefnView) - fielddefns = (getfielddefn(featuredefn, i) for i = 0:nfield(featuredefn)-1) + fielddefns = (getfielddefn(featuredefn, i) for i in 0:nfield(featuredefn)-1) field_names = (Symbol(getname(fielddefn)) for fielddefn in fielddefns) - geom_names = - (Symbol(getname(getgeomdefn(featuredefn, i - 1))) for i = 1:ngeom(featuredefn)) + geom_names = ( + Symbol(getname(getgeomdefn(featuredefn, i - 1))) for + i in 1:ngeom(featuredefn) + ) return (field_names, geom_names, featuredefn, fielddefns) end function Base.show(io::IO, t::Table) - println(io, "Table with $(nfeature(t.layer)) features") + return println(io, "Table with $(nfeature(t.layer)) features") end Base.show(io::IO, ::MIME"text/plain", t::Table) = show(io, t) diff --git a/src/types.jl b/src/types.jl index 1f7fdbe4..ed9696aa 100644 --- a/src/types.jl +++ b/src/types.jl @@ -370,7 +370,13 @@ eval( ) ) -eval(@convert(GDALRWFlag::GDAL.GDALRWFlag, GF_Read::GDAL.GF_Read, GF_Write::GDAL.GF_Write,)) +eval( + @convert( + GDALRWFlag::GDAL.GDALRWFlag, + GF_Read::GDAL.GF_Read, + GF_Write::GDAL.GF_Write, + ) +) eval( @convert( @@ -583,7 +589,8 @@ iscomplex(dtype::GDALDataType)::Bool = Bool(GDAL.gdaldatatypeiscomplex(dtype)) Get name of AsyncStatus data type. """ -getname(dtype::GDALAsyncStatusType)::String = GDAL.gdalgetasyncstatustypename(dtype) +getname(dtype::GDALAsyncStatusType)::String = + GDAL.gdalgetasyncstatustypename(dtype) """ asyncstatustype(name::AbstractString) @@ -613,7 +620,8 @@ colorinterp(name::AbstractString)::GDALColorInterp = Get name of palette interpretation. """ -getname(obj::GDALPaletteInterp)::String = GDAL.gdalgetpaletteinterpretationname(obj) +getname(obj::GDALPaletteInterp)::String = + GDAL.gdalgetpaletteinterpretationname(obj) """ getname(obj::OGRFieldType) diff --git a/src/utils.jl b/src/utils.jl index 324ca719..526b3a30 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -26,19 +26,20 @@ macro convert(args...) type1 = esc(args[1].args[1]) type2 = esc(args[1].args[2]) forward_map = Expr[Expr(:tuple, esc.(a.args)...) for a in args[2:end]] - reverse_map = Expr[Expr(:tuple, esc.(reverse(a.args))...) for a in args[2:end]] + reverse_map = + Expr[Expr(:tuple, esc.(reverse(a.args))...) for a in args[2:end]] quote function Base.convert(::Type{$type2}, ft::$type1) fwd = Dict{$type1,$type2}(Tuple{$type1,$type2}[$(forward_map...)]) return get(fwd, ft) do - error("Unknown type: $ft") + return error("Unknown type: $ft") end end function Base.convert(::Type{$type1}, ft::$type2) rev = Dict{$type2,$type1}(Tuple{$type2,$type1}[$(reverse_map...)]) return get(rev, ft) do - error("Unknown type: $ft") + return error("Unknown type: $ft") end end end @@ -108,7 +109,8 @@ end Fetch list of (non-empty) metadata domains. """ -metadatadomainlist(obj)::Vector{String} = GDAL.gdalgetmetadatadomainlist(obj.ptr) +metadatadomainlist(obj)::Vector{String} = + GDAL.gdalgetmetadatadomainlist(obj.ptr) """ metadata(obj; domain::AbstractString = "") @@ -130,7 +132,11 @@ Fetch single metadata item. ### Returns The metadata item on success, or an empty string on failure. """ -function metadataitem(obj, name::AbstractString; domain::AbstractString = "")::String +function metadataitem( + obj, + name::AbstractString; + domain::AbstractString = "", +)::String item = GDAL.gdalgetmetadataitem(obj.ptr, name, domain) return isnothing(item) ? "" : item end @@ -189,7 +195,8 @@ it in environment variables. the value associated to the key, or the default value if not found. """ function getconfigoption(option::AbstractString, default = C_NULL)::String - result = @gdal(CPLGetConfigOption::Cstring, option::Cstring, default::Cstring) + result = + @gdal(CPLGetConfigOption::Cstring, option::Cstring, default::Cstring) return (result == C_NULL) ? "" : unsafe_string(result) end @@ -233,7 +240,10 @@ end Same as `getconfigoption()` but with settings from `setthreadconfigoption()`. """ function getthreadconfigoption(option::AbstractString, default = C_NULL)::String - result = - @gdal(CPLGetThreadLocalConfigOption::Cstring, option::Cstring, default::Cstring) + result = @gdal( + CPLGetThreadLocalConfigOption::Cstring, + option::Cstring, + default::Cstring + ) return (result == C_NULL) ? "" : unsafe_string(result) end diff --git a/test/runtests.jl b/test/runtests.jl index 04c4cc0b..589fa061 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -34,5 +34,6 @@ include("remotefiles.jl") include("test_geotransform.jl") include("test_images.jl") include("test_utils.jl") + return nothing end end diff --git a/test/test_array.jl b/test/test_array.jl index 54675160..2a74d578 100644 --- a/test/test_array.jl +++ b/test/test_array.jl @@ -4,7 +4,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_array.jl" begin - @testset "RasterDataset Type" begin AG.readraster("ospy/data4/aster.img") do ds @testset "Test forwarded methods" begin @@ -17,8 +16,10 @@ const AG = ArchGDAL; @test AG.width(ds) == 5665 @test AG.height(ds) == 5033 @test AG.getdriver(ds) isa AG.Driver - @test splitpath(AG.filelist(ds)[1]) == ["ospy", "data4", "aster.img"] - @test splitpath(AG.filelist(ds)[2]) == ["ospy", "data4", "aster.rrd"] + @test splitpath(AG.filelist(ds)[1]) == + ["ospy", "data4", "aster.img"] + @test splitpath(AG.filelist(ds)[2]) == + ["ospy", "data4", "aster.rrd"] @test AG.listcapability(ds) isa Dict @test AG.ngcp(ds) == 0 @test AG.write(ds, tempname()) == nothing @@ -39,10 +40,6 @@ const AG = ArchGDAL; end end - - - - @testset "Test Array getindex" begin AG.readraster("ospy/data4/aster.img") do ds @testset "Dataset indexing" begin @@ -58,14 +55,16 @@ const AG = ArchGDAL; total = sum(buffer) count = sum(buffer .> 0) @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + @test total / (AG.height(ds) * AG.width(ds)) ≈ + 47.55674749653172 end @testset "colon indexing" begin buffer = ds[:, :, 1] total = sum(buffer) count = sum(buffer .> 0) @test total / count ≈ 76.33891347095299 - @test total / (AG.height(ds) * AG.width(ds)) ≈ 47.55674749653172 + @test total / (AG.height(ds) * AG.width(ds)) ≈ + 47.55674749653172 end @testset "int indexing" begin @test ds[755, 2107, 1] == 0xff @@ -84,14 +83,16 @@ const AG = ArchGDAL; total = sum(buffer) count = sum(buffer .> 0) @test total / count ≈ 76.33891347095299 - @test total / (AG.height(band) * AG.width(band)) ≈ 47.55674749653172 + @test total / (AG.height(band) * AG.width(band)) ≈ + 47.55674749653172 end @testset "colon indexing" begin buffer = band[:, :] total = sum(buffer) count = sum(buffer .> 0) @test total / count ≈ 76.33891347095299 - @test total / (AG.height(band) * AG.width(band)) ≈ 47.55674749653172 + @test total / (AG.height(band) * AG.width(band)) ≈ + 47.55674749653172 end @testset "int indexing" begin @test band[755, 2107] == 0xff @@ -156,7 +157,9 @@ const AG = ArchGDAL; AG.copy(ds) do copy1 @test typeof(AG.copywholeraster!(ds, copy1)) == typeof(copy1) - @test typeof(AG.copywholeraster!(AG.RasterDataset(copy1), ds)) == typeof(ds) + @test typeof( + AG.copywholeraster!(AG.RasterDataset(copy1), ds), + ) == typeof(ds) @test typeof(AG.copywholeraster!(copy1, ds)) == typeof(ds) end end @@ -172,5 +175,4 @@ const AG = ArchGDAL; @test_throws DimensionMismatch AG._common_size(dataset) end end - end diff --git a/test/test_convert.jl b/test/test_convert.jl index 660277d8..d457ab9d 100644 --- a/test/test_convert.jl +++ b/test/test_convert.jl @@ -10,7 +10,8 @@ const GFT = GeoFormatTypes; @testset "convert point format" begin point = AG.createpoint(100, 70) json = convert(GFT.GeoJSON, point) - @test sprint(print, convert(AG.IGeometry, json)) == "Geometry: POINT (100 70)" + @test sprint(print, convert(AG.IGeometry, json)) == + "Geometry: POINT (100 70)" kml = convert(GFT.KML, point) gml = convert(GFT.GML, point) wkb = convert(GFT.WellKnownBinary, point) @@ -42,5 +43,4 @@ const GFT = GeoFormatTypes; @test convert(GFT.CoordSys, GFT.CRS(), proj4326) isa GFT.CoordSys @test convert(GFT.GML, GFT.CRS(), proj4326) isa GeoFormatTypes.GML end - end diff --git a/test/test_cookbook_geometry.jl b/test/test_cookbook_geometry.jl index 971ed5f8..cdd7de49 100644 --- a/test/test_cookbook_geometry.jl +++ b/test/test_cookbook_geometry.jl @@ -5,9 +5,7 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_cookbook_geometry.jl" begin - @testset "Create a Point" begin - x, y = 1198054.34, 648493.09 wktpoint = "POINT (1198054.34 648493.09)" @@ -92,7 +90,6 @@ const AG = ArchGDAL; end @testset "Create a Polygon" begin - wktpoly = "POLYGON ((1179091.16469033 712782.883845978,1161053.02182265 667456.268434881," * "1214704.9339419 641092.828859039,1228580.42845551 682719.312399842," * @@ -121,6 +118,7 @@ const AG = ArchGDAL; (1179091.1646903288, 712782.8838459781), ]) AG.addgeom!(poly, ring) + return nothing end AG.createlinearring([ @@ -178,7 +176,6 @@ const AG = ArchGDAL; end @testset "Create a Polygon with holes" begin - wktpoly = "POLYGON ((1154115.27456585 686419.444270136,1154115.27456585 653118.257437493," * "1165678.18666051 653118.257437493,1165678.18666051 686419.444270136," * @@ -293,7 +290,6 @@ const AG = ArchGDAL; end @testset "Create a MultiPoint" begin - wktpoints = "MULTIPOINT (1251243.73616105 598078.795866876," * "1240605.85703396 601778.927737169,1250318.70319348 606404.092575036)" @@ -350,7 +346,6 @@ const AG = ArchGDAL; end @testset "Create a MultiLineString" begin - wktline = "MULTILINESTRING ((1214242.41745812 617041.971702131,1234593.14274473 629529.916764372)," * "(1184641.36249577 626754.817861651,1219792.61526356 606866.609058823))" @@ -437,7 +432,6 @@ const AG = ArchGDAL; end @testset "Create a MultiPolygon" begin - wktmultipolygon = "MULTIPOLYGON " * "(((1204067.05481481 634617.598086025,1204067.05481481 620742.103572424," * @@ -565,7 +559,6 @@ const AG = ArchGDAL; end @testset "Create a GeometryCollection" begin - wktcollection = "GEOMETRYCOLLECTION " * "(POINT (-122.23 47.09),LINESTRING (-122.6 47.14,-122.48 47.23))" @@ -735,7 +728,8 @@ const AG = ArchGDAL; @testset "Iterate over Points in a Geometry" begin wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" AG.fromWKT(wkt) do geom - @test AG.getpoint(geom, 3) == (1.2248802965852122e6, 665143.6860159477, 0.0) + @test AG.getpoint(geom, 3) == + (1.2248802965852122e6, 665143.6860159477, 0.0) end end @@ -758,7 +752,8 @@ const AG = ArchGDAL; wkt = "LINESTRING (1181866.263593049 615654.4222507705, 1205917.1207499576 623979.7189589312, 1227192.8790041457 643405.4112779726, 1224880.2965852122 665143.6860159477)" AG.fromWKT(wkt) do line env = AG.envelope(line) - @test (env.MaxX - env.MinX) * (env.MaxY - env.MinY) ≈ 2.2431808256625123e9 + @test (env.MaxX - env.MinX) * (env.MaxY - env.MinY) ≈ + 2.2431808256625123e9 end end @@ -810,7 +805,6 @@ const AG = ArchGDAL; wkt2 = "POLYGON ((1199915.6662253144 633079.3410163528, 1199915.6662253144 614453.958118695, 1219317.1067437078 614453.958118695, 1219317.1067437078 633079.3410163528, 1199915.6662253144 633079.3410163528)))" wkt3 = "POLYGON ((1208064.27124304 624154.678377892,1219317.10674371 624154.678377892,1219317.10674371 614453.958118695,1208064.27124304 614453.958118695,1208064.27124304 624154.678377892))" - # Method 1 AG.fromWKT(wkt1) do poly1 AG.fromWKT(wkt2) do poly2 @@ -821,7 +815,8 @@ const AG = ArchGDAL; end # Method 2 - @test AG.toWKT(AG.intersection(AG.fromWKT(wkt1), AG.fromWKT(wkt2))) == wkt3 + @test AG.toWKT(AG.intersection(AG.fromWKT(wkt1), AG.fromWKT(wkt2))) == + wkt3 end @testset "Calculate union between two Geometries" begin @@ -983,5 +978,4 @@ const AG = ArchGDAL; @test AG.getgeomtype(AG.forceto(AG.fromWKT(wkt), AG.wkbMultiPolygon)) == AG.wkbMultiPolygon end - end diff --git a/test/test_cookbook_projection.jl b/test/test_cookbook_projection.jl index 39c6e21d..ea8f1415 100644 --- a/test/test_cookbook_projection.jl +++ b/test/test_cookbook_projection.jl @@ -4,14 +4,14 @@ const AG = ArchGDAL const GFT = GeoFormatTypes @testset "test_cookbook_projection.jl" begin - @testset "Reproject a Geometry" begin @testset "Method 1" begin AG.importEPSG(2927) do source AG.importEPSG(4326) do target AG.createcoordtrans(source, target) do transform AG.fromWKT("POINT (1120351.57 741921.42)") do point - @test AG.toWKT(point) == "POINT (1120351.57 741921.42)" + @test AG.toWKT(point) == + "POINT (1120351.57 741921.42)" AG.transform!(point, transform) @test GeoInterface.coordinates(point) ≈ [47.3488070138318, -122.5981499431438] @@ -39,20 +39,26 @@ const GFT = GeoFormatTypes @testset "Use reproject" begin @testset "reciprocal reprojection of wkt" begin - wktpoint = GFT.WellKnownText(GFT.Geom(), "POINT (1120351.57 741921.42)") + wktpoint = GFT.WellKnownText( + GFT.Geom(), + "POINT (1120351.57 741921.42)", + ) result = GFT.WellKnownText( GFT.Geom(), "POINT (47.3488070138318 -122.598149943144)", ) - @test AG.reproject(wktpoint, GFT.EPSG(2927), GFT.EPSG(4326)) == result + @test AG.reproject(wktpoint, GFT.EPSG(2927), GFT.EPSG(4326)) == + result @test convert( AG.Geometry, AG.reproject(result, GFT.EPSG(4326), GFT.EPSG(2927)), - ) |> GeoInterface.coordinates ≈ [1.12035156999967e6, 741921.420000271] + ) |> GeoInterface.coordinates ≈ + [1.12035156999967e6, 741921.420000271] end @testset "reproject vector, vector of vector, or tuple" begin coord = [1120351.57, 741921.42] - @test AG.reproject(coord, GFT.EPSG(2927), nothing) ≈ [1120351.57, 741921.42] + @test AG.reproject(coord, GFT.EPSG(2927), nothing) ≈ + [1120351.57, 741921.42] @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326)) ≈ [47.3488070138318, -122.5981499431438] @test AG.reproject([coord], GFT.EPSG(2927), GFT.EPSG(4326)) ≈ @@ -64,8 +70,12 @@ const GFT = GeoFormatTypes GFT.EPSG(4326); order = :compliant, ) ≈ [47.3488070138318, -122.5981499431438] - @test AG.reproject(coord, GFT.EPSG(2927), GFT.EPSG(4326); order = :trad) ≈ - [-122.5981499431438, 47.3488070138318] + @test AG.reproject( + coord, + GFT.EPSG(2927), + GFT.EPSG(4326); + order = :trad, + ) ≈ [-122.5981499431438, 47.3488070138318] @test AG.reproject( [coord], GFT.EPSG(2927), @@ -93,7 +103,6 @@ const GFT = GeoFormatTypes ) ≈ [[-122.5981499431438, 47.3488070138318]] end end - end @testset "Get Projection" begin @@ -122,7 +131,8 @@ const GFT = GeoFormatTypes AG.morphfromESRI!(spatialref) @test AG.toPROJ4(spatialref) == proj4str AG.importEPSGA!(spatialref, 4326) - @test AG.toPROJ4(spatialref) == "+proj=longlat +datum=WGS84 +no_defs" + @test AG.toPROJ4(spatialref) == + "+proj=longlat +datum=WGS84 +no_defs" end AG.importEPSGA(4326) do spatialref @@ -131,8 +141,8 @@ const GFT = GeoFormatTypes @test AG.toWKT(cloneref) == AG.toWKT(cloneref2) end @test AG.toWKT(cloneref) == AG.toWKT(AG.importEPSGA(4326)) - @test AG.toPROJ4(spatialref) == "+proj=longlat +datum=WGS84 +no_defs" + @test AG.toPROJ4(spatialref) == + "+proj=longlat +datum=WGS84 +no_defs" end end - end diff --git a/test/test_dataset.jl b/test/test_dataset.jl index eecf009a..652bd43f 100644 --- a/test/test_dataset.jl +++ b/test/test_dataset.jl @@ -3,17 +3,20 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_dataset.jl" begin - @testset "Test methods for raster dataset" begin AG.read("data/utmsmall.tif") do dataset @testset "Method 1" begin - AG.copy(dataset, filename = "/vsimem/utmcopy.tif") do copydataset + AG.copy( + dataset, + filename = "/vsimem/utmcopy.tif", + ) do copydataset @test AG.ngcp(copydataset) == 0 AG.getband(copydataset, 1) do band @test AG.noverview(band) == 0 AG.buildoverviews!(copydataset, Cint[2, 4, 8]) @test AG.noverview(band) == 3 AG.copywholeraster!(dataset, copydataset) + return nothing end end end @@ -29,7 +32,12 @@ const AG = ArchGDAL; AG.update("/vsimem/utmcopy2.tif") do copydataset @test AG.ngcp(copydataset) == 0 @test AG.noverview(AG.getband(copydataset, 1)) == 3 - AG.copywholeraster!(dataset, copydataset, options = ["COMPRESS=LZW"]) + AG.copywholeraster!( + dataset, + copydataset, + options = ["COMPRESS=LZW"], + ) + return nothing end end end @@ -75,8 +83,11 @@ const AG = ArchGDAL; dataset4 = AG.create(tempname(), driver = AG.getdriver("KML")) @test AG.nlayer(dataset4) == 0 - layer4 = - AG.createlayer(name = "layer4", dataset = dataset4, geom = AG.wkbLineString) + layer4 = AG.createlayer( + name = "layer4", + dataset = dataset4, + geom = AG.wkbLineString, + ) @test AG.nlayer(dataset4) == 1 AG.create(tempname(), driver = AG.getdriver("KML")) do dataset5 @@ -98,7 +109,7 @@ const AG = ArchGDAL; @test AG.ngeom(layer5) == 1 AG.create(AG.getdriver("Memory")) do dataset6 - for i = 1:20 + for i in 1:20 AG.createlayer(name = "layer$(i - 1)", dataset = dataset6) end @test AG.nlayer(dataset6) == 20 @@ -118,5 +129,4 @@ const AG = ArchGDAL; layer15, layer16, layer17, layer18, layer19, """ end end - end diff --git a/test/test_display.jl b/test/test_display.jl index b40d7def..3a995fea 100644 --- a/test/test_display.jl +++ b/test/test_display.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_display.jl" begin - @testset "Testing Displays for NULL objects" begin @test sprint(print, AG.Driver(C_NULL)) == "NULL Driver" @test sprint(print, AG.IDataset()) == "NULL Dataset" @@ -48,7 +47,8 @@ const AG = ArchGDAL; (index 0) FID => 0.0 (index 1) pointname => a """ - @test sprint(print, AG.getfielddefn(feature, 1)) == "pointname (OFTString)" + @test sprint(print, AG.getfielddefn(feature, 1)) == + "pointname (OFTString)" @test sprint(print, AG.getgeomdefn(feature, 0)) == " (wkbPoint)" end end diff --git a/test/test_drivers.jl b/test/test_drivers.jl index 20b312f7..a46b0388 100644 --- a/test/test_drivers.jl +++ b/test/test_drivers.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_drivers.jl" begin - @testset "Testing ConfigOptions" begin @test AG.getconfigoption("GDAL_CACHEMAX") == "" AG.setconfigoption("GDAL_CACHEMAX", "64") @@ -106,5 +105,4 @@ const AG = ArchGDAL; @test AG.extensiondriver(".asc") == "AAIGrid" @test_throws ArgumentError AG.extensiondriver(".not_an_extension") end - end diff --git a/test/test_feature.jl b/test/test_feature.jl index 6dffe1f3..501ec7c9 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_feature.jl" begin - AG.read("data/point.geojson") do dataset layer = AG.getlayer(dataset, 0) AG.getfeature(layer, 0) do f1 @@ -58,7 +57,7 @@ const AG = ArchGDAL; AG.setgeom!(f, 0, AG.createpoint(0, 100)) @test AG.toWKT(AG.getgeom(f, 0)) == "POINT (0 100)" AG.createpolygon([(0.0, 100.0), (100.0, 0.0)]) do poly - AG.setgeom!(f, 0, poly) + return AG.setgeom!(f, 0, poly) end @test AG.toWKT(AG.getgeom(f, 0)) == "POLYGON ((0 100,100 0))" @@ -86,8 +85,10 @@ const AG = ArchGDAL; @test AG.validate(f, AG.F_VAL_NULL, false) == true @test AG.validate(f, AG.F_VAL_GEOM_TYPE, false) == false @test AG.validate(f, AG.F_VAL_WIDTH, false) == true - @test AG.validate(f, AG.F_VAL_ALLOW_NULL_WHEN_DEFAULT, false) == true - @test AG.validate(f, AG.F_VAL_ALLOW_DIFFERENT_GEOM_DIM, false) == true + @test AG.validate(f, AG.F_VAL_ALLOW_NULL_WHEN_DEFAULT, false) == + true + @test AG.validate(f, AG.F_VAL_ALLOW_DIFFERENT_GEOM_DIM, false) == + true @test AG.getfield(f, 1) == "point-a" @test AG.getdefault(f, 1) == "" @@ -105,28 +106,31 @@ const AG = ArchGDAL; AG.create(AG.getdriver("MEMORY")) do output layer = AG.createlayer(dataset = output, geom = AG.wkbPolygon) AG.createfielddefn("int64field", AG.OFTInteger64) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end AG.createfielddefn("doublefield", AG.OFTReal) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end AG.createfielddefn("intlistfield", AG.OFTIntegerList) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("int64listfield", AG.OFTInteger64List) do fielddefn - AG.addfielddefn!(layer, fielddefn) + AG.createfielddefn( + "int64listfield", + AG.OFTInteger64List, + ) do fielddefn + return AG.addfielddefn!(layer, fielddefn) end AG.createfielddefn("doublelistfield", AG.OFTRealList) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end AG.createfielddefn("stringlistfield", AG.OFTStringList) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end AG.createfielddefn("binaryfield", AG.OFTBinary) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end AG.createfielddefn("datetimefield", AG.OFTDateTime) do fielddefn - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end AG.createfeature(layer) do feature AG.setfield!(feature, 0, 1) @@ -168,7 +172,8 @@ const AG = ArchGDAL; @test AG.getfield(lastfeature, 2) == Int32[1, 2] @test AG.getfield(lastfeature, 3) == Int64[1, 2] @test AG.getfield(lastfeature, 4) ≈ Float64[1.0, 2.0] - @test AG.getfield(lastfeature, 5) == String["foo", "bar"] + @test AG.getfield(lastfeature, 5) == + String["foo", "bar"] @test AG.getfield(lastfeature, 6) == UInt8[1, 2, 3, 4] @test AG.getfield(lastfeature, 7) == Dates.DateTime(2016, 9, 25, 21, 17, 0) @@ -188,5 +193,4 @@ const AG = ArchGDAL; @test AG.nfeature(layer) == 3 end end - end diff --git a/test/test_featurelayer.jl b/test/test_featurelayer.jl index 3bd8d548..15a4ec76 100644 --- a/test/test_featurelayer.jl +++ b/test/test_featurelayer.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_featurelayer.jl" begin - @testset "Testing FeatureLayer Methods" begin AG.read("data/point.geojson") do dataset AG.copy(dataset) do tmpcopy @@ -12,11 +11,14 @@ const AG = ArchGDAL; @test sprint(print, AG.getspatialref(tmplayer)) == "NULL Spatial Reference System" AG.getspatialref(tmplayer) do spref - @test sprint(print, spref) == "NULL Spatial Reference System" + @test sprint(print, spref) == + "NULL Spatial Reference System" end - @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer), 0)) == false + @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer), 0)) == + false AG.setignoredfields!(tmplayer, ["OGR_GEOMETRY"]) - @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer), 0)) == true + @test AG.isignored(AG.getgeomdefn(AG.layerdefn(tmplayer), 0)) == + true end AG.copy(dataset, driver = AG.getdriver("Memory")) do tmpcopy @@ -55,6 +57,7 @@ const AG = ArchGDAL; AG.createfeature(newlayer) do newfeature AG.setgeom!(newfeature, 0, AG.createpoint()) AG.setgeom!(newfeature, 1, AG.createlinestring()) + return nothing end @test AG.nfeature(newlayer) == 1 @test sprint(print, newlayer) == """ @@ -84,10 +87,15 @@ const AG = ArchGDAL; AG.setgeom!( newfeature, 2, - AG.createpolygon([[[0.0, 0.0], [1.0, 1.0], [0.0, 1.0]]]), + AG.createpolygon([[ + [0.0, 0.0], + [1.0, 1.0], + [0.0, 1.0], + ]]), ) - @test sprint(print, AG.getgeom(newfeature)) == "Geometry: POINT EMPTY" + @test sprint(print, AG.getgeom(newfeature)) == + "Geometry: POINT EMPTY" @test sprint(print, AG.getgeom(newfeature, 0)) == "Geometry: POINT EMPTY" @test sprint(print, AG.getgeom(newfeature, 1)) == @@ -101,7 +109,8 @@ const AG = ArchGDAL; @test sprint(print, g) == "Geometry: LINESTRING EMPTY" end AG.getgeom(newfeature, 2) do g - @test sprint(print, g) == "Geometry: POLYGON ((0 0,1 1,0 1))" + @test sprint(print, g) == + "Geometry: POLYGON ((0 0,1 1,0 1))" end end end @@ -142,7 +151,8 @@ const AG = ArchGDAL; end @test n == 2 AG.clearspatialfilter!(layer) - @test sprint(print, AG.getspatialfilter(layer)) == "NULL Geometry" + @test sprint(print, AG.getspatialfilter(layer)) == + "NULL Geometry" n = 0 for feature in layer n += 1 diff --git a/test/test_fielddefn.jl b/test/test_fielddefn.jl index db0a0820..c0687040 100644 --- a/test/test_fielddefn.jl +++ b/test/test_fielddefn.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_fielddefn.jl" begin - @testset "Tests for field defn" begin AG.createfielddefn("fieldname", AG.OFTInteger) do fd @test sprint(print, fd) == "fieldname (OFTInteger)" @@ -72,7 +71,8 @@ const AG = ArchGDAL; AG.settype!(gfd, AG.wkbPolyhedralSurface) @test AG.gettype(gfd) == AG.wkbPolyhedralSurface - @test sprint(print, AG.getspatialref(gfd)) == "NULL Spatial Reference System" + @test sprint(print, AG.getspatialref(gfd)) == + "NULL Spatial Reference System" AG.getspatialref(gfd) do spref @test sprint(print, spref) == "NULL Spatial Reference System" end @@ -120,23 +120,24 @@ const AG = ArchGDAL; AG.createfielddefn("newfield", AG.OFTInteger) do fielddef2 AG.addfielddefn!(fd, fielddef2) @test AG.nfield(fd) == 4 - AG.getname(AG.getfielddefn(fd, 0)) == "fieldname" - AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" - AG.getname(AG.getfielddefn(fd, 2)) == "fieldname" - AG.getname(AG.getfielddefn(fd, 3)) == "newfield" + @test AG.getname(AG.getfielddefn(fd, 0)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 2)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 3)) == "newfield" + return nothing end end AG.deletefielddefn!(fd, 0) @test AG.nfield(fd) == 3 - AG.getname(AG.getfielddefn(fd, 0)) == "fieldname" - AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" - AG.getname(AG.getfielddefn(fd, 2)) == "newfield" + @test AG.getname(AG.getfielddefn(fd, 0)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 2)) == "newfield" AG.reorderfielddefns!(fd, Cint[2, 1, 0]) @test AG.nfield(fd) == 3 - AG.getname(AG.getfielddefn(fd, 0)) == "newfield" - AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" - AG.getname(AG.getfielddefn(fd, 2)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 0)) == "newfield" + @test AG.getname(AG.getfielddefn(fd, 1)) == "fieldname" + @test AG.getname(AG.getfielddefn(fd, 2)) == "fieldname" @test AG.ngeom(fd) == 1 @test AG.getgeomtype(fd) == AG.wkbUnknown @@ -176,9 +177,9 @@ const AG = ArchGDAL; AG.createfeature(fd) do f @test AG.nreference(fd) == 2 # artificially inflated @test AG.issame(AG.getfeaturedefn(f), fd) == true + return nothing end @test AG.nreference(fd) == 0 end end - end diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index c33ba1b4..16b62c4d 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_gdal_tutorials.jl" begin - @testset "Raster Tutorial" begin driver = AG.getdriver("GTiff") @@ -16,7 +15,8 @@ const AG = ArchGDAL; nad27_prefix = "PROJCS[\"NAD27 / UTM zone 11N\",GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\"," @test startswith(AG.getproj(dataset), nad27_prefix) == true - @test AG.getgeotransform(dataset) ≈ [440720.0, 60.0, 0.0, 3.75132e6, 0.0, -60.0] + @test AG.getgeotransform(dataset) ≈ + [440720.0, 60.0, 0.0, 3.75132e6, 0.0, -60.0] band = AG.getband(dataset, 1) @test AG.blocksize(band) ≈ [100, 81] @@ -138,7 +138,8 @@ const AG = ArchGDAL; ["IMAGE_STRUCTURE", "", "DERIVED_SUBDATASETS"] @test AG.metadata(dataset) == ["AREA_OR_POINT=Area"] @test AG.metadataitem(dataset, "AREA_OR_POINT") == "Area" - @test AG.metadata(dataset, domain = "IMAGE_STRUCTURE") == ["INTERLEAVE=BAND"] + @test AG.metadata(dataset, domain = "IMAGE_STRUCTURE") == + ["INTERLEAVE=BAND"] @test AG.metadata(dataset, domain = "") == ["AREA_OR_POINT=Area"] @test AG.metadata(dataset, domain = "DERIVED_SUBDATASETS") == [ "DERIVED_SUBDATASET_1_NAME=DERIVED_SUBDATASET:LOGAMPLITUDE:data/utmsmall.tif", @@ -202,18 +203,25 @@ const AG = ArchGDAL; end AG.create(AG.getdriver("MEMORY")) do dataset - layer = - AG.createlayer(name = "point_out", dataset = dataset, geom = AG.wkbPoint) + layer = AG.createlayer( + name = "point_out", + dataset = dataset, + geom = AG.wkbPoint, + ) AG.addfielddefn!(layer, "Name", AG.OFTString, nwidth = 32) featuredefn = AG.layerdefn(layer) @test AG.getname(featuredefn) == "point_out" @test AG.nfeature(layer) == 0 AG.createfeature(layer) do feature - AG.setfield!(feature, AG.findfieldindex(feature, "Name"), "myname") + AG.setfield!( + feature, + AG.findfieldindex(feature, "Name"), + "myname", + ) AG.setgeom!(feature, AG.createpoint(100.123, 0.123)) + return nothing end @test AG.nfeature(layer) == 1 end end - end diff --git a/test/test_geometry.jl b/test/test_geometry.jl index b5fbd7e5..cbdde42b 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -110,12 +110,14 @@ const GFT = GeoFormatTypes 0x00, ] @test AG.toKML(point, "relativeToGround") == - "relativeToGround100,70,0" + "relativeToGround" * + "100,70,0" @test AG.toKML(point, "clampToGround") == - "clampToGround100,70,0" + "clampToGround" * + "100,70,0" @test AG.toKML(point) == "100,70,0" @test AG.toJSON(point) == - "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" + "{ \"type\": \"Point\", \"coordinates\": " * "[ 100.0, 70.0, 0.0 ] }" @test startswith( AG.toJSON(point, SIGNIFICANT_FIGURES = 1), "{ \"type\": \"Point\", \"coordinates\": [", @@ -225,9 +227,11 @@ const GFT = GeoFormatTypes 0x00, ] @test AG.toKML(point, "relativeToGround") == - "relativeToGround100,70,0" + "relativeToGround" * + "100,70,0" @test AG.toKML(point, "clampToGround") == - "clampToGround100,70,0" + "clampToGround" * + "100,70,0" @test AG.toKML(point) == "100,70,0" @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" @@ -337,7 +341,9 @@ const GFT = GeoFormatTypes ], ), ) == - "MULTIPOLYGON (((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1)),((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" + "MULTIPOLYGON (" * + "((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1))," * + "((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" AG.createmultipolygon( Vector{Vector{Tuple{Cdouble,Cdouble}}}[ Vector{Tuple{Cdouble,Cdouble}}[ @@ -363,18 +369,26 @@ const GFT = GeoFormatTypes atol = 1e-6, ) @test AG.toWKT(geom) == - "MULTIPOLYGON (((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1)),((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" + "MULTIPOLYGON (" * + "((0 0,0 4,4 4,4 0),(1 1,1 3,3 3,3 1))," * + "((10 0,10 4,14 4,14 0),(11 1,11 3,13 3,13 1)))" end AG.fromWKT( - "CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))", + "CURVEPOLYGON (" * + "CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0)," * + "(-1 0,0 0.5,1 0,0 1,-1 0))", ) do geom @test AG.toWKT(AG.curvegeom(AG.lineargeom(geom, 0.5))) == - "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" + "CURVEPOLYGON (" * + "CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0)," * + "(-1 0,0.0 0.5,1 0,0 1,-1 0))" AG.lineargeom(geom, 0.5) do lgeom AG.curvegeom(lgeom) do clgeom @test AG.toWKT(clgeom) == - "CURVEPOLYGON (CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0.0 0.5,1 0,0 1,-1 0))" + "CURVEPOLYGON (" * + "CIRCULARSTRING (-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0)," * + "(-1 0,0.0 0.5,1 0,0 1,-1 0))" end @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom @@ -449,58 +463,188 @@ const GFT = GeoFormatTypes end @test AG.toWKT(AG.union(geom1, geom2)) == - "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + "GEOMETRYCOLLECTION (" * + "POLYGON (" * + "(0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "POLYGON (" * + "(10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8))," * + "POINT (2 5 8),POINT (3 6 9))" AG.union(geom1, geom2) do result @test AG.toWKT(result) == - "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + "GEOMETRYCOLLECTION (" * + "POLYGON (" * + "(0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "POLYGON (" * + "(10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8))," * + "POINT (2 5 8),POINT (3 6 9))" @test AG.hascurvegeom(result, true) == false @test AG.hascurvegeom(result, false) == false end @test AG.toWKT(AG.difference(geom1, geom2)) == - "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + "MULTIPOLYGON (" * + "((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" AG.difference(geom1, geom2) do result @test AG.toWKT(result) == - "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + "MULTIPOLYGON (" * + "((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" AG.segmentize!(result, 20) @test AG.toWKT(result) == - "MULTIPOLYGON (((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + "MULTIPOLYGON (" * + "((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" AG.segmentize!(result, 2) @test AG.toWKT(result) == - "MULTIPOLYGON (((0 4 8,2 4 8,4 4 8,4 2 8,4 0 8,2 0 8,0 0 8,0 2 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),((10 4 8,12 4 8,14 4 8,14 2 8,14 0 8,12 0 8,10 0 8,10 2 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)))" + "MULTIPOLYGON (" * + "(" * + "(" * + "0 4 8," * + "2 4 8," * + "4 4 8," * + "4 2 8," * + "4 0 8," * + "2 0 8," * + "0 0 8," * + "0 2 8," * + "0 4 8)," * + "(" * + "3 1 8," * + "3 3 8," * + "1 3 8," * + "1 1 8," * + "3 1 8))," * + "(" * + "(" * + "10 4 8," * + "12 4 8," * + "14 4 8," * + "14 2 8," * + "14 0 8," * + "12 0 8," * + "10 0 8," * + "10 2 8," * + "10 4 8)," * + "(" * + "13 1 8," * + "13 3 8," * + "11 3 8," * + "11 1 8," * + "13 1 8)))" end @test AG.toWKT(AG.symdifference(geom1, geom2)) == - "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + "GEOMETRYCOLLECTION (" * + "POLYGON (" * + "(0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "POLYGON (" * + "(10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8))," * + "POINT (2 5 8),POINT (3 6 9))" AG.symdifference(geom1, geom2) do result @test GeoInterface.geotype(result) == :GeometryCollection @test AG.toWKT(result) == - "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POLYGON ((10 4 8,14 4 8,14 0 8,10 0 8,10 4 8),(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8)),POINT (2 5 8),POINT (3 6 9))" + "GEOMETRYCOLLECTION (" * + "POLYGON (" * + "(0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "POLYGON (" * + "(10 4 8,14 4 8,14 0 8,10 0 8,10 4 8)," * + "(13 1 8,13 3 8,11 3 8,11 1 8,13 1 8))," * + "POINT (2 5 8)," * + "POINT (3 6 9))" AG.removegeom!(result, 1) @test AG.toWKT(result) == - "GEOMETRYCOLLECTION (POLYGON ((0 4 8,4 4 8,4 0 8,0 0 8,0 4 8),(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8)),POINT (2 5 8),POINT (3 6 9))" + "GEOMETRYCOLLECTION (" * + "POLYGON (" * + "(0 4 8,4 4 8,4 0 8,0 0 8,0 4 8)," * + "(3 1 8,3 3 8,1 3 8,1 1 8,3 1 8))," * + "POINT (2 5 8)," * + "POINT (3 6 9))" AG.removeallgeoms!(result) @test AG.toWKT(result) == "GEOMETRYCOLLECTION EMPTY" end geom3 = AG.fromWKT( - "GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8,0 4 8,4 4 8,4 0 8,0 0 8),(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8)),POLYGON ((10 0 8,10 4 8,14 4 8,14 0 8,10 0 8),(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8)), POINT EMPTY)", + "GEOMETRYCOLLECTION (" * + "POINT (2 5 8)," * + "POLYGON (" * + "(0 0 8,0 4 8,4 4 8,4 0 8,0 0 8)," * + "(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8))," * + "POLYGON (" * + "(10 0 8,10 4 8,14 4 8,14 0 8,10 0 8)," * + "(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8))," * + "POINT EMPTY)", ) AG.clone(geom3) do geom4 @test sprint(print, AG.clone(geom3)) == - "Geometry: GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8, ... MPTY)" + "Geometry: GEOMETRYCOLLECTION (" * + "POINT (2 5 8)," * + "POLYGON ((0 0 8," * + " ... MPTY)" @test sprint(print, AG.clone(geom4)) == - "Geometry: GEOMETRYCOLLECTION (POINT (2 5 8),POLYGON ((0 0 8, ... MPTY)" + "Geometry: GEOMETRYCOLLECTION (" * + "POINT (2 5 8)," * + "POLYGON ((0 0 8," * + " ... MPTY)" end AG.clone(AG.getgeom(geom3, 3)) do geom4 @test sprint(print, geom4) == "Geometry: POINT EMPTY" end @test AG.toISOWKT(geom3) == - "GEOMETRYCOLLECTION Z (POINT Z (2 5 8),POLYGON Z ((0 0 8,0 4 8,4 4 8,4 0 8,0 0 8),(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8)),POLYGON Z ((10 0 8,10 4 8,14 4 8,14 0 8,10 0 8),(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8)),POINT Z EMPTY)" - AG.removegeom!(geom3, AG.ngeom(geom3) - 1) # the JSON driver in GDAL 3.0 does not handle null geometries well yet + "GEOMETRYCOLLECTION Z (" * + "POINT Z (2 5 8)," * + "POLYGON Z (" * + "(0 0 8,0 4 8,4 4 8,4 0 8,0 0 8)," * + "(1 1 8,3 1 8,3 3 8,1 3 8,1 1 8))," * + "POLYGON Z (" * + "(10 0 8,10 4 8,14 4 8,14 0 8,10 0 8)," * + "(11 1 8,13 1 8,13 3 8,11 3 8,11 1 8))," * + "POINT Z EMPTY)" + # the JSON driver in GDAL 3.0 does not handle null geometries well yet + AG.removegeom!(geom3, AG.ngeom(geom3) - 1) @test AG.toJSON(geom3) == - """{ "type": "GeometryCollection", "geometries": [ { "type": "Point", "coordinates": [ 2.0, 5.0, 8.0 ] }, { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0, 8.0 ], [ 0.0, 4.0, 8.0 ], [ 4.0, 4.0, 8.0 ], [ 4.0, 0.0, 8.0 ], [ 0.0, 0.0, 8.0 ] ], [ [ 1.0, 1.0, 8.0 ], [ 3.0, 1.0, 8.0 ], [ 3.0, 3.0, 8.0 ], [ 1.0, 3.0, 8.0 ], [ 1.0, 1.0, 8.0 ] ] ] }, { "type": "Polygon", "coordinates": [ [ [ 10.0, 0.0, 8.0 ], [ 10.0, 4.0, 8.0 ], [ 14.0, 4.0, 8.0 ], [ 14.0, 0.0, 8.0 ], [ 10.0, 0.0, 8.0 ] ], [ [ 11.0, 1.0, 8.0 ], [ 13.0, 1.0, 8.0 ], [ 13.0, 3.0, 8.0 ], [ 11.0, 3.0, 8.0 ], [ 11.0, 1.0, 8.0 ] ] ] } ] }""" + """{ "type": "GeometryCollection", "geometries": [ """ * + """{ "type": "Point", "coordinates": [ 2.0, 5.0, 8.0 ] }, """ * + """{ "type": "Polygon", "coordinates": [ """ * + "[ " * + "[ 0.0, 0.0, 8.0 ], " * + "[ 0.0, 4.0, 8.0 ], " * + "[ 4.0, 4.0, 8.0 ], " * + "[ 4.0, 0.0, 8.0 ], " * + "[ 0.0, 0.0, 8.0 ] ], " * + "[ " * + "[ 1.0, 1.0, 8.0 ], " * + "[ 3.0, 1.0, 8.0 ], " * + "[ 3.0, 3.0, 8.0 ], " * + "[ 1.0, 3.0, 8.0 ], " * + "[ 1.0, 1.0, 8.0 ] ] ] }, " * + """{ "type": "Polygon", "coordinates": [ """ * + "[ " * + "[ 10.0, 0.0, 8.0 ], " * + "[ 10.0, 4.0, 8.0 ], " * + "[ 14.0, 4.0, 8.0 ], " * + "[ 14.0, 0.0, 8.0 ], " * + "[ 10.0, 0.0, 8.0 ] ], " * + "[ " * + "[ 11.0, 1.0, 8.0 ], " * + "[ 13.0, 1.0, 8.0 ], " * + "[ 13.0, 3.0, 8.0 ], " * + "[ 11.0, 3.0, 8.0 ], " * + "[ 11.0, 1.0, 8.0 ] ] ] } ] }" AG.createmultilinestring([[ [1.0, 4.0], From cc9b1a1c37f14b17f4ae132a6c6414303d36261d Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 11:46:02 -0700 Subject: [PATCH 097/169] Add a format checker for PRs --- .github/workflows/format_check.yml | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/format_check.yml diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml new file mode 100644 index 00000000..5055b006 --- /dev/null +++ b/.github/workflows/format_check.yml @@ -0,0 +1,31 @@ +name: format-check +on: + push: + branches: + - master + - release-* + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@latest + with: + version: '1' + - uses: actions/checkout@v1 + - name: Format check + shell: julia --color=yes {0} + run: | + using Pkg + # If you update the version, also update the style guide docs. + Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.10")) + using JuliaFormatter + format(".", verbose=true) + out = String(read(Cmd(`git diff`))) + if isempty(out) + exit(0) + end + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) From befe918c8b1d6701506f1910a149beaa1328a8df Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 11:46:12 -0700 Subject: [PATCH 098/169] Update the README with the style guide --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b6b060d..2b7a5cc5 100644 --- a/README.md +++ b/README.md @@ -69,4 +69,22 @@ shell> cd /Users/yeesian/.julia/dev/ArchGDAL [68eda718] + GeoFormatTypes v0.3.0 [cf35fbd7] + GeoInterface v0.5.5 [bd369af6] + Tables v1.4.2 -``` \ No newline at end of file +``` + +## For Developers + +ArchGDAL.jl uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) as +an autoformatting tool. + +We use the options contained in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml). + +To format code, `cd` to the ArchGDAL.jl directory, then run: +```julia +] add JuliaFormatter@0.13.10 +using JuliaFormatter +format(".") +``` + +!!! info + A continuous integration check verifies that all PRs made to ArchGDAL.jl have + passed the formatter. From 594976a23a2f9cb7fce4ce89f94f7b5cc554e0ca Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 11:58:38 -0700 Subject: [PATCH 099/169] Restrict the format checker to just the src/ directory for now. It seems to error on test/test_gdalutilies.jl even though it still formats the files. We'll still have a format_pr.yml to autoformat the entire repository, so I'm less concerned about the test directory. --- .github/workflows/format_check.yml | 2 +- README.md | 2 +- test/test_gdalutilities.jl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml index 5055b006..e4fd63d6 100644 --- a/.github/workflows/format_check.yml +++ b/.github/workflows/format_check.yml @@ -21,7 +21,7 @@ jobs: # If you update the version, also update the style guide docs. Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.10")) using JuliaFormatter - format(".", verbose=true) + format("src", verbose=true) out = String(read(Cmd(`git diff`))) if isempty(out) exit(0) diff --git a/README.md b/README.md index 2b7a5cc5..02e9734d 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ To format code, `cd` to the ArchGDAL.jl directory, then run: ```julia ] add JuliaFormatter@0.13.10 using JuliaFormatter -format(".") +format("src") ``` !!! info diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index f609ea8e..ca0cf7b2 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -1,5 +1,5 @@ -using ArchGDAL, GDAL; -AG = ArchGDAL; +using ArchGDAL, GDAL +AG = ArchGDAL using Test @testset "test_gdalutilities.jl" begin From 9debf2f0ee20d56f8eeb36c3e1369841552fe715 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 16:29:01 -0700 Subject: [PATCH 100/169] Update README.md --- README.md | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 02e9734d..777fd66b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,31 @@ To test if it is installed correctly, pkg> test ArchGDAL ``` -## Dependencies +## Getting Involved + +### Community + +This package will not be possible without https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by the https://www.osgeo.org/ and https://juliageo.org/ communities respectively. In case there is any source of contention or confusion, for support and involvement, we encourage participation and contributions to those libraries and communities over this package. + +### Style Guide + +ArchGDAL.jl uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) as +an autoformatting tool. + +We use the options contained in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml). + +To format code, `cd` to the ArchGDAL.jl directory, then run: +```julia +] add JuliaFormatter@0.13.10 +using JuliaFormatter +format("src") +``` + +!!! info + A continuous integration check verifies that all PRs made to ArchGDAL.jl have + passed the formatter. + +### Dependencies To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1.6/environments/): 1. Navigate to the directory corresponding to the package: @@ -70,21 +94,3 @@ shell> cd /Users/yeesian/.julia/dev/ArchGDAL [cf35fbd7] + GeoInterface v0.5.5 [bd369af6] + Tables v1.4.2 ``` - -## For Developers - -ArchGDAL.jl uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) as -an autoformatting tool. - -We use the options contained in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml). - -To format code, `cd` to the ArchGDAL.jl directory, then run: -```julia -] add JuliaFormatter@0.13.10 -using JuliaFormatter -format("src") -``` - -!!! info - A continuous integration check verifies that all PRs made to ArchGDAL.jl have - passed the formatter. From dbef00a957973225608a0043b99c390c4b42b59c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 16:31:50 -0700 Subject: [PATCH 101/169] tweak phrasing --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 777fd66b..d612faf1 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ pkg> test ArchGDAL ### Community -This package will not be possible without https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by the https://www.osgeo.org/ and https://juliageo.org/ communities respectively. In case there is any source of contention or confusion, for support and involvement, we encourage participation and contributions to those libraries and communities over this package. +This package will not be possible without https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by the https://www.osgeo.org/ and https://juliageo.org/ communities respectively. In case of any contention for support and involvement, we encourage participation and contributions to those libraries and communities over this package. ### Style Guide From 08505ee46927281bbbada1d3b474892d5c194b7c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 16:36:15 -0700 Subject: [PATCH 102/169] Include Julialang in the statement of support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d612faf1..56f46303 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ pkg> test ArchGDAL ### Community -This package will not be possible without https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by the https://www.osgeo.org/ and https://juliageo.org/ communities respectively. In case of any contention for support and involvement, we encourage participation and contributions to those libraries and communities over this package. +This package will not be possible without https://julialang.org/, https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by https://julialang.org/community/, https://www.osgeo.org/ and https://juliageo.org/. In case of any contention for support and involvement, we encourage participation and contributions to those libraries and communities over this package. ### Style Guide From 405fb7fe4ae433a3ee3ce01fde0728da31b291b3 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 9 May 2021 17:53:14 -0700 Subject: [PATCH 103/169] provide a README.md for the tests In particular, documenting how to work with data (if needed). --- README.md | 2 +- test/README.md | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/README.md diff --git a/README.md b/README.md index 56f46303..8842a7fc 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ pkg> test ArchGDAL ### Community -This package will not be possible without https://julialang.org/, https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by https://julialang.org/community/, https://www.osgeo.org/ and https://juliageo.org/. In case of any contention for support and involvement, we encourage participation and contributions to those libraries and communities over this package. +This package will not be possible without https://julialang.org/, https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by https://julialang.org/community/, https://www.osgeo.org/ and https://juliageo.org/. In case of any contention for support and involvement, we encourage participation and contributions to those projects and communities over this package. ### Style Guide diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..c1e0c52b --- /dev/null +++ b/test/README.md @@ -0,0 +1,24 @@ +# ArchGDAL.jl unit tests + +This package uses the [standard library for unit testing](https://docs.julialang.org/en/v1/stdlib/Test/). To run the suite of tests in this directory, + +```julia +pkg> test ArchGDAL +``` + +## Working with Data + +In general, we prefer for unit tests to be written independently of the need for data to be fetched from remote files. + +If you are introducing data to be used for unit testing, please be mindful for it to be released under an appropriate license, and for it to be pared down into a sufficiently small file that still exercises the corresponding logic to be tested. + +The data used for testing in this package are fetched from https://github.com/yeesian/ArchGDALDatasets in [remotefiles.jl](https://github.com/yeesian/ArchGDAL.jl/blob/master/test/remotefiles.jl). + +To add a file, please upload it to that repository with the corresponding license, and follow the below steps to generate the SHA: + +```julia +julia> using SHA +julia> open(filepath/filename) do f + bytes2hex(sha256(f)) + end +``` From f2531ab2290ae73ea739ceed7be22c8c5c983a1e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 14 May 2021 23:19:33 -0700 Subject: [PATCH 104/169] Fix the return type --- src/raster/rasterband.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index e6571c46..cb57d261 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -184,7 +184,7 @@ not be displayed, nor contribute to analysis operations. ### Returns the nodata value for this band or `nothing`. """ -function getnodatavalue(band::AbstractRasterBand)::Union{Cint,Nothing} +function getnodatavalue(band::AbstractRasterBand)::Union{Float64, Nothing} # ### Parameters # * `pbSuccess` pointer to a boolean to use to indicate if a value is # actually associated with this layer. May be `NULL` (default). From ab775a375e37e5da3725ba7f20b54d0029c6d3dc Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 14 May 2021 23:26:32 -0700 Subject: [PATCH 105/169] fix format --- src/raster/rasterband.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index cb57d261..cd0c7ba0 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -184,7 +184,7 @@ not be displayed, nor contribute to analysis operations. ### Returns the nodata value for this band or `nothing`. """ -function getnodatavalue(band::AbstractRasterBand)::Union{Float64, Nothing} +function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Nothing} # ### Parameters # * `pbSuccess` pointer to a boolean to use to indicate if a value is # actually associated with this layer. May be `NULL` (default). From d3570e05abc68f2cb11493477fea7e66b4f6be81 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 14 May 2021 23:28:47 -0700 Subject: [PATCH 106/169] Tweak README --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8842a7fc..96d6d115 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,7 @@ This package will not be possible without https://julialang.org/, https://github ### Style Guide ArchGDAL.jl uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) as -an autoformatting tool. - -We use the options contained in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml). +an autoformatting tool, and uses the options in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml). To format code, `cd` to the ArchGDAL.jl directory, then run: ```julia @@ -50,9 +48,7 @@ using JuliaFormatter format("src") ``` -!!! info - A continuous integration check verifies that all PRs made to ArchGDAL.jl have - passed the formatter. +A continuous integration check verifies that all PRs made to ArchGDAL.jl have passed the formatter. ### Dependencies To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1.6/environments/): From 3d025fedb61596ae500e63a652173d175a5abdc1 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 15 May 2021 01:07:45 -0700 Subject: [PATCH 107/169] Add functionality and documentation for raster images --- docs/make.jl | 1 + docs/src/images.md | 53 +++++++++++++++++++++++++++++++++++++ src/raster/images.jl | 62 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 docs/src/images.md diff --git a/docs/make.jl b/docs/make.jl index 06785100..5dfebc0e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -17,6 +17,7 @@ makedocs( "GDAL Datasets" => "datasets.md", "Feature Data" => "features.md", "Raster Data" => "rasters.md", + "Working with Images" => "images.md", "Tables Interface" => "tables.md", "Geometric Operations" => "geometries.md", "Spatial Projections" => "projections.md", diff --git a/docs/src/images.md b/docs/src/images.md new file mode 100644 index 00000000..ecb1aac7 --- /dev/null +++ b/docs/src/images.md @@ -0,0 +1,53 @@ +# Images + +```@setup rasters +using ArchGDAL +const AG = ArchGDAL +``` + +In this section, we revisit the [`gdalworkshop/world.tif`](https://github.com/yeesian/ArchGDALDatasets/blob/307f8f0e584a39a050c042849004e6a2bd674f99/gdalworkshop/world.tif) dataset. +```@example rasters +dataset = AG.read("gdalworkshop/world.tif") +``` +A description of the display is available in [Raster Datasets](@ref). + +## Reading from Datasets +We can construct an image from it in the following way: +```@example rasters +AG.imread(dataset) +``` + +## Reading from Files +We can read the file as an image instead: +```@example rasters +AG.imread("gdalworkshop/world.tif") +``` + +## Reading from Rasterbands +We can also read from individual raster bands: +```@example rasters +AG.imread(AG.getband(dataset, 1)) +``` +Or equivalently, +```@example rasters +AG.imread(dataset, 1) +``` +It will interpret the color channel (for RGB) correctly there is one. E.g. +```@example rasters +AG.imread(dataset, 2) +``` +and +```@example rasters +AG.imread(dataset, 3) +``` + +## Working with Colors +Operations on colors behave as you think they might: +```@example rasters +AG.imread(dataset, 2) + AG.imread(dataset, 3) +``` +and +```@example rasters +0.5 * AG.imread(dataset, 1) + AG.imread(dataset, 3) +``` +See [Colors.jl](http://juliagraphics.github.io/Colors.jl/stable/) for more on what you can do. diff --git a/src/raster/images.jl b/src/raster/images.jl index 3bddcaad..35e92c14 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -18,17 +18,75 @@ end function imread( colortype::Type{<:ColorTypes.Colorant}, dataset::AbstractDataset, - indices::NTuple{1,<:Integer}, + i::Integer, ) return ImageCore.PermutedDimsArray( ImageCore.colorview( colortype, - ImageCore.normedview(read(dataset, indices[1])), + ImageCore.normedview(read(dataset, i)), ), (2, 1), ) end +function imread( + colortype::Type{<:ColorTypes.Colorant}, + dataset::AbstractDataset, + indices::NTuple{1,<:Integer}, +) + return imread(colortype, dataset, indices[1]) +end + +function imread(band::AbstractRasterBand) + gci = getcolorinterp(band) + imgvalues = read(band) + zerovalues = zeros(eltype(imgvalues), size(imgvalues)) + return if gci == GCI_RedBand + ImageCore.PermutedDimsArray( + ImageCore.colorview( + ColorTypes.RGB, + ImageCore.normedview(imgvalues), + ImageCore.normedview(zerovalues), + ImageCore.normedview(zerovalues), + ), + (2, 1), + ) + elseif gci == GCI_GreenBand + ImageCore.PermutedDimsArray( + ImageCore.colorview( + ColorTypes.RGB, + ImageCore.normedview(zerovalues), + ImageCore.normedview(imgvalues), + ImageCore.normedview(zerovalues), + ), + (2, 1), + ) + elseif gci == GCI_BlueBand + ImageCore.PermutedDimsArray( + ImageCore.colorview( + ColorTypes.RGB, + ImageCore.normedview(zerovalues), + ImageCore.normedview(zerovalues), + ImageCore.normedview(imgvalues), + ), + (2, 1), + ) + else + ImageCore.PermutedDimsArray( + ImageCore.colorview( + ColorTypes.Gray, + ImageCore.normedview(imgvalues), + ), + (2, 1), + ) + end +end + +imread(dataset::AbstractDataset, i::Integer) = imread(getband(dataset, i)) + +imread(dataset::AbstractDataset, indices::NTuple{1,<:Integer}) = + imread(dataset, indices[1]) + function imread( colortype::Type{<:ColorTypes.Colorant}, dataset::AbstractDataset, From ca1ecc322086c6ab85b41b03d11d2c5b1cf0799b Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 15 May 2021 01:31:35 -0700 Subject: [PATCH 108/169] Fix file formatting --- src/raster/images.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index 35e92c14..7142d41c 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -21,10 +21,7 @@ function imread( i::Integer, ) return ImageCore.PermutedDimsArray( - ImageCore.colorview( - colortype, - ImageCore.normedview(read(dataset, i)), - ), + ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, i))), (2, 1), ) end @@ -84,8 +81,9 @@ end imread(dataset::AbstractDataset, i::Integer) = imread(getband(dataset, i)) -imread(dataset::AbstractDataset, indices::NTuple{1,<:Integer}) = - imread(dataset, indices[1]) +function imread(dataset::AbstractDataset, indices::NTuple{1,<:Integer}) + return imread(dataset, indices[1]) +end function imread( colortype::Type{<:ColorTypes.Colorant}, From 52af36465cdec3d9a24accf494f7e2cf054ddaaf Mon Sep 17 00:00:00 2001 From: Felix Cremer Date: Sat, 15 May 2021 13:18:33 -0700 Subject: [PATCH 109/169] Allow to use interactive Datasets in unsafe_gdal functions in utilities.jl --- src/utilities.jl | 62 ++++++++++++++++++++--------- test/test_gdalutilities.jl | 80 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 18 deletions(-) diff --git a/src/utilities.jl b/src/utilities.jl index 7235ec6d..db4611bd 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -1,5 +1,5 @@ """ - gdalinfo(dataset::Dataset, options = String[]) + gdalinfo(dataset::AbstractDataset, options = String[]) List various information about a GDAL supported raster dataset. @@ -11,7 +11,7 @@ List various information about a GDAL supported raster dataset. ### Returns String corresponding to the information about the raster dataset. """ -function gdalinfo(dataset::Dataset, options = String[])::String +function gdalinfo(dataset::AbstractDataset, options = String[])::String options = GDAL.gdalinfooptionsnew(options, C_NULL) result = GDAL.gdalinfo(dataset.ptr, options) GDAL.gdalinfooptionsfree(options) @@ -19,7 +19,10 @@ function gdalinfo(dataset::Dataset, options = String[])::String end """ - unsafe_gdaltranslate(dataset::Dataset, options = String[]; dest = "/vsimem/tmp") + unsafe_gdaltranslate( + dataset::AbstractDataset, + options = String[]; + dest = "/vsimem/tmp") Convert raster data between different formats. @@ -32,7 +35,7 @@ Convert raster data between different formats. The output dataset. """ function unsafe_gdaltranslate( - dataset::Dataset, + dataset::AbstractDataset, options = String[]; dest = "/vsimem/tmp", )::Dataset @@ -44,7 +47,10 @@ function unsafe_gdaltranslate( end """ - unsafe_gdalwarp(datasets::Vector{Dataset}, options = String[]; dest = "/vsimem/tmp") + unsafe_gdalwarp( + datasets::Vector{<:AbstractDataset}, + options = String[]; + dest = "/vsimem/tmp") Image reprojection and warping function. @@ -57,7 +63,7 @@ Image reprojection and warping function. The output dataset. """ function unsafe_gdalwarp( - datasets::Vector{Dataset}, + datasets::Vector{<:AbstractDataset}, options = String[]; dest = "/vsimem/tmp", )::Dataset @@ -76,7 +82,10 @@ function unsafe_gdalwarp( end """ - unsafe_gdalvectortranslate(datasets::Vector{Dataset}, options = String[]; dest = "/vsimem/tmp") + unsafe_gdalvectortranslate( + datasets::Vector{<:AbstractDataset}, + options = String[]; + dest = "/vsimem/tmp") Convert vector data between file formats. @@ -89,7 +98,7 @@ Convert vector data between file formats. The output dataset. """ function unsafe_gdalvectortranslate( - datasets::Vector{Dataset}, + datasets::Vector{<:AbstractDataset}, options = String[]; dest = "/vsimem/tmp", )::Dataset @@ -108,7 +117,12 @@ function unsafe_gdalvectortranslate( end """ - unsafe_gdaldem(dataset::Dataset, processing::String, options = String[]; dest = "/vsimem/tmp", colorfile) + unsafe_gdaldem( + dataset::AbstractDataset, + processing::String, + options = String[]; + dest = "/vsimem/tmp", + colorfile) Tools to analyze and visualize DEMs. @@ -127,7 +141,7 @@ Tools to analyze and visualize DEMs. The output dataset. """ function unsafe_gdaldem( - dataset::Dataset, + dataset::AbstractDataset, processing::String, options = String[]; dest = "/vsimem/tmp", @@ -151,7 +165,10 @@ function unsafe_gdaldem( end """ - unsafe_gdalnearblack(dataset::Dataset, options = String[]; dest = "/vsimem/tmp") + unsafe_gdalnearblack( + dataset::AbstractDataset, + options = String[]; + dest = "/vsimem/tmp") Convert nearly black/white borders to exact value. @@ -164,7 +181,7 @@ Convert nearly black/white borders to exact value. The output dataset. """ function unsafe_gdalnearblack( - dataset::Dataset, + dataset::AbstractDataset, options = String[]; dest = "/vsimem/tmp", )::Dataset @@ -176,7 +193,10 @@ function unsafe_gdalnearblack( end """ - unsafe_gdalgrid(dataset::Dataset, options = String[]; dest = "/vsimem/tmp") + unsafe_gdalgrid( + dataset::AbstractDataset, + options = String[]; + dest = "/vsimem/tmp") Create a raster from the scattered data. @@ -189,7 +209,7 @@ Create a raster from the scattered data. The output dataset. """ function unsafe_gdalgrid( - dataset::Dataset, + dataset::AbstractDataset, options = String[]; dest = "/vsimem/tmp", )::Dataset @@ -201,7 +221,10 @@ function unsafe_gdalgrid( end """ - unsafe_gdalrasterize(dataset::Dataset, options = String[]; dest = "/vsimem/tmp") + unsafe_gdalrasterize( + dataset::AbstractDataset, + options = String[]; + dest = "/vsimem/tmp") Burn vector geometries into a raster. @@ -214,7 +237,7 @@ Burn vector geometries into a raster. The output dataset. """ function unsafe_gdalrasterize( - dataset::Dataset, + dataset::AbstractDataset, options = String[]; dest = "/vsimem/tmp", )::Dataset @@ -226,7 +249,10 @@ function unsafe_gdalrasterize( end """ - unsafe_gdalbuildvrt(datasets::Vector{Dataset}, options = String[]; dest = "/vsimem/tmp") + unsafe_gdalbuildvrt( + datasets::Vector{<:AbstractDataset}, + options = String[]; + dest = "/vsimem/tmp") Build a VRT from a list of datasets. @@ -239,7 +265,7 @@ Build a VRT from a list of datasets. The output dataset. """ function unsafe_gdalbuildvrt( - datasets::Vector{Dataset}, + datasets::Vector{<:AbstractDataset}, options = String[]; dest = "/vsimem/tmp", )::Dataset diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index ca0cf7b2..b8019881 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -169,3 +169,83 @@ using Test end end + +@testset "Interactive data/utmsmall.tif" begin + ds_small = AG.read("data/utmsmall.tif") + @testset "GDAL Error" begin + @test_throws GDAL.GDALError AG.gdalinfo(ds_small, ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdaltranslate(ds_small, ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdalbuildvrt([ds_small], ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdaldem(ds_small, "hillshade", ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdalnearblack(ds_small, ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdalwarp([ds_small], ["-novalidoption"]) + end + + @testset "GDAL Info" begin + infostr = AG.gdalinfo(ds_small, ["-checksum"]) + @test occursin("Checksum=50054", infostr) + info_default = AG.gdalinfo(ds_small) + @test occursin("Driver: GTiff/GeoTIFF", info_default) + end + + ds_tiny = AG.unsafe_gdaltranslate(ds_small, # resample to a 5×5 ascii grid + ["-of","AAIGrid","-r","cubic","-tr","1200","1200"]) + @test typeof(ds_tiny) == AG.Dataset + @testset "GDAL Translate" begin + @test AG.read(ds_tiny, 1) == [128 171 127 93 83; + 126 164 148 114 101; + 161 175 177 164 140; + 185 206 205 172 128; + 193 205 209 181 122] + end + + @testset "GDAL Build VRT" begin + ds_vrt = AG.unsafe_gdalbuildvrt([ds_tiny]) + @test AG.read(ds_vrt, 1) == [128 171 127 93 83; + 126 164 148 114 101; + 161 175 177 164 140; + 185 206 205 172 128; + 193 205 209 181 122] + end + + @testset "GDAL DEM Processing" begin + ds_dempr = AG.unsafe_gdaldem(ds_tiny, "hillshade", ["-of","AAIGrid"]) + @test AG.read(ds_dempr, 1) == [ 0 0 0 0 0; + 0 183 180 181 0; + 0 184 182 181 0; + 0 183 181 177 0; + 0 0 0 0 0] + end + + @testset "GDAL Near Black" begin + ds_nearblack = AG.unsafe_gdalnearblack(ds_tiny, ["-of","GTiff","-color","0"]) + @test AG.read(ds_nearblack, 1) == [ 0 0 0 0 0; + 0 0 0 0 0; + 0 0 177 0 0; + 0 0 0 0 0; + 0 0 0 0 0] + end + + # cannot reproject file on AppVeyor yet + # GDALError (CE_Failure, code 4): + # Unable to open EPSG support file gcs.csv. Try setting the + # GDAL_DATA environment variable to point to the directory + # containing EPSG csv files. + # @testset "GDAL Warp" begin + # AG.gdalwarp([ds_small], ["-of","MEM","-t_srs","EPSG:4326"]) do ds_warped + # @test AG.width(ds_small) == 100 + # @test AG.height(ds_small) == 100 + # @test AG.width(ds_warped) == 109 + # @test AG.height(ds_warped) == 91 + # end + # end + @testset "GDAL Warp" begin + ds_warped = AG.unsafe_gdalwarp([ds_small], ["-of","MEM"]) + @test AG.width(ds_small) == 100 + @test AG.height(ds_small) == 100 + @test AG.shortname(AG.getdriver(ds_small)) == "GTiff" + @test AG.width(ds_warped) == 100 + @test AG.height(ds_warped) == 100 + @test AG.shortname(AG.getdriver(ds_warped)) == "MEM" + end +end From ddc62bfc0490564f1bf55c43cfb5e006432f3b01 Mon Sep 17 00:00:00 2001 From: Aayush Joglekar Date: Sat, 15 May 2021 14:23:42 -0700 Subject: [PATCH 110/169] Replace Pkg.PlatformEngine --> Custom download & verify --- Project.toml | 4 ++- test/remotefiles.jl | 61 ++++++++++++++++++++++++++++++++++++++++----- test/runtests.jl | 3 ++- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/Project.toml b/Project.toml index 3cb66eb0..27d0f6c5 100644 --- a/Project.toml +++ b/Project.toml @@ -25,9 +25,11 @@ julia = "1.3" [extras] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Dates", "Pkg", "Statistics", "Test"] +test = ["Dates", "Downloads", "Pkg", "Statistics", "SHA", "Test"] diff --git a/test/remotefiles.jl b/test/remotefiles.jl index be67cead..250cee13 100644 --- a/test/remotefiles.jl +++ b/test/remotefiles.jl @@ -1,10 +1,5 @@ # this file downloads files which are used during testing the package # if they are already present and their checksum matches, they are not downloaded again - -using Pkg.PlatformEngines - -probe_platform_engines!() # for download - const testdatadir = @__DIR__ REPO_URL = "https://github.com/yeesian/ArchGDALDatasets/blob/master/" @@ -118,6 +113,60 @@ remotefiles = [ ), ] +function verify(path::AbstractString, hash::AbstractString) + @assert occursin(r"^[0-9a-f]{64}$", hash) + hash = lowercase(hash) + if isfile(path) + calc_hash = open(path) do file + bytes2hex(sha256(file)) + end + @assert occursin(r"^[0-9a-f]{64}$", calc_hash) + if calc_hash != hash + @error "Hash Mismatch! Expected: $hash, Calculated: $calc_hash\n" + return false + else + return true + end + else + error("File read error: $path") + end +end + +function download_verify(url::AbstractString, hash::Union{AbstractString, Nothing}, dest::AbstractString) + file_existed = false + # verify if file exists + if isfile(dest) + file_existed = true + if hash !== nothing && verify(dest, hash) + # hash verified + return true + else + # either hash is nothing or couldn't pass the SHA test + @error("Failed to verify file: $dest with hash: $hash. Re-downloading file...") + end + end + # if the file exists but some problem exists, we delete it to start from scratch + file_existed && Base.rm(dest; force=true) + # Make sure the containing folder exists + mkpath(dirname(dest)) + # downloads the file at dest + Downloads.download(url, dest) + # hash exists and verification fails + if hash !== nothing && !verify(dest, hash) + if file_existed + # the file might be corrupted so we start from scracth + Base.rm(dest; force=true) + Downloads.download(url, dest) + if hash !== nothing && !verify(dest, hash) + error("Verification failed") + end + else + error("Verification failed. File not created after download.") + end + end + return !file_existed +end + for (f, sha) in remotefiles # create the directories if they don't exist currdir = dirname(f) @@ -125,5 +174,5 @@ for (f, sha) in remotefiles # download the file if it is not there or if it has a different checksum currfile = normpath(joinpath(testdatadir, f)) url = REPO_URL * f * "?raw=true" - PlatformEngines.download_verify(url, sha, currfile; force = true) + download_verify(url, sha, currfile) end diff --git a/test/runtests.jl b/test/runtests.jl index 589fa061..6e9f0467 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ using Test using Dates -using Pkg.PlatformEngines +using Downloads +using SHA # ensure all testing files are present include("remotefiles.jl") From 86ee7ecc8ff0dd4cd186a557bc6b9009140704ac Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 15 May 2021 14:33:29 -0700 Subject: [PATCH 111/169] Move importing of Downloads and SHA to remotefiles.jl --- test/remotefiles.jl | 3 +++ test/runtests.jl | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/remotefiles.jl b/test/remotefiles.jl index 250cee13..9b465b0c 100644 --- a/test/remotefiles.jl +++ b/test/remotefiles.jl @@ -1,3 +1,6 @@ +using Downloads +using SHA + # this file downloads files which are used during testing the package # if they are already present and their checksum matches, they are not downloaded again const testdatadir = @__DIR__ diff --git a/test/runtests.jl b/test/runtests.jl index 6e9f0467..eba19932 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,5 @@ using Test using Dates -using Downloads -using SHA # ensure all testing files are present include("remotefiles.jl") From 88a9fa5673e648bb6b2f954352d4d27b51c8c818 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 15 May 2021 15:07:21 -0700 Subject: [PATCH 112/169] Add contributor's guide --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 96d6d115..71d7de6d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Coverage Status](https://coveralls.io/repos/github/yeesian/ArchGDAL.jl/badge.svg?branch=master)](https://coveralls.io/github/yeesian/ArchGDAL.jl?branch=master) [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://yeesian.com/ArchGDAL.jl/stable) [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://yeesian.com/ArchGDAL.jl/dev) +[![ColPrac: Contributor's Guide](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac) [GDAL](http://gdal.org/) is a translator library for raster and vector geospatial data formats that is released under an [X/MIT](https://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse) license by the [Open Source Geospatial Foundation](http://www.osgeo.org/). As a library, it presents an abstract data model to drivers for various [raster](http://www.gdal.org/formats_list.html) and [vector](http://www.gdal.org/ogr_formats.html) formats. From ebe90bf83736aa77ed9df9a40a51c4c1c82c009e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Thu, 20 May 2021 21:25:24 -0700 Subject: [PATCH 113/169] Ran JuliaFormatter --- test/remotefiles.jl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/remotefiles.jl b/test/remotefiles.jl index 9b465b0c..a8fe07de 100644 --- a/test/remotefiles.jl +++ b/test/remotefiles.jl @@ -121,7 +121,7 @@ function verify(path::AbstractString, hash::AbstractString) hash = lowercase(hash) if isfile(path) calc_hash = open(path) do file - bytes2hex(sha256(file)) + return bytes2hex(sha256(file)) end @assert occursin(r"^[0-9a-f]{64}$", calc_hash) if calc_hash != hash @@ -135,7 +135,11 @@ function verify(path::AbstractString, hash::AbstractString) end end -function download_verify(url::AbstractString, hash::Union{AbstractString, Nothing}, dest::AbstractString) +function download_verify( + url::AbstractString, + hash::Union{AbstractString,Nothing}, + dest::AbstractString, +) file_existed = false # verify if file exists if isfile(dest) @@ -145,11 +149,13 @@ function download_verify(url::AbstractString, hash::Union{AbstractString, Nothin return true else # either hash is nothing or couldn't pass the SHA test - @error("Failed to verify file: $dest with hash: $hash. Re-downloading file...") + @error( + "Failed to verify file: $dest with hash: $hash. Re-downloading file..." + ) end end # if the file exists but some problem exists, we delete it to start from scratch - file_existed && Base.rm(dest; force=true) + file_existed && Base.rm(dest; force = true) # Make sure the containing folder exists mkpath(dirname(dest)) # downloads the file at dest @@ -158,7 +164,7 @@ function download_verify(url::AbstractString, hash::Union{AbstractString, Nothin if hash !== nothing && !verify(dest, hash) if file_existed # the file might be corrupted so we start from scracth - Base.rm(dest; force=true) + Base.rm(dest; force = true) Downloads.download(url, dest) if hash !== nothing && !verify(dest, hash) error("Verification failed") From c3926c24fd3e1d75e2900a0060f4f663ff321d66 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Thu, 20 May 2021 21:47:26 -0700 Subject: [PATCH 114/169] Fix tables example --- docs/src/tables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tables.md b/docs/src/tables.md index ff34b244..fd6e5668 100644 --- a/docs/src/tables.md +++ b/docs/src/tables.md @@ -35,7 +35,7 @@ dataset. ```@example tables dataset1 = ArchGDAL.read("data/multi_geom.csv", options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"]) -layer = ArchGDAL.getlayer(dataset, 0) +layer = ArchGDAL.getlayer(dataset1, 0) table = ArchGDAL.Table(layer) df = DataFrame(table) ``` From 917f7926bcea8a59bd4734183a9a6d3d9767e105 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Thu, 20 May 2021 21:54:44 -0700 Subject: [PATCH 115/169] ArchGDAL.getgeomdefn -> getgeomdefn --- src/tables.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tables.jl b/src/tables.jl index dff0bbb3..0ad67aab 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -11,10 +11,10 @@ function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema field_names, geom_names, featuredefn, fielddefns = schema_names(layerdefn(layer)) ngeom = ArchGDAL.ngeom(featuredefn) - geomdefns = (ArchGDAL.getgeomdefn(featuredefn, i) for i in 0:ngeom-1) + geom_types = + (IGeometry{gettype(getgeomdefn(featuredefn, i))} for i in 0:ngeom-1) field_types = (convert(DataType, gettype(fielddefn)) for fielddefn in fielddefns) - geom_types = (IGeometry{gettype(geomdefn)} for geomdefn in geomdefns) return Tables.Schema( (geom_names..., field_names...), (geom_types..., field_types...), From a83a33f8d527302cfd033b51f90b0c618bd7258b Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 18:06:57 -0700 Subject: [PATCH 116/169] add a section about the compat entries These are needed, so that Julia can resolve the package versions and it is good practice to have compat entries for all dependencies. Co-authored-by: Felix Cremer --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 71d7de6d..5b422a12 100644 --- a/README.md +++ b/README.md @@ -90,4 +90,6 @@ shell> cd /Users/yeesian/.julia/dev/ArchGDAL [68eda718] + GeoFormatTypes v0.3.0 [cf35fbd7] + GeoInterface v0.5.5 [bd369af6] + Tables v1.4.2 -``` +```4. Add a compat entry into Project.toml so that julia can resolve the versions +``` Open the Project.toml file in a texteditor and add in the [compat] section the line: + CEnum = "0.4" From fcaba40d908d2778799fb3643580196f88805365 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 18:11:47 -0700 Subject: [PATCH 117/169] add compat entries for ColorTypes and ImageCore --- Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index 27d0f6c5..653ffa3c 100644 --- a/Project.toml +++ b/Project.toml @@ -16,10 +16,12 @@ ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" [compat] +ColorTypes = "0.11" DiskArrays = "0.2.4" GDAL = "1.1.3" GeoFormatTypes = "0.3" GeoInterface = "0.4, 0.5" +ImageCore = "0.9" Tables = "1" julia = "1.3" From 6f79b64b2bfc2049e39a7f10c5597e51b28eaf91 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 21:39:15 -0700 Subject: [PATCH 118/169] Add badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5b422a12..6647772c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # ArchGDAL [![CI](https://github.com/yeesian/ArchGDAL.jl/workflows/CI/badge.svg)](https://github.com/yeesian/ArchGDAL.jl/actions?query=workflow%3ACI) [![Coverage Status](https://coveralls.io/repos/github/yeesian/ArchGDAL.jl/badge.svg?branch=master)](https://coveralls.io/github/yeesian/ArchGDAL.jl?branch=master) +[![version](https://juliahub.com/docs/ArchGDAL/version.svg)](https://juliahub.com/ui/Packages/ArchGDAL/MCIiB) [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://yeesian.com/ArchGDAL.jl/stable) [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://yeesian.com/ArchGDAL.jl/dev) [![ColPrac: Contributor's Guide](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac) +[![deps](https://juliahub.com/docs/ArchGDAL/deps.svg)](https://juliahub.com/ui/Packages/ArchGDAL/MCIiB?t=2) [GDAL](http://gdal.org/) is a translator library for raster and vector geospatial data formats that is released under an [X/MIT](https://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse) license by the [Open Source Geospatial Foundation](http://www.osgeo.org/). As a library, it presents an abstract data model to drivers for various [raster](http://www.gdal.org/formats_list.html) and [vector](http://www.gdal.org/ogr_formats.html) formats. From 307f0f2f11414bb9f3586ae5518a7e14c6c425c8 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 21:40:48 -0700 Subject: [PATCH 119/169] rearrange badges for color --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6647772c..e34c732e 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ [![version](https://juliahub.com/docs/ArchGDAL/version.svg)](https://juliahub.com/ui/Packages/ArchGDAL/MCIiB) [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://yeesian.com/ArchGDAL.jl/stable) [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://yeesian.com/ArchGDAL.jl/dev) -[![ColPrac: Contributor's Guide](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac) [![deps](https://juliahub.com/docs/ArchGDAL/deps.svg)](https://juliahub.com/ui/Packages/ArchGDAL/MCIiB?t=2) +[![ColPrac: Contributor's Guide](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac) [GDAL](http://gdal.org/) is a translator library for raster and vector geospatial data formats that is released under an [X/MIT](https://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse) license by the [Open Source Geospatial Foundation](http://www.osgeo.org/). As a library, it presents an abstract data model to drivers for various [raster](http://www.gdal.org/formats_list.html) and [vector](http://www.gdal.org/ogr_formats.html) formats. From 3a0b3a8cb9cb248036d0f80b257d4949e309fb04 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 21:52:08 -0700 Subject: [PATCH 120/169] fix for table geometry v.s. field ordering --- src/tables.jl | 8 ++++---- test/test_tables.jl | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tables.jl b/src/tables.jl index 0ad67aab..dc208746 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -8,7 +8,7 @@ struct Table{T<:AbstractFeatureLayer} end function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema - field_names, geom_names, featuredefn, fielddefns = + geom_names, field_names, featuredefn, fielddefns = schema_names(layerdefn(layer)) ngeom = ArchGDAL.ngeom(featuredefn) geom_types = @@ -53,8 +53,8 @@ end function Tables.columnnames( row::Feature, )::NTuple{Int64(nfield(row) + ngeom(row)),Symbol} - field_names, geom_names = schema_names(getfeaturedefn(row)) - return (field_names..., geom_names...) + geom_names, field_names = schema_names(getfeaturedefn(row)) + return (geom_names..., field_names...) end function schema_names(featuredefn::IFeatureDefnView) @@ -65,7 +65,7 @@ function schema_names(featuredefn::IFeatureDefnView) i in 1:ngeom(featuredefn) ) replace!(geom_names, Symbol("") => Symbol("geometry"), count = 1) - return (field_names, geom_names, featuredefn, fielddefns) + return (geom_names, field_names, featuredefn, fielddefns) end function Base.show(io::IO, t::Table) diff --git a/test/test_tables.jl b/test/test_tables.jl index f174c486..685c4fa4 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -58,7 +58,7 @@ using Tables @test length(features) == 2 @test Tables.columnnames(features[1]) == - (:id, :zoom, :location, :point, :linestring) + (:point, :linestring, :id, :zoom, :location) @test Tables.getcolumn(features[2], -5) == nothing @test Tables.getcolumn(features[2], 0) == nothing @test Tables.getcolumn(features[1], 1) == "5.1" @@ -78,7 +78,7 @@ using Tables @test isnothing(Tables.getcolumn(features[1], :fake)) @test Tables.columnnames(features[2]) == - (:id, :zoom, :location, :point, :linestring) + (:point, :linestring, :id, :zoom, :location) @test Tables.getcolumn(features[2], -5) == nothing @test Tables.getcolumn(features[2], 0) == nothing @test Tables.getcolumn(features[2], 1) == "5.2" @@ -96,10 +96,10 @@ using Tables "LINESTRING (35 15,15 35,45 45)" @test isnothing(Tables.getcolumn(features[2], :fake)) - field_names, geom_names = AG.schema_names(AG.layerdefn(layer)) + geom_names, field_names = AG.schema_names(AG.layerdefn(layer)) @test collect(geom_names) == [:geometry] @test collect(field_names) == [:FID, :pointname] - field_names, geom_names = AG.schema_names(AG.layerdefn(layer1)) + geom_names, field_names = AG.schema_names(AG.layerdefn(layer1)) @test collect(geom_names) == [:point, :linestring] @test collect(field_names) == [:id, :zoom, :location] end From 0ca1a7d0242aa3e62ddeba1a957a398a965c89ce Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 22:36:49 -0700 Subject: [PATCH 121/169] Add conversion for geometries to wkbUnknown This is useful when constructing vectors of geometries of multiple types --- src/convert.jl | 9 +++++++++ test/test_convert.jl | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/convert.jl b/src/convert.jl index 56393754..4b48c4cd 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -49,6 +49,15 @@ function Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) return fromGML(GFT.val(source)) end +function Base.convert( + ::Type{IGeometry{wkbUnknown}}, + source::AbstractGeometry, +) + result = IGeometry(C_NULL) + result.ptr = unsafe_clone(source).ptr + return result +end + """ convert(::Type{<:GeoFormatTypes.AbstractWellKnownText}, source::AbstractGeometry) diff --git a/test/test_convert.jl b/test/test_convert.jl index d457ab9d..9b9e8013 100644 --- a/test/test_convert.jl +++ b/test/test_convert.jl @@ -43,4 +43,12 @@ const GFT = GeoFormatTypes; @test convert(GFT.CoordSys, GFT.CRS(), proj4326) isa GFT.CoordSys @test convert(GFT.GML, GFT.CRS(), proj4326) isa GeoFormatTypes.GML end + + @testset "geometry conversions" begin + geom1 = AG.createpoint(1, 2) + @test typeof(geom1) == AG.IGeometry{AG.wkbPoint} + geom2 = convert(AG.IGeometry{AG.wkbUnknown}, geom1) + @test typeof(geom2) == AG.IGeometry{AG.wkbUnknown} + @test AG.toWKT(geom1) == AG.toWKT(geom2) + end end From 309d598e17fc8d52c3574db3591d792b12f5d5eb Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Fri, 21 May 2021 22:41:04 -0700 Subject: [PATCH 122/169] ran JuliaFormatter --- src/convert.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/convert.jl b/src/convert.jl index 4b48c4cd..1d58acdc 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -49,10 +49,7 @@ function Base.convert(::Type{<:AbstractGeometry}, source::GFT.GML) return fromGML(GFT.val(source)) end -function Base.convert( - ::Type{IGeometry{wkbUnknown}}, - source::AbstractGeometry, -) +function Base.convert(::Type{IGeometry{wkbUnknown}}, source::AbstractGeometry) result = IGeometry(C_NULL) result.ptr = unsafe_clone(source).ptr return result From 3c94ec2c660af240edaabe63e726ab05bde708af Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 22 May 2021 04:02:56 -0700 Subject: [PATCH 123/169] Revamp implementation of imread() to be on-par with read() Needs corresponding unit tests --- src/constants.jl | 2 +- src/raster/images.jl | 319 +++++++++++++++++++++++++++++-------------- 2 files changed, 217 insertions(+), 104 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index e0e56552..5e62a733 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -86,7 +86,7 @@ const StringList = Ptr{Cstring} GCI_PaletteIndex = 2, # Paletted (see associated color table) GCI_RedBand = 3, # Red band of RGBA image GCI_GreenBand = 4, # Green band of RGBA image - GCI_BlueBand = 5, # Green band of RGBA image + GCI_BlueBand = 5, # Blue band of RGBA image GCI_AlphaBand = 6, # Alpha (0=transparent, 255=opaque) GCI_HueBand = 7, # Hue band of HLS image GCI_SaturationBand = 8, # Saturation band of HLS image diff --git a/src/raster/images.jl b/src/raster/images.jl index 7142d41c..399426b5 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -1,146 +1,259 @@ -function imread(colortable::ColorTable, dataset::AbstractDataset, indices) - palette = getcolortable(getband(dataset, indices[1])) do ct - return paletteinterp(ct) +function imview(colortype::Type{<:ColorTypes.Colorant}, imgvalues...) + return ImageCore.PermutedDimsArray( + ImageCore.colorview( + colortype, + (ImageCore.normedview(img) for img in imgvalues)..., + ), + (2, 1), + ) +end + +function imview(gci::GDALColorInterp, imgvalues::Matrix) + return if gci == GCI_GrayIndex + imview(ColorTypes.Gray, imgvalues) + elseif gci == GCI_Undefined + imview(ColorTypes.Gray, imgvalues) + elseif gci == GCI_RedBand + zerovalues = zeros(eltype(imgvalues), size(imgvalues)) + imview(GPI_RGB, imgvalues, zerovalues, zerovalues) + elseif gci == GCI_GreenBand + zerovalues = zeros(eltype(imgvalues), size(imgvalues)) + imview(GPI_RGB, zerovalues, imgvalues, zerovalues) + elseif gci == GCI_BlueBand + zerovalues = zeros(eltype(imgvalues), size(imgvalues)) + imview(GPI_RGB, zerovalues, zerovalues, imgvalues) + else + error( + """ + Unknown GCI: $gci. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. + """, + ) end - colortype = if palette == GPI_Gray - ColorTypes.Gray - elseif palette == GPI_RGB - ColorTypes.RGBA +end + +function imview(gpi::GDALPaletteInterp, imgvalues::Matrix) + return if gpi == GPI_Gray + imview(ColorTypes.Gray, imgvalues) + else + error( + """ + Unsupported GPI: $gpi. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. + """, + ) + end +end + +function imview(gpi::GDALPaletteInterp, c1::Matrix, c2::Matrix, c3::Matrix) + return if gpi == GPI_Gray + imview(ColorTypes.Gray, c1, c2, c3) + elseif gpi == GPI_RGB + imview(ColorTypes.RGB, c1, c2, c3) else - error(""" - $palette not yet supported. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues - """) + error( + """ + Unsupported GPI: $gpi. If it should be supported, please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. + """, + ) end - return imread(colortype, dataset, Tuple(indices)) +end + +function imview( + gpi::GDALPaletteInterp, + c1::Matrix, + c2::Matrix, + c3::Matrix, + c4::Matrix, +) + return if gpi == GPI_Gray + imview(ColorTypes.Gray, c1, c2, c3, c4) + elseif gpi == GPI_RGB + imview(ColorTypes.RGBA, c1, c2, c3, c4) + else + error( + """ + Unsupported GPI: $gpi. If it should be supported, please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. + """, + ) + end +end + +function imread( + colortype::Type{T}, + rb::AbstractRasterBand, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} + return imview(colortype, read(rb, xoffset, yoffset, xsize, ysize)) end function imread( - colortype::Type{<:ColorTypes.Colorant}, + colortype::Type{T}, dataset::AbstractDataset, i::Integer, -) - return ImageCore.PermutedDimsArray( - ImageCore.colorview(colortype, ImageCore.normedview(read(dataset, i))), - (2, 1), + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} + return imread( + colortype, + getband(dataset, i), + xoffset, + yoffset, + xsize, + ysize, ) end function imread( - colortype::Type{<:ColorTypes.Colorant}, + colortype::Type{T}, + rb::AbstractRasterBand, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} + return imview(colortype, read(rb, rows, cols)) +end + +function imread( + colortype::Type{T}, dataset::AbstractDataset, - indices::NTuple{1,<:Integer}, -) - return imread(colortype, dataset, indices[1]) -end - -function imread(band::AbstractRasterBand) - gci = getcolorinterp(band) - imgvalues = read(band) - zerovalues = zeros(eltype(imgvalues), size(imgvalues)) - return if gci == GCI_RedBand - ImageCore.PermutedDimsArray( - ImageCore.colorview( - ColorTypes.RGB, - ImageCore.normedview(imgvalues), - ImageCore.normedview(zerovalues), - ImageCore.normedview(zerovalues), - ), - (2, 1), - ) - elseif gci == GCI_GreenBand - ImageCore.PermutedDimsArray( - ImageCore.colorview( - ColorTypes.RGB, - ImageCore.normedview(zerovalues), - ImageCore.normedview(imgvalues), - ImageCore.normedview(zerovalues), - ), - (2, 1), - ) - elseif gci == GCI_BlueBand - ImageCore.PermutedDimsArray( - ImageCore.colorview( - ColorTypes.RGB, - ImageCore.normedview(zerovalues), - ImageCore.normedview(zerovalues), - ImageCore.normedview(imgvalues), - ), - (2, 1), - ) - else - ImageCore.PermutedDimsArray( - ImageCore.colorview( - ColorTypes.Gray, - ImageCore.normedview(imgvalues), - ), - (2, 1), - ) - end + i::Integer, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} + return imread(colortype, getband(dataset, i), rows, cols) +end + +function imread( + colortype::Type{T}, + rb::AbstractRasterBand, +) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} + return imview(colortype, read(rb)) end -imread(dataset::AbstractDataset, i::Integer) = imread(getband(dataset, i)) +function imread( + colortype::Type{T}, + dataset::AbstractDataset, + i::Integer, +) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} + return imread(colortype, getband(dataset, i)) +end -function imread(dataset::AbstractDataset, indices::NTuple{1,<:Integer}) - return imread(dataset, indices[1]) +function imread( + rb::AbstractRasterBand, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +) + return imview(getcolorinterp(rb), read(rb, xoffset, yoffset, xsize, ysize)) end function imread( - colortype::Type{<:ColorTypes.Colorant}, dataset::AbstractDataset, - indices::NTuple{3,<:Integer}, + i::Integer, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, ) - return ImageCore.PermutedDimsArray( - ImageCore.colorview( - colortype, - ImageCore.normedview(read(dataset, indices[1])), - ImageCore.normedview(read(dataset, indices[2])), - ImageCore.normedview(read(dataset, indices[3])), - ), - (2, 1), - ) + return imread(getband(dataset, i), xoffset, yoffset, xsize, ysize) end function imread( - colortype::Type{<:ColorTypes.Colorant}, - dataset::Dataset, - indices::NTuple{4,<:Integer}, + rb::AbstractRasterBand, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, ) - return ImageCore.PermutedDimsArray( - ImageCore.colorview( - colortype, - ImageCore.normedview(read(dataset, indices[1])), - ImageCore.normedview(read(dataset, indices[2])), - ImageCore.normedview(read(dataset, indices[3])), - ImageCore.normedview(read(dataset, indices[4])), - ), - (2, 1), - ) + return imview(getcolorinterp(rb), read(rb, rows, cols)) end -function imread(dataset::AbstractDataset, indices) +function imread( + dataset::AbstractDataset, + i::Integer, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +) + return imread(getband(dataset, i), rows, cols) +end + +function imread(rb::AbstractRasterBand) + return imview(getcolorinterp(rb), read(rb)) +end + +function imread(dataset::AbstractDataset, i::Integer) + return imread(getband(dataset, i)) +end + +# function imread(dataset::AbstractDataset, indices::NTuple{1,<:Integer}) +# return imread(dataset, indices[1]) +# end + +function _paletteindices(dataset::AbstractDataset, indices) gci = unique( GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices], ) gciorder = sort(gci) return if gciorder == [GCI_GrayIndex] - imread(ColorTypes.Gray, dataset, Tuple(indices[sortperm(gci)])) + GPI_Gray, Tuple(indices[sortperm(gci)]) elseif gciorder == [GCI_PaletteIndex] - getcolortable(getband(dataset, 1)) do ct - return imread(ct, dataset, indices) + gpi = getcolortable(getband(dataset, indices[1])) do ct + return paletteinterp(ct) end + gpi, Tuple(indices) elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand] - imread(ColorTypes.RGB, dataset, Tuple(indices[sortperm(gci)])) + GPI_RGB, Tuple(indices[sortperm(gci)]) elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand] - imread(ColorTypes.RGBA, dataset, Tuple(indices[sortperm(gci)])) + GPI_RGB, Tuple(indices[sortperm(gci)]) else - error(""" - Unknown GCI: $gciorder. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues - """) + error( + """ + Unknown GCI: $gciorder. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. + """, + ) end end +function imread( + dataset::AbstractDataset, + indices, + xoffset::Integer, + yoffset::Integer, + xsize::Integer, + ysize::Integer, +) + gpi, idxs = _paletteindices(dataset, indices) + return imview( + gpi, + ( + read(getband(dataset, i), xoffset, yoffset, xsize, ysize) for + i in idxs + )..., + ) +end + +function imread( + dataset::AbstractDataset, + indices, + rows::UnitRange{<:Integer}, + cols::UnitRange{<:Integer}, +) + gpi, idxs = _paletteindices(dataset, indices) + return imview(gpi, (read(getband(dataset, i), rows, cols) for i in idxs)...) +end + +function imread(dataset::AbstractDataset, indices) + gpi, idxs = _paletteindices(dataset, indices) + return imview(gpi, (read(getband(dataset, i)) for i in idxs)...) +end + imread(dataset::AbstractDataset) = imread(dataset, 1:nraster(dataset)) function imread(filename::String) From ff3d2ebafe6674310ac5e0e364df453e33cb41d3 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 22 May 2021 10:27:13 -0700 Subject: [PATCH 124/169] Add tests for images --- src/raster/images.jl | 24 +++++++++++------------ test/test_images.jl | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index 399426b5..41ab9bb3 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -82,25 +82,25 @@ function imview( end function imread( - colortype::Type{T}, + colortype::Union{GDALPaletteInterp, GDALColorInterp}, rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer, -) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} +) return imview(colortype, read(rb, xoffset, yoffset, xsize, ysize)) end function imread( - colortype::Type{T}, + colortype::Union{GDALPaletteInterp, GDALColorInterp}, dataset::AbstractDataset, i::Integer, xoffset::Integer, yoffset::Integer, xsize::Integer, ysize::Integer, -) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} +) return imread( colortype, getband(dataset, i), @@ -112,36 +112,36 @@ function imread( end function imread( - colortype::Type{T}, + colortype::Union{GDALPaletteInterp, GDALColorInterp}, rb::AbstractRasterBand, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, -) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} +) return imview(colortype, read(rb, rows, cols)) end function imread( - colortype::Type{T}, + colortype::Union{GDALPaletteInterp, GDALColorInterp}, dataset::AbstractDataset, i::Integer, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, -) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} +) return imread(colortype, getband(dataset, i), rows, cols) end function imread( - colortype::Type{T}, + colortype::Union{GDALPaletteInterp, GDALColorInterp}, rb::AbstractRasterBand, -) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} +) return imview(colortype, read(rb)) end function imread( - colortype::Type{T}, + colortype::Union{GDALPaletteInterp, GDALColorInterp}, dataset::AbstractDataset, i::Integer, -) where {T<:Union{GDALPaletteInterp,GDALColorInterp}} +) return imread(colortype, getband(dataset, i)) end diff --git a/test/test_images.jl b/test/test_images.jl index d479ebe5..bb586fe6 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -23,11 +23,56 @@ import ColorTypes nbands = 4, dtype = UInt8, ) do dataset + @testset "imview" begin + @test eltype(AG.imview(AG.GCI_GrayIndex, ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_Undefined, ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_RedBand, ones(UInt8, 2, 2))) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_GreenBand, ones(UInt8, 2, 2))) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_BlueBand, ones(UInt8, 2, 2))) == ColorTypes.RGB{ImageCore.N0f8} + @test_throws ErrorException AG.imview(AG.GCI_Max, ones(UInt8, 2, 2)) + @test eltype(AG.imview(AG.GPI_Gray, ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imview(AG.GPI_Gray, ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} + @test_throws ErrorException AG.imview(AG.GPI_HLS, ones(UInt8, 2, 2)) + @test_throws ErrorException AG.imview(AG.GPI_HLS, ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2)) + @test_throws ErrorException AG.imview(AG.GPI_HLS, ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2)) + end + + @testset "imread(color, ..., xoffset, yoffset, xsize, ysize)" begin + @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1), 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1), 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1, 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, dataset, 1, 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} + end + + @testset "imread(color, ..., rows::UnitRange, cols::UnitRange)" begin + @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1), 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1), 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1, 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, dataset, 1, 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} + end + + @testset "imread(color, ...)" begin + @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1))) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1))) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, dataset, 1)) == ColorTypes.Gray{ImageCore.N0f8} + end + @testset "Test RGBA colors" begin AG.setcolorinterp!(AG.getband(dataset, 1), AG.GCI_RedBand) AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_GreenBand) AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_BlueBand) AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_AlphaBand) + @test eltype(AG.imread(AG.getband(dataset, 1))) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1)) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1), 0, 0, 2, 2)) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1, 0, 0, 2, 2)) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1), 1:2, 1:2)) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1, 1:2, 1:2)) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1))) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1)) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1:4, 0, 0, 2, 2)) == ColorTypes.RGBA{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1:4, 1:2, 1:2)) == ColorTypes.RGBA{ImageCore.N0f8} @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} end From 421cac0523d23e8ba908405f7c3d9e64c506890e Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 22 May 2021 10:34:05 -0700 Subject: [PATCH 125/169] Ran JuliaFormatter --- src/raster/images.jl | 12 ++-- test/test_geometry.jl | 106 ++++++++++++++++++++++-------- test/test_geos_operations.jl | 73 +++++++++++++++++---- test/test_geotransform.jl | 27 ++++++-- test/test_images.jl | 123 ++++++++++++++++++++++++----------- test/test_iterators.jl | 2 - test/test_ospy_examples.jl | 39 ++++++----- test/test_rasterattrtable.jl | 35 +++++++--- test/test_rasterband.jl | 22 ++++--- test/test_rasterio.jl | 61 ++++++++++++----- test/test_spatialref.jl | 26 +++++--- test/test_styletable.jl | 6 +- test/test_tables.jl | 5 +- test/test_types.jl | 31 +++++---- test/test_utils.jl | 2 - 15 files changed, 400 insertions(+), 170 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index 41ab9bb3..4cb9d52e 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -82,7 +82,7 @@ function imview( end function imread( - colortype::Union{GDALPaletteInterp, GDALColorInterp}, + colortype::Union{GDALPaletteInterp,GDALColorInterp}, rb::AbstractRasterBand, xoffset::Integer, yoffset::Integer, @@ -93,7 +93,7 @@ function imread( end function imread( - colortype::Union{GDALPaletteInterp, GDALColorInterp}, + colortype::Union{GDALPaletteInterp,GDALColorInterp}, dataset::AbstractDataset, i::Integer, xoffset::Integer, @@ -112,7 +112,7 @@ function imread( end function imread( - colortype::Union{GDALPaletteInterp, GDALColorInterp}, + colortype::Union{GDALPaletteInterp,GDALColorInterp}, rb::AbstractRasterBand, rows::UnitRange{<:Integer}, cols::UnitRange{<:Integer}, @@ -121,7 +121,7 @@ function imread( end function imread( - colortype::Union{GDALPaletteInterp, GDALColorInterp}, + colortype::Union{GDALPaletteInterp,GDALColorInterp}, dataset::AbstractDataset, i::Integer, rows::UnitRange{<:Integer}, @@ -131,14 +131,14 @@ function imread( end function imread( - colortype::Union{GDALPaletteInterp, GDALColorInterp}, + colortype::Union{GDALPaletteInterp,GDALColorInterp}, rb::AbstractRasterBand, ) return imview(colortype, read(rb)) end function imread( - colortype::Union{GDALPaletteInterp, GDALColorInterp}, + colortype::Union{GDALPaletteInterp,GDALColorInterp}, dataset::AbstractDataset, i::Integer, ) diff --git a/test/test_geometry.jl b/test/test_geometry.jl index 6ace0d10..4beeb4be 100644 --- a/test/test_geometry.jl +++ b/test/test_geometry.jl @@ -4,7 +4,6 @@ const AG = ArchGDAL const GFT = GeoFormatTypes @testset "test_geometry.jl" begin - @testset "Incomplete GeoInterface geometries" begin @test_logs (:warn, "unknown geometry type") GeoInterface.geotype( AG.creategeom(AG.wkbCircularString), @@ -33,7 +32,11 @@ const GFT = GeoFormatTypes # Method 1 AG.createpoint(100, 70) do point @test GeoInterface.geotype(point) == :Point - @test isapprox(GeoInterface.coordinates(point), [100, 70], atol = 1e-6) + @test isapprox( + GeoInterface.coordinates(point), + [100, 70], + atol = 1e-6, + ) @test AG.geomdim(point) == 0 @test AG.getcoorddim(point) == 2 AG.setcoorddim!(point, 3) @@ -115,9 +118,11 @@ const GFT = GeoFormatTypes @test AG.toKML(point, "clampToGround") == "clampToGround" * "100,70,0" - @test AG.toKML(point) == "100,70,0" + @test AG.toKML(point) == + "100,70,0" @test AG.toJSON(point) == - "{ \"type\": \"Point\", \"coordinates\": " * "[ 100.0, 70.0, 0.0 ] }" + "{ \"type\": \"Point\", \"coordinates\": " * + "[ 100.0, 70.0, 0.0 ] }" @test startswith( AG.toJSON(point, SIGNIFICANT_FIGURES = 1), "{ \"type\": \"Point\", \"coordinates\": [", @@ -127,7 +132,11 @@ const GFT = GeoFormatTypes "{ \"type\": \"Point\", \"coordinates\": [", ) AG.createpoint(100, 70, 0) do point2 - @test isapprox(GeoInterface.coordinates(point2), [100, 70, 0], atol = 1e-6) + @test isapprox( + GeoInterface.coordinates(point2), + [100, 70, 0], + atol = 1e-6, + ) @test AG.equals(point, point2) == true end AG.createpoint((100, 70, 0)) do point3 @@ -233,7 +242,8 @@ const GFT = GeoFormatTypes @test AG.toKML(point, "clampToGround") == "clampToGround" * "100,70,0" - @test AG.toKML(point) == "100,70,0" + @test AG.toKML(point) == + "100,70,0" @test AG.toJSON(point) == "{ \"type\": \"Point\", \"coordinates\": [ 100.0, 70.0, 0.0 ] }" @test AG.equals(point, AG.createpoint(100, 70, 0)) == true @@ -268,7 +278,11 @@ const GFT = GeoFormatTypes @test GFT.val(convert(GFT.WellKnownText, geom)) == AG.toWKT(geom) @test typeof(geom) == AG.Geometry{AG.wkbLineString} end - AG.createlinestring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + AG.createlinestring( + [1.0, 2.0, 3.0], + [4.0, 5.0, 6.0], + [7.0, 8.0, 9.0], + ) do geom @test AG.toWKT(geom) == "LINESTRING (1 4 7,2 5 8,3 6 9)" AG.setpoint!(geom, 1, 10, 10, 10) @test AG.toWKT(geom) == "LINESTRING (1 4 7,10 10 10,3 6 9)" @@ -292,7 +306,11 @@ const GFT = GeoFormatTypes @test AG.toWKT(geom) == "LINEARRING EMPTY" @test typeof(geom) == AG.Geometry{AG.wkbLineString} # this seems odd end - AG.createlinearring([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + AG.createlinearring( + [1.0, 2.0, 3.0], + [4.0, 5.0, 6.0], + [7.0, 8.0, 9.0], + ) do geom @test AG.toWKT(geom) == "LINEARRING (1 4 7,2 5 8,3 6 9)" AG.closerings!(geom) @test AG.toWKT(geom) == "LINEARRING (1 4 7,2 5 8,3 6 9,1 4 7)" @@ -310,7 +328,11 @@ const GFT = GeoFormatTypes @test AG.toWKT(geom) == "POLYGON ((1 4,2 5,3 6))" @test typeof(geom) == AG.Geometry{AG.wkbPolygon} end - AG.createpolygon([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + AG.createpolygon( + [1.0, 2.0, 3.0], + [4.0, 5.0, 6.0], + [7.0, 8.0, 9.0], + ) do geom @test AG.toWKT(geom) == "POLYGON ((1 4 7,2 5 8,3 6 9))" AG.closerings!(geom) @test AG.toWKT(geom) == "POLYGON ((1 4 7,2 5 8,3 6 9,1 4 7))" @@ -328,7 +350,11 @@ const GFT = GeoFormatTypes @test AG.toWKT(geom) == "MULTIPOINT (1 4,2 5,3 6)" @test typeof(geom) == AG.Geometry{AG.wkbMultiPoint} end - AG.createmultipoint([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) do geom + AG.createmultipoint( + [1.0, 2.0, 3.0], + [4.0, 5.0, 6.0], + [7.0, 8.0, 9.0], + ) do geom @test AG.toWKT(geom) == "MULTIPOINT (1 4 7,2 5 8,3 6 9)" end @@ -365,7 +391,10 @@ const GFT = GeoFormatTypes @test isapprox( GeoInterface.coordinates(geom), [ - [[[0, 0], [0, 4], [4, 4], [4, 0]], [[1, 1], [1, 3], [3, 3], [3, 1]]], + [ + [[0, 0], [0, 4], [4, 4], [4, 0]], + [[1, 1], [1, 3], [3, 3], [3, 1]], + ], [ [[10, 0], [10, 4], [14, 4], [14, 0]], [[11, 1], [11, 3], [13, 3], [13, 1]], @@ -399,27 +428,37 @@ const GFT = GeoFormatTypes "(-1 0,0.0 0.5,1 0,0 1,-1 0))" @test typeof(clgeom) == AG.Geometry{AG.wkbCurvePolygon} end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + @test AG.ngeom( + AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString)), + ) == 2 AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom @test typeof(mlsgeom) == AG.Geometry{AG.wkbMultiLineString} AG.polygonize(mlsgeom) do plgeom @test AG.ngeom(plgeom) == 2 - @test typeof(plgeom) == AG.Geometry{AG.wkbGeometryCollection} + @test typeof(plgeom) == + AG.Geometry{AG.wkbGeometryCollection} end end end @test startswith( AG.toWKT( - AG.curvegeom(AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT = "NO")), + AG.curvegeom( + AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT = "NO"), + ), ), "CURVEPOLYGON (CIRCULARSTRING (", ) AG.lineargeom(geom, 0.5, ADD_INTERMEDIATE_POINT = "NO") do lgeom AG.curvegeom(lgeom) do clgeom - @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") + @test startswith( + AG.toWKT(clgeom), + "CURVEPOLYGON (CIRCULARSTRING (", + ) end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + @test AG.ngeom( + AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString)), + ) == 2 AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom AG.polygonize(mlsgeom) do plgeom @test AG.ngeom(plgeom) == 2 @@ -429,15 +468,22 @@ const GFT = GeoFormatTypes @test startswith( AG.toWKT( - AG.curvegeom(AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5)), + AG.curvegeom( + AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5), + ), ), "CURVEPOLYGON (CIRCULARSTRING (", ) AG.lineargeom(geom, ["ADD_INTERMEDIATE_POINT=NO"], 0.5) do lgeom AG.curvegeom(lgeom) do clgeom - @test startswith(AG.toWKT(clgeom), "CURVEPOLYGON (CIRCULARSTRING (") + @test startswith( + AG.toWKT(clgeom), + "CURVEPOLYGON (CIRCULARSTRING (", + ) end - @test AG.ngeom(AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString))) == 2 + @test AG.ngeom( + AG.polygonize(AG.forceto(lgeom, AG.wkbMultiLineString)), + ) == 2 AG.forceto(lgeom, AG.wkbMultiLineString) do mlsgeom AG.polygonize(mlsgeom) do plgeom @test AG.ngeom(plgeom) == 2 @@ -460,7 +506,11 @@ const GFT = GeoFormatTypes ], ], ) - geom2 = AG.createmultipoint([1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]) + geom2 = AG.createmultipoint( + [1.0, 2.0, 3.0], + [4.0, 5.0, 6.0], + [7.0, 8.0, 9.0], + ) AG.closerings!(geom1) @test AG.disjoint(geom1, geom2) == false @@ -667,7 +717,8 @@ const GFT = GeoFormatTypes [1.0, 4.0], ]]) do geom4 @test AG.toWKT(geom4) == "MULTILINESTRING ((1 4,2 5,3 6,1 4))" - @test AG.toWKT(AG.polygonfromedges(geom4, 0.1)) == "POLYGON ((1 4,2 5,3 6,1 4))" + @test AG.toWKT(AG.polygonfromedges(geom4, 0.1)) == + "POLYGON ((1 4,2 5,3 6,1 4))" AG.polygonfromedges(geom4, 0.1) do geom5 @test AG.toWKT(geom5) == "POLYGON ((1 4,2 5,3 6,1 4))" end @@ -703,9 +754,11 @@ const GFT = GeoFormatTypes end AG.createpoint(100, 70, 0) do geom - @test sprint(print, AG.getspatialref(geom)) == "NULL Spatial Reference System" + @test sprint(print, AG.getspatialref(geom)) == + "NULL Spatial Reference System" AG.getspatialref(geom) do spatialref - @test sprint(print, spatialref) == "NULL Spatial Reference System" + @test sprint(print, spatialref) == + "NULL Spatial Reference System" end end @@ -716,14 +769,16 @@ const GFT = GeoFormatTypes @test AG.toPROJ4(AG.getspatialref(geom)) == "+proj=longlat +datum=WGS84 +no_defs" AG.getspatialref(geom) do spatialref - @test AG.toPROJ4(spatialref) == "+proj=longlat +datum=WGS84 +no_defs" + @test AG.toPROJ4(spatialref) == + "+proj=longlat +datum=WGS84 +no_defs" end end AG.createpoint(1, 2) do point @test sprint(print, AG.getspatialref(point)) == "NULL Spatial Reference System" AG.getspatialref(point) do spatialref - @test sprint(print, spatialref) == "NULL Spatial Reference System" + @test sprint(print, spatialref) == + "NULL Spatial Reference System" end end end @@ -749,5 +804,4 @@ const GFT = GeoFormatTypes @test sprint(print, g) == "NULL Geometry" end end - end diff --git a/test/test_geos_operations.jl b/test/test_geos_operations.jl index 559739a1..5f8e7d58 100644 --- a/test/test_geos_operations.jl +++ b/test/test_geos_operations.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_geos_operations.jl" begin - function equivalent_to_wkt(geom::AG.Geometry, wkt::String) fromWKT(wkt) do test_geom @test toWKT(geom) == toWKT(test_geom) @@ -11,9 +10,18 @@ const AG = ArchGDAL; end @testset "Interpolation along a LineString" begin - AG.createlinestring([(8.0, 1.0), (9.0, 1.0), (9.0, 2.0), (8.0, 2.0)]) do ls - for (dist, dest) in - [(1.0, (9, 1)), (2.0, (9, 2)), (1.5, (9.0, 1.5)), (2.5, (8.5, 2.0))] + AG.createlinestring([ + (8.0, 1.0), + (9.0, 1.0), + (9.0, 2.0), + (8.0, 2.0), + ]) do ls + for (dist, dest) in [ + (1.0, (9, 1)), + (2.0, (9, 2)), + (1.5, (9.0, 1.5)), + (2.5, (8.5, 2.0)), + ] AG.pointalongline(ls, dist) do pt1 AG.createpoint(dest) do pt2 @test AG.toWKT(pt1) == AG.toWKT(pt2) @@ -69,7 +77,8 @@ const AG = ArchGDAL; @test AG.isempty(g2) == true @test AG.toWKT(g2) == "MULTILINESTRING EMPTY" end - @test AG.toWKT(AG.delaunaytriangulation(g1, 0, true)) == "MULTILINESTRING EMPTY" + @test AG.toWKT(AG.delaunaytriangulation(g1, 0, true)) == + "MULTILINESTRING EMPTY" end AG.fromWKT("POINT(0 0)") do g1 AG.delaunaytriangulation(g1, 0, false) do g2 @@ -103,7 +112,11 @@ const AG = ArchGDAL; end end - function test_method(f::Function, wkt1::AbstractString, wkt2::AbstractString) + function test_method( + f::Function, + wkt1::AbstractString, + wkt2::AbstractString, + ) AG.fromWKT(wkt1) do geom f(geom) do result @test AG.toWKT(result) == wkt2 @@ -115,13 +128,21 @@ const AG = ArchGDAL; @testset "Centroid" begin test_method(AG.centroid, "POINT(10 0)", "POINT (10 0)") test_method(AG.centroid, "LINESTRING(0 0, 10 0)", "POINT (5 0)") - test_method(AG.centroid, "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", "POINT (5 5)") + test_method( + AG.centroid, + "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", + "POINT (5 5)", + ) test_method(AG.centroid, "LINESTRING EMPTY", "POINT EMPTY") end @testset "Point on Surface" begin test_method(AG.pointonsurface, "POINT(10 0)", "POINT (10 0)") - test_method(AG.pointonsurface, "LINESTRING(0 0, 5 0, 10 0)", "POINT (5 0)") + test_method( + AG.pointonsurface, + "LINESTRING(0 0, 5 0, 10 0)", + "POINT (5 0)", + ) test_method( AG.pointonsurface, "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", @@ -148,7 +169,12 @@ const AG = ArchGDAL; end @testset "Intersection" begin - test_method(AG.intersection, "POLYGON EMPTY", "POLYGON EMPTY", "POLYGON EMPTY") + test_method( + AG.intersection, + "POLYGON EMPTY", + "POLYGON EMPTY", + "POLYGON EMPTY", + ) test_method( AG.intersection, "POLYGON((1 1,1 5,5 5,5 1,1 1))", @@ -179,8 +205,18 @@ const AG = ArchGDAL; @testset "Intersects" begin test_predicate(AG.intersects, "POLYGON EMPTY", "POLYGON EMPTY", false) - test_predicate(AG.intersects, "POLYGON((1 1,1 5,5 5,5 1,1 1))", "POINT(2 2)", true) - test_predicate(AG.intersects, "POINT(2 2)", "POLYGON((1 1,1 5,5 5,5 1,1 1))", true) + test_predicate( + AG.intersects, + "POLYGON((1 1,1 5,5 5,5 1,1 1))", + "POINT(2 2)", + true, + ) + test_predicate( + AG.intersects, + "POINT(2 2)", + "POLYGON((1 1,1 5,5 5,5 1,1 1))", + true, + ) test_predicate( AG.intersects, "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", @@ -197,8 +233,18 @@ const AG = ArchGDAL; @testset "Within" begin test_predicate(AG.within, "POLYGON EMPTY", "POLYGON EMPTY", false) - test_predicate(AG.within, "POLYGON((1 1,1 5,5 5,5 1,1 1))", "POINT(2 2)", false) - test_predicate(AG.within, "POINT(2 2)", "POLYGON((1 1,1 5,5 5,5 1,1 1))", true) + test_predicate( + AG.within, + "POLYGON((1 1,1 5,5 5,5 1,1 1))", + "POINT(2 2)", + false, + ) + test_predicate( + AG.within, + "POINT(2 2)", + "POLYGON((1 1,1 5,5 5,5 1,1 1))", + true, + ) test_predicate( AG.within, "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))", @@ -234,5 +280,4 @@ const AG = ArchGDAL; "POLYGON ((56.5286666667 25.2101666667,56.529 25.2105,56.5288333333 25.2103333333,56.5286666667 25.2101666667))" end end - end diff --git a/test/test_geotransform.jl b/test/test_geotransform.jl index a474bee1..8ec5814d 100644 --- a/test/test_geotransform.jl +++ b/test/test_geotransform.jl @@ -3,16 +3,33 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_geotransform.jl" begin - - f(gt, pixel, line) = - [gt[1] + pixel * gt[2] + line * gt[3], gt[4] + pixel * gt[5] + line * gt[6]] - gt1 = [-1111950.519667, 463.3127165279167, 0.0, 6671703.118, 0.0, -463.3127165279165] + function f(gt, pixel, line) + return [ + gt[1] + pixel * gt[2] + line * gt[3], + gt[4] + pixel * gt[5] + line * gt[6], + ] + end + gt1 = [ + -1111950.519667, + 463.3127165279167, + 0.0, + 6671703.118, + 0.0, + -463.3127165279165, + ] for (pixel, line) in ((0.0, 0.0), (3.0, 2.0), (15.5, 9.9)) @test AG.applygeotransform(gt1, pixel, line) ≈ f(gt1, pixel, line) end gt2 = AG.invgeotransform(gt1) - @test gt2 ≈ [2400.0, 0.0021583694216166533, 0.0, 14400.0, 0.0, -0.002158369421616654] + @test gt2 ≈ [ + 2400.0, + 0.0021583694216166533, + 0.0, + 14400.0, + 0.0, + -0.002158369421616654, + ] gt3 = AG.composegeotransform(gt1, gt2) @test gt3 ≈ [0.0, 1.0, 0.0, 0.0, 0.0, 1.0] diff --git a/test/test_images.jl b/test/test_images.jl index bb586fe6..d81faded 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -5,9 +5,9 @@ import ImageCore import ColorTypes @testset "test_images.jl" begin - @testset "Test Gray colors" begin - @test eltype(AG.imread("data/utmsmall.tif")) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread("data/utmsmall.tif")) == + ColorTypes.Gray{ImageCore.N0f8} end AG.read("gdalworkshop/world.tif") do dataset @@ -24,38 +24,78 @@ import ColorTypes dtype = UInt8, ) do dataset @testset "imview" begin - @test eltype(AG.imview(AG.GCI_GrayIndex, ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imview(AG.GCI_Undefined, ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imview(AG.GCI_RedBand, ones(UInt8, 2, 2))) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imview(AG.GCI_GreenBand, ones(UInt8, 2, 2))) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imview(AG.GCI_BlueBand, ones(UInt8, 2, 2))) == ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_GrayIndex, ones(UInt8, 2, 2))) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_Undefined, ones(UInt8, 2, 2))) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_RedBand, ones(UInt8, 2, 2))) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_GreenBand, ones(UInt8, 2, 2))) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imview(AG.GCI_BlueBand, ones(UInt8, 2, 2))) == + ColorTypes.RGB{ImageCore.N0f8} @test_throws ErrorException AG.imview(AG.GCI_Max, ones(UInt8, 2, 2)) - @test eltype(AG.imview(AG.GPI_Gray, ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imview(AG.GPI_Gray, ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2))) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imview(AG.GPI_Gray, ones(UInt8, 2, 2))) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype( + AG.imview( + AG.GPI_Gray, + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ), + ) == ColorTypes.Gray{ImageCore.N0f8} @test_throws ErrorException AG.imview(AG.GPI_HLS, ones(UInt8, 2, 2)) - @test_throws ErrorException AG.imview(AG.GPI_HLS, ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2)) - @test_throws ErrorException AG.imview(AG.GPI_HLS, ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2), ones(UInt8, 2, 2)) + @test_throws ErrorException AG.imview( + AG.GPI_HLS, + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ) + @test_throws ErrorException AG.imview( + AG.GPI_HLS, + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ones(UInt8, 2, 2), + ) end @testset "imread(color, ..., xoffset, yoffset, xsize, ysize)" begin - @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1), 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1), 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1, 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GPI_Gray, dataset, 1, 0, 0, 2, 2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype( + AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1), 0, 0, 2, 2), + ) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype( + AG.imread(AG.GPI_Gray, AG.getband(dataset, 1), 0, 0, 2, 2), + ) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1, 0, 0, 2, 2)) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, dataset, 1, 0, 0, 2, 2)) == + ColorTypes.Gray{ImageCore.N0f8} end @testset "imread(color, ..., rows::UnitRange, cols::UnitRange)" begin - @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1), 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1), 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1, 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GPI_Gray, dataset, 1, 1:2, 1:2)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype( + AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1), 1:2, 1:2), + ) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype( + AG.imread(AG.GPI_Gray, AG.getband(dataset, 1), 1:2, 1:2), + ) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1, 1:2, 1:2)) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, dataset, 1, 1:2, 1:2)) == + ColorTypes.Gray{ImageCore.N0f8} end @testset "imread(color, ...)" begin - @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1))) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1))) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1)) == ColorTypes.Gray{ImageCore.N0f8} - @test eltype(AG.imread(AG.GPI_Gray, dataset, 1)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, AG.getband(dataset, 1))) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, AG.getband(dataset, 1))) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GCI_GrayIndex, dataset, 1)) == + ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(AG.GPI_Gray, dataset, 1)) == + ColorTypes.Gray{ImageCore.N0f8} end @testset "Test RGBA colors" begin @@ -63,16 +103,26 @@ import ColorTypes AG.setcolorinterp!(AG.getband(dataset, 2), AG.GCI_GreenBand) AG.setcolorinterp!(AG.getband(dataset, 3), AG.GCI_BlueBand) AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_AlphaBand) - @test eltype(AG.imread(AG.getband(dataset, 1))) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(dataset, 1)) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(AG.getband(dataset, 1), 0, 0, 2, 2)) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(dataset, 1, 0, 0, 2, 2)) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(AG.getband(dataset, 1), 1:2, 1:2)) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(dataset, 1, 1:2, 1:2)) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(AG.getband(dataset, 1))) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(dataset, 1)) == ColorTypes.RGB{ImageCore.N0f8} - @test eltype(AG.imread(dataset, 1:4, 0, 0, 2, 2)) == ColorTypes.RGBA{ImageCore.N0f8} - @test eltype(AG.imread(dataset, 1:4, 1:2, 1:2)) == ColorTypes.RGBA{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1))) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1)) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1), 0, 0, 2, 2)) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1, 0, 0, 2, 2)) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1), 1:2, 1:2)) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1, 1:2, 1:2)) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(AG.getband(dataset, 1))) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1)) == + ColorTypes.RGB{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1:4, 0, 0, 2, 2)) == + ColorTypes.RGBA{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 1:4, 1:2, 1:2)) == + ColorTypes.RGBA{ImageCore.N0f8} @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} end @@ -93,7 +143,7 @@ import ColorTypes AG.setcolortable!(AG.getband(dataset, 1), ct) AG.setcolortable!(AG.getband(dataset, 2), ct) AG.setcolortable!(AG.getband(dataset, 3), ct) - AG.setcolortable!(AG.getband(dataset, 4), ct) + return AG.setcolortable!(AG.getband(dataset, 4), ct) end @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} @@ -101,17 +151,16 @@ import ColorTypes AG.setcolortable!(AG.getband(dataset, 1), ct) AG.setcolortable!(AG.getband(dataset, 2), ct) AG.setcolortable!(AG.getband(dataset, 3), ct) - AG.setcolortable!(AG.getband(dataset, 4), ct) + return AG.setcolortable!(AG.getband(dataset, 4), ct) end @test eltype(AG.imread(dataset)) == ColorTypes.Gray{ImageCore.N0f8} AG.createcolortable(AG.GPI_CMYK) do ct # CMYK not supported yet AG.setcolortable!(AG.getband(dataset, 1), ct) AG.setcolortable!(AG.getband(dataset, 2), ct) - AG.setcolortable!(AG.getband(dataset, 3), ct) + return AG.setcolortable!(AG.getband(dataset, 3), ct) end @test_throws ErrorException AG.imread(dataset, 1:3) end end - end diff --git a/test/test_iterators.jl b/test/test_iterators.jl index 3e11e715..96f812fd 100644 --- a/test/test_iterators.jl +++ b/test/test_iterators.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_iterators.jl" begin - @testset "Iterator interface Window Iterator" begin ds = AG.readraster("ospy/data4/aster.img") band = AG.getband(ds, 1) @@ -14,5 +13,4 @@ const AG = ArchGDAL; @test size(window) == (79, 89) @test length(window) == 7031 end - end diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index f5e936fe..3913bb71 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -4,7 +4,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_ospy_examples.jl" begin - """ function to copy fields (not the data) from one layer to another parameters: @@ -13,7 +12,7 @@ const AG = ArchGDAL; """ function copyfields(fromlayer, tolayer) featuredefn = AG.layerdefn(fromlayer) - for i = 0:(AG.nfield(featuredefn)-1) + for i in 0:(AG.nfield(featuredefn)-1) fd = AG.getfielddefn(featuredefn, i) if AG.gettype(fd) == OFTReal # to deal with errors like @@ -38,7 +37,7 @@ const AG = ArchGDAL; toFeature: feature object that the data is to be copied into """ function copyattributes(fromfeature, tofeature) - for i = 0:(AG.nfield(fromfeature)-1) + for i in 0:(AG.nfield(fromfeature)-1) if AG.isfieldset(fromfeature, i) try AG.setfield!(tofeature, i, AG.getfield(fromfeature, i)) @@ -90,15 +89,19 @@ const AG = ArchGDAL; @test id == i @test 4e5 <= x <= 5e5 @test 4.5e6 <= y <= 5e6 - @test cover in ("shrubs", "trees", "rocks", "grass", "bare", "water") + @test cover in + ("shrubs", "trees", "rocks", "grass", "bare", "water") end #reference: http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw1b.py # version 1 AG.create(AG.getdriver("MEMORY")) do output inlayer = AG.getlayer(input, 0) - outlayer = - AG.createlayer(name = "hw1b", dataset = output, geom = AG.wkbPoint) + outlayer = AG.createlayer( + name = "hw1b", + dataset = output, + geom = AG.wkbPoint, + ) inlayerdefn = AG.layerdefn(inlayer) AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 0)) AG.addfielddefn!(outlayer, AG.getfielddefn(inlayerdefn, 1)) @@ -110,7 +113,7 @@ const AG = ArchGDAL; AG.createfeature(outlayer) do outfeature AG.setgeom!(outfeature, AG.getgeom(infeature)) AG.setfield!(outfeature, 0, id) - AG.setfield!(outfeature, 1, cover) + return AG.setfield!(outfeature, 1, cover) end end end @@ -136,7 +139,7 @@ const AG = ArchGDAL; Field 0 (id): [OFTInteger], 2, 6, 9, 14, 19, 20, 22, 26, 34, 36, 41 Field 1 (cover): [OFTString], trees, trees, trees, trees, trees, trees, ... """ - AG.copy(results, name = "hw1b", dataset = output) + return AG.copy(results, name = "hw1b", dataset = output) end @test sprint(print, output) == """ GDAL Dataset (Driver: Memory/Memory) @@ -153,15 +156,18 @@ const AG = ArchGDAL; # http://www.gis.usu.edu/~chrisg/python/2009/lectures/ospy_hw2a.py open("ospy/data2/ut_counties.txt", "r") do file AG.create(AG.getdriver("MEMORY")) do output - layer = - AG.createlayer(name = "hw2a", dataset = output, geom = AG.wkbPolygon) + layer = AG.createlayer( + name = "hw2a", + dataset = output, + geom = AG.wkbPolygon, + ) @test sprint(print, layer) == """ Layer: hw2a Geometry 0 (): [wkbPolygon] """ AG.createfielddefn("name", AG.OFTString) do fielddefn AG.setwidth!(fielddefn, 30) - AG.addfielddefn!(layer, fielddefn) + return AG.addfielddefn!(layer, fielddefn) end @test sprint(print, layer) == """ Layer: hw2a @@ -183,7 +189,7 @@ const AG = ArchGDAL; ) end AG.addgeom!(poly, ring) - AG.setgeom!(feature, poly) + return AG.setgeom!(feature, poly) end end end @@ -273,7 +279,7 @@ const AG = ArchGDAL; yOffset = round(Int, (y - yOrigin) / pixelHeight) # create a string to print out @test AG.getfield(feature, id) == i - for j = 1:AG.nraster(ds) + for j in 1:AG.nraster(ds) data = AG.read(ds, j, xOffset, yOffset, 1, 1) results[i, j] = data[1, 1] end @@ -355,7 +361,7 @@ const AG = ArchGDAL; AG.rasterio!(inband3, buffer3, j, i, ncols, nrows) data2 = buffer2[1:nrows, 1:ncols] data3 = buffer3[1:nrows, 1:ncols] - for row = 1:nrows, col = 1:ncols + for row in 1:nrows, col in 1:ncols denominator = data2[row, col] + data3[row, col] if denominator > 0 numerator = data3[row, col] - data2[row, col] @@ -384,7 +390,7 @@ const AG = ArchGDAL; AG.setnodatavalue!(outband, -99) # georeference the image and set the projection AG.setgeotransform!(outDS, AG.getgeotransform(ds)) - AG.setproj!(outDS, AG.getproj(ds)) + return AG.setproj!(outDS, AG.getproj(ds)) # build pyramids # gdal.SetConfigOption('HFA_USE_RRD', 'YES') @@ -484,7 +490,7 @@ const AG = ArchGDAL; # set the geotransform and projection on the output geotransform = [minX, pixelWidth1, 0, maxY, 0, pixelHeight1] AG.setgeotransform!(dsout, geotransform) - AG.setproj!(dsout, AG.getproj(ds1)) + return AG.setproj!(dsout, AG.getproj(ds1)) # build pyramids for the output # gdal.SetConfigOption('HFA_USE_RRD', 'YES') @@ -497,5 +503,4 @@ const AG = ArchGDAL; end end end - end diff --git a/test/test_rasterattrtable.jl b/test/test_rasterattrtable.jl index bf5f19c9..38629791 100644 --- a/test/test_rasterattrtable.jl +++ b/test/test_rasterattrtable.jl @@ -4,7 +4,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_rasterattrtable.jl" begin - @testset "Testing Raster Attribute Tables" begin AG.createRAT() do rat @test AG.ncolumn(rat) == 0 @@ -26,12 +25,30 @@ const AG = ArchGDAL; AG.setrowcount!(rat, 5) @test AG.nrow(rat) == 5 - @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Cint}(undef, 5)) == - fill(0, 5) - @test AG.attributeio!(rat, AG.GF_Read, 0, 0, 5, Array{Float64}(undef, 5)) == - fill(0, 5) - @test AG.attributeio!(rat, AG.GF_Read, 1, 0, 5, Array{Float64}(undef, 5)) == - fill(0, 5) + @test AG.attributeio!( + rat, + AG.GF_Read, + 0, + 0, + 5, + Array{Cint}(undef, 5), + ) == fill(0, 5) + @test AG.attributeio!( + rat, + AG.GF_Read, + 0, + 0, + 5, + Array{Float64}(undef, 5), + ) == fill(0, 5) + @test AG.attributeio!( + rat, + AG.GF_Read, + 1, + 0, + 5, + Array{Float64}(undef, 5), + ) == fill(0, 5) @test AG.asstring(rat, 2, 0) == "0" @test AG.asint(rat, 2, 0) == 0 @@ -98,9 +115,9 @@ const AG = ArchGDAL; @test sprint(print, ct2) == "NULL ColorTable" end AG.createRAT(ct) do rat - @test sprint(print, AG.toColorTable(rat, 0)) == "ColorTable[GPI_RGB]" + @test sprint(print, AG.toColorTable(rat, 0)) == + "ColorTable[GPI_RGB]" end end end - end diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 963f7644..059ba621 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -4,7 +4,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_rasterband.jl" begin - @testset "Test methods for rasterband" begin AG.read("data/utmsmall.tif") do dataset ds_result = """ @@ -92,8 +91,12 @@ const AG = ArchGDAL; blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: """ @test AG.maskflags(destband) == 1 - @test AG.maskflaginfo(rb) == - (all_valid = true, per_dataset = false, alpha = false, nodata = false) + @test AG.maskflaginfo(rb) == ( + all_valid = true, + per_dataset = false, + alpha = false, + nodata = false, + ) AG.createmaskband!(destband, 3) AG.getmaskband(destband) do maskband @test sprint(print, maskband) == """ @@ -102,14 +105,18 @@ const AG = ArchGDAL; overviews: """ end @test AG.maskflags(destband) == 3 - @test AG.maskflaginfo(destband) == - (all_valid = true, per_dataset = true, alpha = false, nodata = false) + @test AG.maskflaginfo(destband) == ( + all_valid = true, + per_dataset = true, + alpha = false, + nodata = false, + ) AG.fillraster!(destband, 3) AG.setcategorynames!(destband, ["foo", "bar"]) @test AG.getcategorynames(destband) == ["foo", "bar"] AG.getoverview(destband, 0) do overview - AG.regenerateoverviews!( + return AG.regenerateoverviews!( destband, [overview, AG.getoverview(destband, 2)], ) @@ -127,7 +134,7 @@ const AG = ArchGDAL; end AG.createcolortable(AG.GPI_RGB) do ct @test ct.ptr != GDAL.GDALColorTableH(C_NULL) - AG.setcolortable!(destband, ct) + return AG.setcolortable!(destband, ct) end AG.clearcolortable!(destband) AG.getcolortable(destband) do ct @@ -136,5 +143,4 @@ const AG = ArchGDAL; end end end - end diff --git a/test/test_rasterio.jl b/test/test_rasterio.jl index d1d658aa..bb37196f 100644 --- a/test/test_rasterio.jl +++ b/test/test_rasterio.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_rasterio.jl" begin - AG.read("ospy/data4/aster.img") do ds @testset "version 1" begin band = AG.getband(ds, 1) @@ -85,7 +84,8 @@ const AG = ArchGDAL; @testset "version 6" begin band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) + buffer = + Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) AG.rasterio!(ds, buffer, [1]) count = sum(buffer .> 0) total = sum(buffer) @@ -95,7 +95,8 @@ const AG = ArchGDAL; @testset "version 7" begin band = AG.getband(ds, 1) - buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) + buffer = + Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) AG.read!(band, buffer) count = sum(buffer .> 0) total = sum(buffer) @@ -105,7 +106,8 @@ const AG = ArchGDAL; @testset "version 8" begin band = AG.getband(ds, 1) - buffer = Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) + buffer = + Matrix{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds)) AG.read!(ds, buffer, 1) count = sum(buffer .> 0) total = sum(buffer) @@ -115,7 +117,8 @@ const AG = ArchGDAL; @testset "version 9" begin band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) + buffer = + Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 1) AG.read!(ds, buffer, [1]) count = sum(buffer .> 0) total = sum(buffer) @@ -125,7 +128,8 @@ const AG = ArchGDAL; @testset "version 10" begin band = AG.getband(ds, 1) - buffer = Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 3) + buffer = + Array{AG.pixeltype(band)}(undef, AG.width(ds), AG.height(ds), 3) AG.read!(ds, buffer) count = sum(buffer[:, :, 1] .> 0) total = sum(buffer[:, :, 1]) @@ -175,7 +179,12 @@ const AG = ArchGDAL; @testset "writeblock!(rb::RasterBand, xoffset, yoffset, buffer)" begin # We write everything to typemax(UInt8) for ((i, j), (nrows, ncols)) in AG.blocks(bandout) - AG.writeblock!(bandout, j, i, fill(typemax(UInt8), ncols, nrows)) + AG.writeblock!( + bandout, + j, + i, + fill(typemax(UInt8), ncols, nrows), + ) end buffer = AG.read(bandout) nnzero = sum(buffer .> 0) @@ -193,7 +202,11 @@ const AG = ArchGDAL; # We write everything to typemax(UInt8) AG.write!( bandout, - fill(typemax(UInt8), AG.height(bandout), AG.width(bandout)), + fill( + typemax(UInt8), + AG.height(bandout), + AG.width(bandout), + ), ) buffer = AG.read(bandout) nnzero = sum(buffer .> 0) @@ -201,7 +214,10 @@ const AG = ArchGDAL; @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) # Now we write everything to 0 - AG.write!(bandout, fill(0x00, AG.height(bandout), AG.width(bandout))) + AG.write!( + bandout, + fill(0x00, AG.height(bandout), AG.width(bandout)), + ) @test sum(AG.read(bandout) .> 0) == 0 end @@ -209,7 +225,11 @@ const AG = ArchGDAL; # We write everything to typemax(UInt8) AG.write!( dsout, - fill(typemax(UInt8), AG.height(bandout), AG.width(bandout)), + fill( + typemax(UInt8), + AG.height(bandout), + AG.width(bandout), + ), 1, ) buffer = AG.read(bandout) @@ -218,7 +238,11 @@ const AG = ArchGDAL; @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) # Now we write everything to 0 - AG.write!(dsout, fill(0x00, AG.height(bandout), AG.width(bandout)), 1) + AG.write!( + dsout, + fill(0x00, AG.height(bandout), AG.width(bandout)), + 1, + ) @test sum(AG.read(bandout) .> 0) == 0 end @@ -226,7 +250,12 @@ const AG = ArchGDAL; # We write everything to typemax(UInt8) AG.write!( dsout, - fill(typemax(UInt8), AG.height(dsout), AG.width(dsout), 2), + fill( + typemax(UInt8), + AG.height(dsout), + AG.width(dsout), + 2, + ), 1:2, ) buffer = AG.read(dsout) @@ -235,12 +264,14 @@ const AG = ArchGDAL; @test sum(buffer) / nnzero ≈ Float64(typemax(UInt8)) # Now we write everything to 0 - AG.write!(dsout, fill(0x00, AG.height(dsout), AG.width(dsout), 2), 1:2) + AG.write!( + dsout, + fill(0x00, AG.height(dsout), AG.width(dsout), 2), + 1:2, + ) @test sum(AG.read(dsout) .> 0) == 0 end end end - end - end diff --git a/test/test_spatialref.jl b/test/test_spatialref.jl index 28361dbb..e8fec066 100644 --- a/test/test_spatialref.jl +++ b/test/test_spatialref.jl @@ -5,7 +5,6 @@ import GeoFormatTypes; const GFT = GeoFormatTypes; @testset "test_spatialref.jl" begin - @testset "Test Formats for Spatial Reference Systems" begin proj4326 = "+proj=longlat +datum=WGS84 +no_defs" proj26912 = "+proj=utm +zone=12 +datum=NAD83 +units=m +no_defs" @@ -233,26 +232,34 @@ const GFT = GeoFormatTypes; end @testset "generic importCRS" begin - @test AG.toWKT(AG.importCRS(GFT.WellKnownText(GFT.CRS(), wkt4326))) == - AG.toWKT(AG.importWKT(wkt4326)) - @test AG.toWKT(AG.importCRS(GFT.ESRIWellKnownText(GFT.CRS(), wkt4326))) == - AG.toWKT(AG.importESRI(wkt4326)) + @test AG.toWKT( + AG.importCRS(GFT.WellKnownText(GFT.CRS(), wkt4326)), + ) == AG.toWKT(AG.importWKT(wkt4326)) + @test AG.toWKT( + AG.importCRS(GFT.ESRIWellKnownText(GFT.CRS(), wkt4326)), + ) == AG.toWKT(AG.importESRI(wkt4326)) @test AG.toWKT(AG.importCRS(GFT.ProjString(proj4326))) == AG.toWKT(AG.importPROJ4(proj4326)) - @test AG.toWKT(AG.importCRS(GFT.EPSG(4326))) == AG.toWKT(AG.importEPSG(4326)) + @test AG.toWKT(AG.importCRS(GFT.EPSG(4326))) == + AG.toWKT(AG.importEPSG(4326)) @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :trad)) == AG.toWKT(AG.importEPSG(4326)) @test AG.toWKT(AG.importCRS(GFT.EPSG(4326), order = :compliant)) == AG.toWKT(AG.importEPSG(4326)) @test AG.toWKT(AG.importCRS(GFT.GML(xml4326))) == AG.toWKT(AG.importXML(xml4326)) - @test AG.toWKT(AG.importCRS(GFT.KML(""))) == AG.toWKT(AG.importEPSG(4326)) - @test_throws ArgumentError AG.importCRS(GFT.EPSG(4326), order = :unknown) + @test AG.toWKT(AG.importCRS(GFT.KML(""))) == + AG.toWKT(AG.importEPSG(4326)) + @test_throws ArgumentError AG.importCRS( + GFT.EPSG(4326), + order = :unknown, + ) end end @testset "Cloning NULL SRS" begin - @test sprint(print, AG.clone(AG.ISpatialRef())) == "NULL Spatial Reference System" + @test sprint(print, AG.clone(AG.ISpatialRef())) == + "NULL Spatial Reference System" AG.clone(AG.ISpatialRef()) do spatialref @test sprint(print, spatialref) == "NULL Spatial Reference System" end @@ -274,5 +281,4 @@ const GFT = GeoFormatTypes; @test AG.getattrvalue(spatialref, "AUTHORITY", 1) == "4326" end end - end diff --git a/test/test_styletable.jl b/test/test_styletable.jl index 6b2df874..17f0667c 100644 --- a/test/test_styletable.jl +++ b/test/test_styletable.jl @@ -3,7 +3,6 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_styletable.jl" begin - @testset "Testing StyleTable Methods" begin AG.createstylemanager() do sm @test AG.initialize!(sm) == true @@ -59,7 +58,7 @@ const AG = ArchGDAL; @test AG.nextstyle(stbl) == "style2" AG.resetreading!(stbl) @test AG.nextstyle(stbl) == "style1" - AG.savestyletable(stbl, "tmp/styletable.txt") + return AG.savestyletable(stbl, "tmp/styletable.txt") end AG.createstyletable() do stbl AG.loadstyletable!(stbl, "tmp/styletable.txt") @@ -70,8 +69,7 @@ const AG = ArchGDAL; AG.resetreading!(stbl) @test AG.nextstyle(stbl) == "style1" end - rm("tmp/styletable.txt") + return rm("tmp/styletable.txt") end end - end diff --git a/test/test_tables.jl b/test/test_tables.jl index 685c4fa4..c678ddb0 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -4,7 +4,6 @@ const AG = ArchGDAL; using Tables @testset "test_tables.jl" begin - @testset "Tables Support" begin dataset = AG.read(joinpath(@__DIR__, "data/point.geojson")) dataset1 = AG.read( @@ -64,8 +63,7 @@ using Tables @test Tables.getcolumn(features[1], 1) == "5.1" @test Tables.getcolumn(features[1], 2) == "1.0" @test Tables.getcolumn(features[1], 3) == "Mumbai" - @test AG.toWKT(Tables.getcolumn(features[1], 4)) == - "POINT (30 10)" + @test AG.toWKT(Tables.getcolumn(features[1], 4)) == "POINT (30 10)" @test AG.toWKT(Tables.getcolumn(features[1], 5)) == "LINESTRING (30 10,10 30,40 40)" @test Tables.getcolumn(features[1], :id) == "5.1" @@ -104,5 +102,4 @@ using Tables @test collect(field_names) == [:id, :zoom, :location] end end - end diff --git a/test/test_types.jl b/test/test_types.jl index 186c09a9..a4680607 100644 --- a/test/test_types.jl +++ b/test/test_types.jl @@ -4,7 +4,6 @@ const AG = ArchGDAL; import ImageCore @testset "test_types.jl" begin - @testset "Testing GDAL Type Methods" begin @testset "GDAL Open Flags" begin @test AG.OF_READONLY | 0x04 == 0x04 @@ -23,7 +22,10 @@ import ImageCore @test Base.convert(AG.GDALDataType, UInt8) == AG.GDT_Byte @test_throws ErrorException Base.convert(AG.GDALDataType, Int64) @test_throws ErrorException Base.convert(DataType, AG.GDT_TypeCount) - @test_throws MethodError Base.convert(ImageCore.Normed, AG.GDT_Float32) + @test_throws MethodError Base.convert( + ImageCore.Normed, + AG.GDT_Float32, + ) end @testset "GDAL Colors and Palettes" begin @@ -63,7 +65,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiPoint) == AG.wkbMultiPoint @test AG.basetype(AG.wkbMultiLineString) == AG.wkbMultiLineString @test AG.basetype(AG.wkbMultiPolygon) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollection) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbGeometryCollection) == + AG.wkbGeometryCollection @test AG.basetype(AG.wkbCircularString) == AG.wkbCircularString @test AG.basetype(AG.wkbCompoundCurve) == AG.wkbCompoundCurve @test AG.basetype(AG.wkbCurvePolygon) == AG.wkbCurvePolygon @@ -71,7 +74,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiSurface) == AG.wkbMultiSurface @test AG.basetype(AG.wkbCurve) == AG.wkbCurve @test AG.basetype(AG.wkbSurface) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurface) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbPolyhedralSurface) == + AG.wkbPolyhedralSurface @test AG.basetype(AG.wkbTIN) == AG.wkbTIN @test AG.basetype(AG.wkbTriangle) == AG.wkbTriangle @test AG.basetype(AG.wkbNone) == AG.wkbNone @@ -83,7 +87,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiSurfaceZ) == AG.wkbMultiSurface @test AG.basetype(AG.wkbCurveZ) == AG.wkbCurve @test AG.basetype(AG.wkbSurfaceZ) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurfaceZ) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceZ) == + AG.wkbPolyhedralSurface @test AG.basetype(AG.wkbTINZ) == AG.wkbTIN @test AG.basetype(AG.wkbTriangleZ) == AG.wkbTriangle @test AG.basetype(AG.wkbPointM) == AG.wkbPoint @@ -92,7 +97,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiPointM) == AG.wkbMultiPoint @test AG.basetype(AG.wkbMultiLineStringM) == AG.wkbMultiLineString @test AG.basetype(AG.wkbMultiPolygonM) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollectionM) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbGeometryCollectionM) == + AG.wkbGeometryCollection @test AG.basetype(AG.wkbCircularStringM) == AG.wkbCircularString @test AG.basetype(AG.wkbCompoundCurveM) == AG.wkbCompoundCurve @test AG.basetype(AG.wkbCurvePolygonM) == AG.wkbCurvePolygon @@ -100,7 +106,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiSurfaceM) == AG.wkbMultiSurface @test AG.basetype(AG.wkbCurveM) == AG.wkbCurve @test AG.basetype(AG.wkbSurfaceM) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurfaceM) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceM) == + AG.wkbPolyhedralSurface @test AG.basetype(AG.wkbTINM) == AG.wkbTIN @test AG.basetype(AG.wkbTriangleM) == AG.wkbTriangle @test AG.basetype(AG.wkbPointZM) == AG.wkbPoint @@ -109,7 +116,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiPointZM) == AG.wkbMultiPoint @test AG.basetype(AG.wkbMultiLineStringZM) == AG.wkbMultiLineString @test AG.basetype(AG.wkbMultiPolygonZM) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollectionZM) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbGeometryCollectionZM) == + AG.wkbGeometryCollection @test AG.basetype(AG.wkbCircularStringZM) == AG.wkbCircularString @test AG.basetype(AG.wkbCompoundCurveZM) == AG.wkbCompoundCurve @test AG.basetype(AG.wkbCurvePolygonZM) == AG.wkbCurvePolygon @@ -117,7 +125,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiSurfaceZM) == AG.wkbMultiSurface @test AG.basetype(AG.wkbCurveZM) == AG.wkbCurve @test AG.basetype(AG.wkbSurfaceZM) == AG.wkbSurface - @test AG.basetype(AG.wkbPolyhedralSurfaceZM) == AG.wkbPolyhedralSurface + @test AG.basetype(AG.wkbPolyhedralSurfaceZM) == + AG.wkbPolyhedralSurface @test AG.basetype(AG.wkbTINZM) == AG.wkbTIN @test AG.basetype(AG.wkbTriangleZM) == AG.wkbTriangle @test AG.basetype(AG.wkbPoint25D) == AG.wkbPoint @@ -126,8 +135,8 @@ import ImageCore @test AG.basetype(AG.wkbMultiPoint25D) == AG.wkbMultiPoint @test AG.basetype(AG.wkbMultiLineString25D) == AG.wkbMultiLineString @test AG.basetype(AG.wkbMultiPolygon25D) == AG.wkbMultiPolygon - @test AG.basetype(AG.wkbGeometryCollection25D) == AG.wkbGeometryCollection + @test AG.basetype(AG.wkbGeometryCollection25D) == + AG.wkbGeometryCollection end end - end diff --git a/test/test_utils.jl b/test/test_utils.jl index 3569becb..61456715 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -3,12 +3,10 @@ import ArchGDAL; const AG = ArchGDAL; @testset "test_utils.jl" begin - @testset "metadataitem" begin driver = AG.getdriver("DERIVED") @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "" driver = AG.getdriver("GTiff") @test AG.metadataitem(driver, "DMD_EXTENSIONS") == "tif tiff" end - end From 1234d6b5a7abb1a422b2ff5f66a31d6798ca717f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 22 May 2021 10:37:57 -0700 Subject: [PATCH 126/169] remove obsolete code --- src/raster/images.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index 4cb9d52e..cd991e54 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -191,10 +191,6 @@ function imread(dataset::AbstractDataset, i::Integer) return imread(getband(dataset, i)) end -# function imread(dataset::AbstractDataset, indices::NTuple{1,<:Integer}) -# return imread(dataset, indices[1]) -# end - function _paletteindices(dataset::AbstractDataset, indices) gci = unique( GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices], From fb25d5a910700ef2faebbefc7790c3cb97dd51db Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 22 May 2021 11:28:45 -0700 Subject: [PATCH 127/169] Fix the description for updating compatibility --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e34c732e..3d718d24 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,12 @@ shell> cd /Users/yeesian/.julia/dev/ArchGDAL [68eda718] + GeoFormatTypes v0.3.0 [cf35fbd7] + GeoInterface v0.5.5 [bd369af6] + Tables v1.4.2 -```4. Add a compat entry into Project.toml so that julia can resolve the versions -``` Open the Project.toml file in a texteditor and add in the [compat] section the line: - CEnum = "0.4" +``` + +4. Update the `[compat]` section of `Project.toml` so that julia can resolve the versions, e.g. + +``` +[compat] +... +CEnum = "0.4" +``` From bf6be50008dabb127efc03bd7cf3eec33b4bcfba Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 16:56:45 -0700 Subject: [PATCH 128/169] Removing the forecast checker from PRs It'll be easier to let PR authors not worry about the format for multi-commit PRs, and wait for text editor integration instead. In the meantime, there's a format_pr.yml that can autoformat the codebase --- .github/workflows/format_check.yml | 31 ------------------------------ README.md | 4 +--- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 .github/workflows/format_check.yml diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml deleted file mode 100644 index e4fd63d6..00000000 --- a/.github/workflows/format_check.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: format-check -on: - push: - branches: - - master - - release-* - pull_request: - types: [opened, synchronize, reopened] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: julia-actions/setup-julia@latest - with: - version: '1' - - uses: actions/checkout@v1 - - name: Format check - shell: julia --color=yes {0} - run: | - using Pkg - # If you update the version, also update the style guide docs. - Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.10")) - using JuliaFormatter - format("src", verbose=true) - out = String(read(Cmd(`git diff`))) - if isempty(out) - exit(0) - end - @error "Some files have not been formatted !!!" - write(stdout, out) - exit(1) diff --git a/README.md b/README.md index 3d718d24..465fdca8 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,13 @@ This package will not be possible without https://julialang.org/, https://github ArchGDAL.jl uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) as an autoformatting tool, and uses the options in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml). -To format code, `cd` to the ArchGDAL.jl directory, then run: +If you wish to format code, `cd` to the ArchGDAL.jl directory, then run: ```julia ] add JuliaFormatter@0.13.10 using JuliaFormatter format("src") ``` -A continuous integration check verifies that all PRs made to ArchGDAL.jl have passed the formatter. - ### Dependencies To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1.6/environments/): From ac50e17d930a19142b9d0b9ba79e2e5b13a936ce Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:00:18 -0700 Subject: [PATCH 129/169] Re-enable test for gdal warp --- test/test_gdalutilities.jl | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index b8019881..06d4583f 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -226,19 +226,15 @@ end 0 0 0 0 0] end - # cannot reproject file on AppVeyor yet - # GDALError (CE_Failure, code 4): - # Unable to open EPSG support file gcs.csv. Try setting the - # GDAL_DATA environment variable to point to the directory - # containing EPSG csv files. - # @testset "GDAL Warp" begin - # AG.gdalwarp([ds_small], ["-of","MEM","-t_srs","EPSG:4326"]) do ds_warped - # @test AG.width(ds_small) == 100 - # @test AG.height(ds_small) == 100 - # @test AG.width(ds_warped) == 109 - # @test AG.height(ds_warped) == 91 - # end - # end + @testset "GDAL Warp" begin + AG.gdalwarp([ds_small], ["-of","MEM","-t_srs","EPSG:4326"]) do ds_warped + @test AG.width(ds_small) == 100 + @test AG.height(ds_small) == 100 + @test AG.width(ds_warped) == 109 + @test AG.height(ds_warped) == 91 + end + end + @testset "GDAL Warp" begin ds_warped = AG.unsafe_gdalwarp([ds_small], ["-of","MEM"]) @test AG.width(ds_small) == 100 From b98940ba83fe03e48908162f246391f242ac4c4b Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:19:51 -0700 Subject: [PATCH 130/169] Use JuliaFormatter --- test/test_gdalutilities.jl | 134 ++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 47 deletions(-) diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index 06d4583f..f46f9da8 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -1,12 +1,14 @@ -using ArchGDAL, GDAL -AG = ArchGDAL +import ArchGDAL, GDAL; +const AG = ArchGDAL using Test @testset "test_gdalutilities.jl" begin - AG.read("data/utmsmall.tif") do ds_small @testset "GDAL Error" begin - @test_throws GDAL.GDALError AG.gdalinfo(ds_small, ["-novalidoption"]) + @test_throws GDAL.GDALError AG.gdalinfo( + ds_small, + ["-novalidoption"], + ) @test_throws GDAL.GDALError AG.unsafe_gdaltranslate( ds_small, ["-novalidoption"], @@ -24,7 +26,10 @@ using Test ds_small, ["-novalidoption"], ) - @test_throws GDAL.GDALError AG.unsafe_gdalwarp([ds_small], ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdalwarp( + [ds_small], + ["-novalidoption"], + ) end @testset "GDAL Info" begin @@ -86,7 +91,10 @@ using Test end @testset "GDAL Near Black" begin - AG.gdalnearblack(ds_tiny, ["-of", "GTiff", "-color", "0"]) do ds_nearblack + AG.gdalnearblack( + ds_tiny, + ["-of", "GTiff", "-color", "0"], + ) do ds_nearblack @test AG.read(ds_nearblack, 1) == [ 0 0 0 0 0 0 0 0 0 0 @@ -99,7 +107,10 @@ using Test end @testset "GDAL Warp" begin - AG.gdalwarp([ds_small], ["-of", "MEM", "-t_srs", "EPSG:4326"]) do ds_warped + AG.gdalwarp( + [ds_small], + ["-of", "MEM", "-t_srs", "EPSG:4326"], + ) do ds_warped @test AG.width(ds_small) == 100 @test AG.height(ds_small) == 100 @test AG.width(ds_warped) == 109 @@ -136,7 +147,8 @@ using Test "0.1", ], ) do ds_grid - @test AG.getgeotransform(ds_grid) ≈ [100.0, 0.1, 0.0, 0.0, 0.0, 0.01] + @test AG.getgeotransform(ds_grid) ≈ + [100.0, 0.1, 0.0, 0.0, 0.0, 0.01] end end @@ -151,12 +163,11 @@ using Test end @testset "GDAL Vector Translate" begin - AG.gdalvectortranslate( + AG.unsafe_gdalvectortranslate( [ds_point], ["-f", "CSV", "-lco", "GEOMETRY=AS_XY"], dest = "data/point.csv", - ) do ds_csv - end + ) @test replace(read("data/point.csv", String), "\r" => "") == """ X,Y,FID,pointname 100,0,2,point-a @@ -167,18 +178,33 @@ using Test rm("data/point.csv") end end - end @testset "Interactive data/utmsmall.tif" begin ds_small = AG.read("data/utmsmall.tif") @testset "GDAL Error" begin @test_throws GDAL.GDALError AG.gdalinfo(ds_small, ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdaltranslate(ds_small, ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdalbuildvrt([ds_small], ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdaldem(ds_small, "hillshade", ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdalnearblack(ds_small, ["-novalidoption"]) - @test_throws GDAL.GDALError AG.unsafe_gdalwarp([ds_small], ["-novalidoption"]) + @test_throws GDAL.GDALError AG.unsafe_gdaltranslate( + ds_small, + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdalbuildvrt( + [ds_small], + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdaldem( + ds_small, + "hillshade", + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdalnearblack( + ds_small, + ["-novalidoption"], + ) + @test_throws GDAL.GDALError AG.unsafe_gdalwarp( + [ds_small], + ["-novalidoption"], + ) end @testset "GDAL Info" begin @@ -188,60 +214,74 @@ end @test occursin("Driver: GTiff/GeoTIFF", info_default) end - ds_tiny = AG.unsafe_gdaltranslate(ds_small, # resample to a 5×5 ascii grid - ["-of","AAIGrid","-r","cubic","-tr","1200","1200"]) + ds_tiny = AG.unsafe_gdaltranslate( + ds_small, # resample to a 5×5 ascii grid + ["-of", "AAIGrid", "-r", "cubic", "-tr", "1200", "1200"], + ) @test typeof(ds_tiny) == AG.Dataset @testset "GDAL Translate" begin - @test AG.read(ds_tiny, 1) == [128 171 127 93 83; - 126 164 148 114 101; - 161 175 177 164 140; - 185 206 205 172 128; - 193 205 209 181 122] + @test AG.read(ds_tiny, 1) == [ + 128 171 127 93 83 + 126 164 148 114 101 + 161 175 177 164 140 + 185 206 205 172 128 + 193 205 209 181 122 + ] end @testset "GDAL Build VRT" begin ds_vrt = AG.unsafe_gdalbuildvrt([ds_tiny]) - @test AG.read(ds_vrt, 1) == [128 171 127 93 83; - 126 164 148 114 101; - 161 175 177 164 140; - 185 206 205 172 128; - 193 205 209 181 122] + @test AG.read(ds_vrt, 1) == [ + 128 171 127 93 83 + 126 164 148 114 101 + 161 175 177 164 140 + 185 206 205 172 128 + 193 205 209 181 122 + ] end @testset "GDAL DEM Processing" begin - ds_dempr = AG.unsafe_gdaldem(ds_tiny, "hillshade", ["-of","AAIGrid"]) - @test AG.read(ds_dempr, 1) == [ 0 0 0 0 0; - 0 183 180 181 0; - 0 184 182 181 0; - 0 183 181 177 0; - 0 0 0 0 0] + ds_dempr = AG.unsafe_gdaldem(ds_tiny, "hillshade", ["-of", "AAIGrid"]) + @test AG.read(ds_dempr, 1) == [ + 0 0 0 0 0 + 0 183 180 181 0 + 0 184 182 181 0 + 0 183 181 177 0 + 0 0 0 0 0 + ] end @testset "GDAL Near Black" begin - ds_nearblack = AG.unsafe_gdalnearblack(ds_tiny, ["-of","GTiff","-color","0"]) - @test AG.read(ds_nearblack, 1) == [ 0 0 0 0 0; - 0 0 0 0 0; - 0 0 177 0 0; - 0 0 0 0 0; - 0 0 0 0 0] + ds_nearblack = + AG.unsafe_gdalnearblack(ds_tiny, ["-of", "GTiff", "-color", "0"]) + @test AG.read(ds_nearblack, 1) == [ + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 177 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + ] end @testset "GDAL Warp" begin - AG.gdalwarp([ds_small], ["-of","MEM","-t_srs","EPSG:4326"]) do ds_warped + AG.gdalwarp( + [ds_small], + ["-of", "MEM", "-t_srs", "EPSG:4326"], + ) do ds_warped @test AG.width(ds_small) == 100 @test AG.height(ds_small) == 100 @test AG.width(ds_warped) == 109 @test AG.height(ds_warped) == 91 end end - - @testset "GDAL Warp" begin - ds_warped = AG.unsafe_gdalwarp([ds_small], ["-of","MEM"]) + + @testset "GDAL Warp #2" begin + ds_warped = AG.unsafe_gdalwarp([ds_small], ["-of", "MEM"]) @test AG.width(ds_small) == 100 @test AG.height(ds_small) == 100 @test AG.shortname(AG.getdriver(ds_small)) == "GTiff" @test AG.width(ds_warped) == 100 @test AG.height(ds_warped) == 100 @test AG.shortname(AG.getdriver(ds_warped)) == "MEM" - end -end + end +end From 2a31683164a9ec97bbb061ce4e26a45236cc8a57 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:22:41 -0700 Subject: [PATCH 131/169] Use links instead of URLs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 465fdca8..2b175b8b 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ pkg> test ArchGDAL ### Community -This package will not be possible without https://julialang.org/, https://github.com/OSGeo/gdal and https://github.com/JuliaGeo/GDAL.jl. They are maintained by https://julialang.org/community/, https://www.osgeo.org/ and https://juliageo.org/. In case of any contention for support and involvement, we encourage participation and contributions to those projects and communities over this package. +This package will not be possible without [JuliaLang](https://julialang.org/), [GDAL](https://github.com/OSGeo/gdal) and [GDAL.jl](https://github.com/JuliaGeo/GDAL.jl). They are maintained by https://julialang.org/community/, https://www.osgeo.org/ and https://juliageo.org/ respectively. In case of any contention for support and involvement, we encourage participation and contributions to those projects and communities over this package. ### Style Guide From 90b864632848aeb0cb3942be38ecf163c2e2bc90 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:25:57 -0700 Subject: [PATCH 132/169] Use `=== nothing` instead of isnothing() for performance See https://github.com/JuliaLang/julia/pull/36444 for context. --- src/utils.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index 526b3a30..9a3822f9 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -138,7 +138,9 @@ function metadataitem( domain::AbstractString = "", )::String item = GDAL.gdalgetmetadataitem(obj.ptr, name, domain) - return isnothing(item) ? "" : item + # Use `=== nothing` instead of isnothing() for performance. + # See https://github.com/JuliaLang/julia/pull/36444 for context. + return item === nothing ? "" : item end """ From 4f7058c0407804e97b38378ed38a0a5978aaf067 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:26:24 -0700 Subject: [PATCH 133/169] Future-proof the url to use the latest 1.* version. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b175b8b..c49bdd1d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ format("src") ``` ### Dependencies -To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1.6/environments/): +To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1/environments/): 1. Navigate to the directory corresponding to the package: From 52ed3917aaf223a71b166bac5a99c386299ab219 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:26:52 -0700 Subject: [PATCH 134/169] Use the project environment for the docs --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 3526e372..15e6dae3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@ The latest stable version of the documentation can be viewed at https://yeesian.com/ArchGDAL.jl/stable/. To build a local version of the documentation, navigate to this directory and run the following command: ```shell -$ julia make.jl +$ julia --project make.jl ``` It should create files in a subdirectory named `build/`. If it builds successfully, you should be able to preview the documentation in a browser by opening `build/index.html` in a browser. From e86beac5117657411ed42ff1f269003db0bd6f69 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:31:25 -0700 Subject: [PATCH 135/169] Format test cases that take up too much vertical whitespace --- test/test_cookbook_geometry.jl | 26 +------- test/test_gdal_tutorials.jl | 105 +-------------------------------- 2 files changed, 6 insertions(+), 125 deletions(-) diff --git a/test/test_cookbook_geometry.jl b/test/test_cookbook_geometry.jl index cdd7de49..1f62c9ee 100644 --- a/test/test_cookbook_geometry.jl +++ b/test/test_cookbook_geometry.jl @@ -655,29 +655,9 @@ const AG = ArchGDAL; end @testset "Create Geometry from WKB" begin - wkb = [ - 0x01, - 0x01, - 0x00, - 0x00, - 0x00, - 0x7b, - 0x14, - 0xae, - 0x47, - 0x45, - 0x78, - 0xfa, - 0x40, - 0xe1, - 0x7a, - 0x14, - 0x2e, - 0x21, - 0x01, - 0x27, - 0x41, - ] + #! format: off + wkb = [0x01, 0x01, 0x00, 0x00, 0x00, 0x7b, 0x14, 0xae, 0x47, 0x45, 0x78, 0xfa, 0x40, 0xe1, 0x7a, 0x14, 0x2e, 0x21, 0x01, 0x27, 0x41] + #! format: on x, y = 108420.33, 753808.59 # Method 1 diff --git a/test/test_gdal_tutorials.jl b/test/test_gdal_tutorials.jl index 16b62c4d..77be3fc4 100644 --- a/test/test_gdal_tutorials.jl +++ b/test/test_gdal_tutorials.jl @@ -31,108 +31,9 @@ const AG = ArchGDAL; # Reading Raster Data @test AG.width(band) == 100 data = map(Float32, AG.read(dataset, 1)) - @test data[:, 1] ≈ Float32[ - 107.0f0, - 123.0f0, - 132.0f0, - 115.0f0, - 132.0f0, - 132.0f0, - 140.0f0, - 132.0f0, - 132.0f0, - 132.0f0, - 107.0f0, - 132.0f0, - 107.0f0, - 132.0f0, - 132.0f0, - 107.0f0, - 123.0f0, - 115.0f0, - 156.0f0, - 148.0f0, - 107.0f0, - 132.0f0, - 107.0f0, - 115.0f0, - 99.0f0, - 123.0f0, - 99.0f0, - 74.0f0, - 115.0f0, - 82.0f0, - 115.0f0, - 115.0f0, - 107.0f0, - 123.0f0, - 123.0f0, - 99.0f0, - 123.0f0, - 123.0f0, - 115.0f0, - 115.0f0, - 107.0f0, - 90.0f0, - 99.0f0, - 107.0f0, - 107.0f0, - 99.0f0, - 123.0f0, - 107.0f0, - 140.0f0, - 123.0f0, - 123.0f0, - 115.0f0, - 99.0f0, - 132.0f0, - 123.0f0, - 115.0f0, - 115.0f0, - 123.0f0, - 132.0f0, - 115.0f0, - 123.0f0, - 132.0f0, - 214.0f0, - 156.0f0, - 165.0f0, - 148.0f0, - 115.0f0, - 148.0f0, - 156.0f0, - 148.0f0, - 140.0f0, - 165.0f0, - 156.0f0, - 197.0f0, - 156.0f0, - 197.0f0, - 140.0f0, - 173.0f0, - 156.0f0, - 165.0f0, - 148.0f0, - 156.0f0, - 206.0f0, - 214.0f0, - 181.0f0, - 206.0f0, - 173.0f0, - 222.0f0, - 206.0f0, - 255.0f0, - 214.0f0, - 173.0f0, - 214.0f0, - 255.0f0, - 214.0f0, - 247.0f0, - 255.0f0, - 230.0f0, - 206.0f0, - 197.0f0, - ] + #! format: off + @test data[:, 1] ≈ Float32[107.0f0, 123.0f0, 132.0f0, 115.0f0, 132.0f0, 132.0f0, 140.0f0, 132.0f0, 132.0f0, 132.0f0, 107.0f0, 132.0f0, 107.0f0, 132.0f0, 132.0f0, 107.0f0, 123.0f0, 115.0f0, 156.0f0, 148.0f0, 107.0f0, 132.0f0, 107.0f0, 115.0f0, 99.0f0, 123.0f0, 99.0f0, 74.0f0, 115.0f0, 82.0f0, 115.0f0, 115.0f0, 107.0f0, 123.0f0, 123.0f0, 99.0f0, 123.0f0, 123.0f0, 115.0f0, 115.0f0, 107.0f0, 90.0f0, 99.0f0, 107.0f0, 107.0f0, 99.0f0, 123.0f0, 107.0f0, 140.0f0, 123.0f0, 123.0f0, 115.0f0, 99.0f0, 132.0f0, 123.0f0, 115.0f0, 115.0f0, 123.0f0, 132.0f0, 115.0f0, 123.0f0, 132.0f0, 214.0f0, 156.0f0, 165.0f0, 148.0f0, 115.0f0, 148.0f0, 156.0f0, 148.0f0, 140.0f0, 165.0f0, 156.0f0, 197.0f0, 156.0f0, 197.0f0, 140.0f0, 173.0f0, 156.0f0, 165.0f0, 148.0f0, 156.0f0, 206.0f0, 214.0f0, 181.0f0, 206.0f0, 173.0f0, 222.0f0, 206.0f0, 255.0f0, 214.0f0, 173.0f0, 214.0f0, 255.0f0, 214.0f0, 247.0f0, 255.0f0, 230.0f0, 206.0f0, 197.0f0] + #! format: on @test AG.metadatadomainlist(dataset) == ["IMAGE_STRUCTURE", "", "DERIVED_SUBDATASETS"] From a665f3407930b8221269f8949c246db022c3a85c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 17:34:38 -0700 Subject: [PATCH 136/169] Bugfix to write out the file before reading it. --- test/test_gdalutilities.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index f46f9da8..c2fbc1db 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -163,11 +163,11 @@ using Test end @testset "GDAL Vector Translate" begin - AG.unsafe_gdalvectortranslate( + AG.destroy(AG.unsafe_gdalvectortranslate( [ds_point], ["-f", "CSV", "-lco", "GEOMETRY=AS_XY"], dest = "data/point.csv", - ) + )) @test replace(read("data/point.csv", String), "\r" => "") == """ X,Y,FID,pointname 100,0,2,point-a From dadfa12e10c6d0719c32e855cbb9415753e1b3a2 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 18:21:30 -0700 Subject: [PATCH 137/169] Remove unnecessary `Table{T<:AbstractFeatureLayer}` type. FeatureLayers now implement the table interface without having to go through a Table wrapper type. --- docs/src/tables.md | 30 ++++++++---------------------- src/tables.jl | 22 ++++------------------ test/test_tables.jl | 18 +++--------------- 3 files changed, 15 insertions(+), 55 deletions(-) diff --git a/docs/src/tables.md b/docs/src/tables.md index fd6e5668..2af31c39 100644 --- a/docs/src/tables.md +++ b/docs/src/tables.md @@ -5,39 +5,25 @@ using ArchGDAL using DataFrames ``` -ArchGDAL now brings in greater flexibilty in terms of raster data handling via the -[Tables.jl](https://github.com/JuliaData/Tables.jl) API, that aims to provide a fast and -responsive tabular interface to data. +ArchGDAL now brings in greater flexibilty in terms of vector data handling via the +[Tables.jl](https://github.com/JuliaData/Tables.jl) API. In general, tables are modelled based on feature layers and support multiple geometries per layer. Namely, the layer(s) of a dataset can be converted to DataFrame(s) to perform miscellaneous spatial operations. -In this section, we revisit the +Here is a quick example based on the [`data/point.geojson`](https://github.com/yeesian/ArchGDALDatasets/blob/307f8f0e584a39a050c042849004e6a2bd674f99/data/point.geojson) -dataset. +dataset: ```@example tables dataset = ArchGDAL.read("data/point.geojson") -``` - -Each layer can be represented as a separate Table. -```@example tables -layer = ArchGDAL.getlayer(dataset, 0) +DataFrame(ArchGDAL.getlayer(dataset, 0)) ``` -The [`ArchGDAL.Table`](@ref) method accepts an `ArchGDAL.FeatureLayer`. -```@example tables -table = ArchGDAL.Table(layer) -``` - -Finally layers can be converted to DataFrames to perform miscellaneous spatial operations. Here, we visit the +Here is an example with multiple geometries based on the [`data/multi_geom.csv`](https://github.com/yeesian/ArchGDALDatasets/blob/master/data/multi_geom.csv) -dataset. +dataset: ```@example tables dataset1 = ArchGDAL.read("data/multi_geom.csv", options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"]) -layer = ArchGDAL.getlayer(dataset1, 0) -table = ArchGDAL.Table(layer) -df = DataFrame(table) +DataFrame(ArchGDAL.getlayer(dataset1, 0)) ``` - -The Tables interface also supports multiple geometries per layer. diff --git a/src/tables.jl b/src/tables.jl index dc208746..e5635844 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -1,12 +1,3 @@ -""" -A tabular representation of a `FeatureLayer` - -Every row is a `Feature` consisting of Geometry and attributes. -""" -struct Table{T<:AbstractFeatureLayer} - layer::T -end - function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema geom_names, field_names, featuredefn, fielddefns = schema_names(layerdefn(layer)) @@ -21,11 +12,11 @@ function Tables.schema(layer::AbstractFeatureLayer)::Tables.Schema ) end -Tables.istable(::Type{<:Table})::Bool = true -Tables.rowaccess(::Type{<:Table})::Bool = true +Tables.istable(::Type{<:AbstractFeatureLayer})::Bool = true +Tables.rowaccess(::Type{<:AbstractFeatureLayer})::Bool = true -function Tables.rows(t::Table{T})::T where {T<:AbstractFeatureLayer} - return t.layer +function Tables.rows(layer::T)::T where {T<:AbstractFeatureLayer} + return layer end function Tables.getcolumn(row::Feature, i::Int) @@ -67,8 +58,3 @@ function schema_names(featuredefn::IFeatureDefnView) replace!(geom_names, Symbol("") => Symbol("geometry"), count = 1) return (geom_names, field_names, featuredefn, fielddefns) end - -function Base.show(io::IO, t::Table) - return println(io, "Table with $(nfeature(t.layer)) features") -end -Base.show(io::IO, ::MIME"text/plain", t::Table) = show(io, t) diff --git a/test/test_tables.jl b/test/test_tables.jl index c678ddb0..090bba01 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -26,15 +26,6 @@ using Tables layer = AG.getlayer(dataset, 0) layer1 = AG.getlayer(dataset1, 0) layer2 = AG.getlayer(dataset2, 0) - gt = AG.Table(layer) - gt1 = AG.Table(layer1) - gt2 = AG.Table(layer2) - - @testset "read layer to table" begin - @test sprint(print, gt) == "Table with 4 features\n" - @test sprint(print, gt1) == "Table with 2 features\n" - @test sprint(print, gt2) == "Table with 9 features\n" - end @testset "Tables methods" begin @test Tables.schema(layer1) == Tables.Schema( @@ -47,13 +38,10 @@ using Tables String, ), ) - @test Tables.istable(AG.Table) == true - @test Tables.rowaccess(AG.Table) == true - @test Tables.rows(gt) isa AG.AbstractFeatureLayer - @test Tables.rows(gt1) isa AG.AbstractFeatureLayer - @test Tables.rows(gt2) isa AG.AbstractFeatureLayer + @test Tables.istable(typeof(layer)) == true + @test Tables.rowaccess(typeof(layer)) == true - features = collect(Tables.rows(gt1)) + features = collect(Tables.rows(layer1)) @test length(features) == 2 @test Tables.columnnames(features[1]) == From d2ae1bd1bff8a2378e871ca681deb3aed8031122 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 18:45:34 -0700 Subject: [PATCH 138/169] Undo replacement of empty geometry column names with "geometry". If we just do the replacement in the schema, the schema will be out of sync with the geometry column names of the individual features in the layer: this causes issues that were not detected when it was first introduced in #160. --- src/tables.jl | 1 - test/test_tables.jl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tables.jl b/src/tables.jl index e5635844..ca5d9893 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -55,6 +55,5 @@ function schema_names(featuredefn::IFeatureDefnView) Symbol(getname(getgeomdefn(featuredefn, i - 1))) for i in 1:ngeom(featuredefn) ) - replace!(geom_names, Symbol("") => Symbol("geometry"), count = 1) return (geom_names, field_names, featuredefn, fielddefns) end diff --git a/test/test_tables.jl b/test/test_tables.jl index 090bba01..d1ecf6af 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -83,7 +83,7 @@ using Tables @test isnothing(Tables.getcolumn(features[2], :fake)) geom_names, field_names = AG.schema_names(AG.layerdefn(layer)) - @test collect(geom_names) == [:geometry] + @test collect(geom_names) == [Symbol("")] @test collect(field_names) == [:FID, :pointname] geom_names, field_names = AG.schema_names(AG.layerdefn(layer1)) @test collect(geom_names) == [:point, :linestring] From 37cb501108dbc4ad09dfc638c14fec4110e6a288 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 18:48:49 -0700 Subject: [PATCH 139/169] Tweak wording --- docs/src/tables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tables.md b/docs/src/tables.md index 2af31c39..424c6c12 100644 --- a/docs/src/tables.md +++ b/docs/src/tables.md @@ -18,7 +18,7 @@ dataset = ArchGDAL.read("data/point.geojson") DataFrame(ArchGDAL.getlayer(dataset, 0)) ``` -Here is an example with multiple geometries based on the +To illustrate multiple geometries, here is a second example based on the [`data/multi_geom.csv`](https://github.com/yeesian/ArchGDALDatasets/blob/master/data/multi_geom.csv) dataset: From 4bfaa01e2975f7165ee7d6dbf7033d4b3188741a Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 19:00:54 -0700 Subject: [PATCH 140/169] format file --- test/test_gdalutilities.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/test_gdalutilities.jl b/test/test_gdalutilities.jl index c2fbc1db..bc3e0d01 100644 --- a/test/test_gdalutilities.jl +++ b/test/test_gdalutilities.jl @@ -163,11 +163,13 @@ using Test end @testset "GDAL Vector Translate" begin - AG.destroy(AG.unsafe_gdalvectortranslate( - [ds_point], - ["-f", "CSV", "-lco", "GEOMETRY=AS_XY"], - dest = "data/point.csv", - )) + AG.destroy( + AG.unsafe_gdalvectortranslate( + [ds_point], + ["-f", "CSV", "-lco", "GEOMETRY=AS_XY"], + dest = "data/point.csv", + ), + ) @test replace(read("data/point.csv", String), "\r" => "") == """ X,Y,FID,pointname 100,0,2,point-a From a8f831e214c074805927506b82ce1af99965211f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 19:01:15 -0700 Subject: [PATCH 141/169] fix typo and use https where possible --- docs/src/images.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/images.md b/docs/src/images.md index ecb1aac7..a3b03515 100644 --- a/docs/src/images.md +++ b/docs/src/images.md @@ -32,7 +32,7 @@ Or equivalently, ```@example rasters AG.imread(dataset, 1) ``` -It will interpret the color channel (for RGB) correctly there is one. E.g. +It will interpret the color channel (for RGB) correctly if there is one. E.g. ```@example rasters AG.imread(dataset, 2) ``` @@ -50,4 +50,4 @@ and ```@example rasters 0.5 * AG.imread(dataset, 1) + AG.imread(dataset, 3) ``` -See [Colors.jl](http://juliagraphics.github.io/Colors.jl/stable/) for more on what you can do. +See [Colors.jl](https://juliagraphics.github.io/Colors.jl/stable/) for more on what you can do. From 5107fe5fa14b92496eeca2cc58736c7f49cd2653 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 30 May 2021 19:01:56 -0700 Subject: [PATCH 142/169] use abstract input types and fix indentation for multiline strings --- src/raster/images.jl | 53 ++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index cd991e54..8d669586 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -1,5 +1,5 @@ function imview(colortype::Type{<:ColorTypes.Colorant}, imgvalues...) - return ImageCore.PermutedDimsArray( + return PermutedDimsArray( ImageCore.colorview( colortype, (ImageCore.normedview(img) for img in imgvalues)..., @@ -8,7 +8,7 @@ function imview(colortype::Type{<:ColorTypes.Colorant}, imgvalues...) ) end -function imview(gci::GDALColorInterp, imgvalues::Matrix) +function imview(gci::GDALColorInterp, imgvalues::AbstractMatrix) return if gci == GCI_GrayIndex imview(ColorTypes.Gray, imgvalues) elseif gci == GCI_Undefined @@ -25,27 +25,32 @@ function imview(gci::GDALColorInterp, imgvalues::Matrix) else error( """ - Unknown GCI: $gci. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. - """, + Unknown GCI: $gci. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. + """, ) end end -function imview(gpi::GDALPaletteInterp, imgvalues::Matrix) +function imview(gpi::GDALPaletteInterp, imgvalues::AbstractMatrix) return if gpi == GPI_Gray imview(ColorTypes.Gray, imgvalues) else error( """ - Unsupported GPI: $gpi. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. - """, + Unsupported GPI: $gpi. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. + """, ) end end -function imview(gpi::GDALPaletteInterp, c1::Matrix, c2::Matrix, c3::Matrix) +function imview( + gpi::GDALPaletteInterp, + c1::AbstractMatrix, + c2::AbstractMatrix, + c3::AbstractMatrix, +) return if gpi == GPI_Gray imview(ColorTypes.Gray, c1, c2, c3) elseif gpi == GPI_RGB @@ -53,19 +58,19 @@ function imview(gpi::GDALPaletteInterp, c1::Matrix, c2::Matrix, c3::Matrix) else error( """ - Unsupported GPI: $gpi. If it should be supported, please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. - """, + Unsupported GPI: $gpi. If it should be supported, please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. + """, ) end end function imview( gpi::GDALPaletteInterp, - c1::Matrix, - c2::Matrix, - c3::Matrix, - c4::Matrix, + c1::AbstractMatrix, + c2::AbstractMatrix, + c3::AbstractMatrix, + c4::AbstractMatrix, ) return if gpi == GPI_Gray imview(ColorTypes.Gray, c1, c2, c3, c4) @@ -74,9 +79,9 @@ function imview( else error( """ - Unsupported GPI: $gpi. If it should be supported, please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. - """, + Unsupported GPI: $gpi. If it should be supported, please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. + """, ) end end @@ -210,9 +215,9 @@ function _paletteindices(dataset::AbstractDataset, indices) else error( """ - Unknown GCI: $gciorder. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. - """, + Unknown GCI: $gciorder. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. + """, ) end end @@ -252,7 +257,7 @@ end imread(dataset::AbstractDataset) = imread(dataset, 1:nraster(dataset)) -function imread(filename::String) +function imread(filename::AbstractString) return read(filename) do dataset return imread(dataset) end From 3895551bee3aba298c259be1675e2f7c524aae84 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 13:32:15 -0700 Subject: [PATCH 143/169] remove conventions.md --- docs/make.jl | 1 - docs/src/conventions.md | 0 2 files changed, 1 deletion(-) delete mode 100644 docs/src/conventions.md diff --git a/docs/make.jl b/docs/make.jl index 5dfebc0e..390c2f93 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -25,7 +25,6 @@ makedocs( "Interactive versus Scoped Objects" => "memory.md", "Design Considerations" => "considerations.md", "API Reference" => "reference.md", - # "Naming Conventions" => "conventions.md", # table between GDAL, GDAL.jl, and ArchGDAL.jl ], ) diff --git a/docs/src/conventions.md b/docs/src/conventions.md deleted file mode 100644 index e69de29b..00000000 From 83b70259519581b1ca8070284f5c56d2f3d9e053 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 13:49:54 -0700 Subject: [PATCH 144/169] Return missing rather than -1 or nothing if no matching field is found. --- src/ogr/feature.jl | 23 ++++++++++++----------- src/tables.jl | 6 +++--- test/test_tables.jl | 12 ++++++------ 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 3813d71c..d0509a20 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -106,7 +106,7 @@ Fetch the field index given field name. * `name`: the name of the field to search for. ### Returns -the field index, or -1 if no matching field is found. +the field index, or `missing` if no matching field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. @@ -114,8 +114,13 @@ This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. function findfieldindex( feature::Feature, name::Union{AbstractString,Symbol}, -)::Integer - return GDAL.ogr_f_getfieldindex(feature.ptr, name) +)::Union{Integer,Missing} + i = GDAL.ogr_f_getfieldindex(feature.ptr, name) + return if i == -1 + missing + else + i + end end """ @@ -380,6 +385,8 @@ function getdefault(feature::Feature, i::Integer)::String return getdefault(getfielddefn(feature, i)) end +getfield(feature::Feature, i::Missing)::Missing = missing + function getfield(feature::Feature, i::Integer) _FETCHFIELD = Dict{OGRFieldType,Function}( OFTInteger => asint, #0 @@ -406,14 +413,8 @@ function getfield(feature::Feature, i::Integer) end end -function getfield(feature::Feature, name::Union{AbstractString,Symbol}) - i = findfieldindex(feature, name) - return if i == -1 - nothing - else - getfield(feature, i) - end -end +getfield(feature::Feature, name::Union{AbstractString,Symbol}) = + getfield(feature, findfieldindex(feature, name)) """ setfield!(feature::Feature, i::Integer, value) diff --git a/src/tables.jl b/src/tables.jl index ca5d9893..13e15290 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -25,20 +25,20 @@ function Tables.getcolumn(row::Feature, i::Int) elseif i > 0 return getfield(row, i - 1) else - return nothing + return missing end end function Tables.getcolumn(row::Feature, name::Symbol) field = getfield(row, name) - if !isnothing(field) + if !ismissing(field) return field end geom = getgeom(row, name) if geom.ptr != C_NULL return geom end - return nothing + return missing end function Tables.columnnames( diff --git a/test/test_tables.jl b/test/test_tables.jl index d1ecf6af..753e3334 100644 --- a/test/test_tables.jl +++ b/test/test_tables.jl @@ -46,8 +46,8 @@ using Tables @test Tables.columnnames(features[1]) == (:point, :linestring, :id, :zoom, :location) - @test Tables.getcolumn(features[2], -5) == nothing - @test Tables.getcolumn(features[2], 0) == nothing + @test ismissing(Tables.getcolumn(features[2], -5)) + @test ismissing(Tables.getcolumn(features[2], 0)) @test Tables.getcolumn(features[1], 1) == "5.1" @test Tables.getcolumn(features[1], 2) == "1.0" @test Tables.getcolumn(features[1], 3) == "Mumbai" @@ -61,12 +61,12 @@ using Tables "POINT (30 10)" @test AG.toWKT(Tables.getcolumn(features[1], :linestring)) == "LINESTRING (30 10,10 30,40 40)" - @test isnothing(Tables.getcolumn(features[1], :fake)) + @test ismissing(Tables.getcolumn(features[1], :fake)) @test Tables.columnnames(features[2]) == (:point, :linestring, :id, :zoom, :location) - @test Tables.getcolumn(features[2], -5) == nothing - @test Tables.getcolumn(features[2], 0) == nothing + @test ismissing(Tables.getcolumn(features[2], -5)) + @test ismissing(Tables.getcolumn(features[2], 0)) @test Tables.getcolumn(features[2], 1) == "5.2" @test Tables.getcolumn(features[2], 2) == "2.0" @test Tables.getcolumn(features[2], 3) == "New Delhi" @@ -80,7 +80,7 @@ using Tables "POINT (35 15)" @test AG.toWKT(Tables.getcolumn(features[2], :linestring)) == "LINESTRING (35 15,15 35,45 45)" - @test isnothing(Tables.getcolumn(features[2], :fake)) + @test ismissing(Tables.getcolumn(features[2], :fake)) geom_names, field_names = AG.schema_names(AG.layerdefn(layer)) @test collect(geom_names) == [Symbol("")] From 7351750705dcc178fb8ebffd2a7645713e69e65d Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 14:02:02 -0700 Subject: [PATCH 145/169] Added discussion on tables interface Based on the thread in https://github.com/yeesian/ArchGDAL.jl/pull/179#discussion_r642127217. --- docs/src/considerations.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/src/considerations.md b/docs/src/considerations.md index 7ab87838..709c2efa 100644 --- a/docs/src/considerations.md +++ b/docs/src/considerations.md @@ -15,3 +15,10 @@ Here's a collection of references for developers who are interested: - [https://github.com/mapbox/rasterio/pull/665](https://github.com/mapbox/rasterio/pull/665) - [https://github.com/mapbox/rasterio/issues/875](https://github.com/mapbox/rasterio/issues/875) - [https://rasterio.readthedocs.io/en/latest/topics/configuration.html](https://rasterio.readthedocs.io/en/latest/topics/configuration.html) + +## Tables.jl Interface + +The interface is implemented in [`src/tables.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/tables.jl). The current API from GDAL makes it row-based in the conventions of Tables.jl. Therefore, + +* `ArchGDAL.Feature` meets the criteria for an [`AbstractRow`](https://tables.juliadata.org/dev/#Tables.AbstractRow-1) based on https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/tables.jl#L31-L58. +* `ArchGDAL.FeatureLayer` meets the criteria for an `AbstractRow`-iterator based on the previous bullet and meeting the criteria for [`Iteration`](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) in https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/base/iterators.jl#L1-L18 From 9c7069cbd30b4bf61fbe59901577a18c1950301f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 14:20:46 -0700 Subject: [PATCH 146/169] Add discussion of enum values between base enums and cenums Based on the discussion in https://github.com/yeesian/ArchGDAL.jl/pull/179#discussion_r642123058. --- docs/src/considerations.md | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/src/considerations.md b/docs/src/considerations.md index 709c2efa..d4f46cd0 100644 --- a/docs/src/considerations.md +++ b/docs/src/considerations.md @@ -16,6 +16,55 @@ Here's a collection of references for developers who are interested: - [https://github.com/mapbox/rasterio/issues/875](https://github.com/mapbox/rasterio/issues/875) - [https://rasterio.readthedocs.io/en/latest/topics/configuration.html](https://rasterio.readthedocs.io/en/latest/topics/configuration.html) +## GDAL Enum Values + +[GDAL.jl](https://github.com/JuliaGeo/GDAL.jl) uses [CEnum.jl](https://github.com/JuliaInterop/CEnum.jl), which is a C-compatible enum, this is the default in [Clang.jl](https://github.com/JuliaInterop/Clang.jl). This is useful when the underlying values are of interest, for example the following snippets from [`src/types.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/types.jl): + +```julia +import Base.| + +for T in (GDALOpenFlag, FieldValidation) + eval(quote + |(x::$T, y::UInt8) = UInt8(x) | y + |(x::UInt8, y::$T) = x | UInt8(y) + |(x::$T, y::$T) = UInt8(x) | UInt8(y) + end) +end +``` + +and + +```julia +function basetype(gt::OGRwkbGeometryType)::OGRwkbGeometryType + wkbGeomType = convert(GDAL.OGRwkbGeometryType, gt) + wkbGeomType &= (~0x80000000) # Remove 2.5D flag. + wkbGeomType %= 1000 # Normalize Z, M, and ZM types. + return GDAL.OGRwkbGeometryType(wkbGeomType) +end +``` + +However, the use of CEnum.jl allows for multiple enums to have the same underlying value, resulting in unintuitive behavior if they are used as keys in a dictionary. For example, in the following code: + +```julia +julia> Dict(GDAL.GCI_YCbCr_CrBand => "a", GDAL.GCI_Max => "b") +Dict{GDAL.GDALColorInterp, String} with 1 entry: + GCI_YCbCr_CrBand => "b" +``` + +the entry for `GDAL.GCI_YCbCr_CrBand => "a"` got overwritten by `GDAL.GCI_Max => "b"` because both `GDAL.GCI_YCbCr_CrBand` and `GDAL.GCI_Max` corresponded to the same value. + +To avoid such forms of behavior, this package uses [`Base.Enums`](https://docs.julialang.org/en/v1/base/base/#Base.Enums.Enum) instead, so the above example would result in the following behavior: + + +```julia +julia> Dict(ArchGDAL.GCI_YCbCr_CrBand => "a", ArchGDAL.GCI_Max => "b") +Dict{ArchGDAL.GDALColorInterp, String} with 2 entries: + GCI_YCbCr_CrBand => "a" + GCI_Max => "b" +``` + +To maintain parity with GDAL behavior, ArchGDAL.jl provides conversion methods to map from the enums in ArchGDAL to the corresponding cenums from GDAL.jl when calling the corresponding GDAL functions. + ## Tables.jl Interface The interface is implemented in [`src/tables.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/tables.jl). The current API from GDAL makes it row-based in the conventions of Tables.jl. Therefore, From abe94cdea5ff20233fb96d519ac25c87f8b3c9b1 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 14:30:52 -0700 Subject: [PATCH 147/169] Updating getnodatavalueband to return missing rather than nothing Based on https://docs.julialang.org/en/v1/manual/faq/#Nothingness-and-missing-values-1: > To represent missing data in the statistical sense (NA in R or NULL in SQL), use the missing object. --- src/raster/rasterband.jl | 14 +++++++------- test/test_display.jl | 2 +- test/test_ospy_examples.jl | 4 ++-- test/test_rasterband.jl | 20 ++++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index cd0c7ba0..4a5833e3 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -176,15 +176,15 @@ end Fetch the no data value for this band. -If there is no out of data value, `nothing` will be -returned instead. The no data value for a band is generally a special marker -value used to mark pixels that are not valid data. Such pixels should generally -not be displayed, nor contribute to analysis operations. +If there is no out of data value, `missing` will be returned instead. The no +data value for a band is generally a special marker value used to mark pixels +that are not valid data. Such pixels should generally not be displayed, nor +contribute to analysis operations. ### Returns -the nodata value for this band or `nothing`. +the nodata value for this band or `missing`. """ -function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Nothing} +function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Missing} # ### Parameters # * `pbSuccess` pointer to a boolean to use to indicate if a value is # actually associated with this layer. May be `NULL` (default). @@ -193,7 +193,7 @@ function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Nothing} return if Bool(hasnodatavalue[]) nodatavalue else - nothing + missing end end diff --git a/test/test_display.jl b/test/test_display.jl index 3a995fea..ad4af648 100644 --- a/test/test_display.jl +++ b/test/test_display.jl @@ -68,7 +68,7 @@ const AG = ArchGDAL; @test sprint(print, AG.getband(dataset, 1)) == """ [GA_ReadOnly] Band 1 (Red): 2048 x 1024 (UInt8) - blocksize: 256×256, nodata: nothing, units: 1.0px + 0.0 + blocksize: 256×256, nodata: missing, units: 1.0px + 0.0 overviews: (0) 1024x512 (1) 512x256 (2) 256x128 (3) 128x64 (4) 64x32 (5) 32x16 (6) 16x8 """ diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index 3913bb71..0102134d 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -385,7 +385,7 @@ const AG = ArchGDAL; outband = AG.getband(outDS, 1) @test sprint(print, outband) == """ [GA_Update] Band 1 (Undefined): 5665 x 5033 (Float32) - blocksize: 5665×1, nodata: nothing, units: 1.0px + 0.0 + blocksize: 5665×1, nodata: missing, units: 1.0px + 0.0 overviews: """ AG.setnodatavalue!(outband, -99) # georeference the image and set the projection @@ -484,7 +484,7 @@ const AG = ArchGDAL; bandout = AG.getband(dsout, 1) @test sprint(print, bandout) == """ [GA_Update] Band 1 (Undefined): 4500 x 3000 (UInt8) - blocksize: 4500×1, nodata: nothing, units: 1.0px + 0.0 + blocksize: 4500×1, nodata: missing, units: 1.0px + 0.0 overviews: """ # set the geotransform and projection on the output diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 059ba621..83bfe780 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -43,25 +43,25 @@ const AG = ArchGDAL; AG.setscale!(rb, 1) @test AG.getscale(rb) ≈ 1 - @test isnothing(AG.getnodatavalue(rb)) + @test ismissing(AG.getnodatavalue(rb)) AG.setnodatavalue!(rb, -100) @test AG.getnodatavalue(rb) ≈ -100 AG.deletenodatavalue!(rb) - @test isnothing(AG.getnodatavalue(rb)) + @test ismissing(AG.getnodatavalue(rb)) AG.copy(dataset) do dest destband = AG.getband(dest, 1) AG.copywholeraster!(rb, destband) @test sprint(print, destband) == """ [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 overviews: """ @test AG.noverview(destband) == 0 AG.buildoverviews!(dest, Cint[2, 4, 8]) @test AG.noverview(destband) == 3 @test sprint(print, destband) == """ [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 overviews: (0) 50x50 (1) 25x25 (2) 13x13 """ @test AG.getcolorinterp(destband) == AG.GCI_GrayIndex @@ -70,25 +70,25 @@ const AG = ArchGDAL; @test sprint(print, AG.sampleoverview(destband, 100)) == """ [GA_Update] Band 1 (Gray): 13 x 13 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 overviews: """ @test sprint(print, AG.sampleoverview(destband, 200)) == """ [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 overviews: """ @test sprint(print, AG.sampleoverview(destband, 500)) == """ [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 overviews: """ AG.sampleoverview(destband, 1000) do result @test sprint(print, result) == """ [GA_Update] Band 1 (Gray): 50 x 50 (UInt8) - blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 overviews: """ end @test sprint(print, AG.getmaskband(destband)) == """ [GA_ReadOnly] Band 0 (Undefined): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 overviews: """ @test AG.maskflags(destband) == 1 @test AG.maskflaginfo(rb) == ( @@ -101,7 +101,7 @@ const AG = ArchGDAL; AG.getmaskband(destband) do maskband @test sprint(print, maskband) == """ [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 overviews: """ end @test AG.maskflags(destband) == 3 From e720366b307fe6e7f91f5b28e8ea95527be078bd Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 14:45:33 -0700 Subject: [PATCH 148/169] Capture the discussion on colors and images --- docs/src/considerations.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/src/considerations.md b/docs/src/considerations.md index d4f46cd0..a592cedf 100644 --- a/docs/src/considerations.md +++ b/docs/src/considerations.md @@ -65,6 +65,29 @@ Dict{ArchGDAL.GDALColorInterp, String} with 2 entries: To maintain parity with GDAL behavior, ArchGDAL.jl provides conversion methods to map from the enums in ArchGDAL to the corresponding cenums from GDAL.jl when calling the corresponding GDAL functions. +## Colors + +Rather than encouraging [operations on colortables](https://gdal.org/python/osgeo.gdal.ColorTable-class.html) (with very limited functionality from GDAL), users are better served by arrays of [ColorTypes](https://github.com/JuliaGraphics/ColorTypes.jl) using [Colors.jl](https://github.com/JuliaGraphics/Colors.jl), [for example](http://juliagraphics.github.io/Colors.jl/stable/colormapsandcolorscales/#Generating-a-range-of-colors) + +```julia +range(startcolor, stop=endcolor, length=15) +``` + +instead of + +```julia +createcolorramp!(colortable, startindex, startcolor, startindex+15, endcolor) +``` + +## Images + +To differentiate 2d arrays of colors from 3d arrays with band as the third dimension: + +* For 2D arrays (a single rasterband), if they have a color interpretation, we use the color interpretation. If they don't have a color interpretation, ArchGDAL.jl defaults to "Grey". +* For >2D arrays (multiple rasterbands), if they have a palette interpretation (or combination of color interpretations) that resolves to a valid colortype, ArchGDAL.jl uses the palette interpretation. If they don't have a palette interpretation, we throw an error. + +In general, `read()` will return `Array{UInt8}`, and `imread()` will return `Array{<:Colorant}`. + ## Tables.jl Interface The interface is implemented in [`src/tables.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/tables.jl). The current API from GDAL makes it row-based in the conventions of Tables.jl. Therefore, From cff9913d38dbbd27c65dbe5f005a283f68566307 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 15:01:58 -0700 Subject: [PATCH 149/169] Ran juliaformatter --- src/ogr/feature.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index d0509a20..4d866380 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -413,8 +413,9 @@ function getfield(feature::Feature, i::Integer) end end -getfield(feature::Feature, name::Union{AbstractString,Symbol}) = - getfield(feature, findfieldindex(feature, name)) +function getfield(feature::Feature, name::Union{AbstractString,Symbol}) + return getfield(feature, findfieldindex(feature, name)) +end """ setfield!(feature::Feature, i::Integer, value) From d5a5885057a53499965c83839c6aba5912e67191 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 15:46:55 -0700 Subject: [PATCH 150/169] Add docstrings for enum conversions --- src/constants.jl | 180 +++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + test/test_doctest.jl | 3 + 3 files changed, 184 insertions(+) create mode 100644 test/test_doctest.jl diff --git a/src/constants.jl b/src/constants.jl index 5e62a733..8ef6fe5d 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -1,5 +1,17 @@ const StringList = Ptr{Cstring} +""" +The value of `GDALDataType` could be different from `GDAL.GDALDataType`. + +It maps correctly to `GDAL.GDALDataType` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALDataType, ArchGDAL.GDT_Unknown) + +# output +GDT_Unknown::GDALDataType = 0x00000000 +``` +""" @enum( GDALDataType, GDT_Unknown = 0, @@ -17,6 +29,18 @@ const StringList = Ptr{Cstring} GDT_TypeCount = 12, ) +""" +The value of `OGRFieldType` could be different from `GDAL.OGRFieldType`. + +It maps correctly to `GDAL.OGRFieldType` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRFieldType, ArchGDAL.OFTInteger) + +# output +OFTInteger::OGRFieldType = 0x00000000 +``` +""" @enum( OGRFieldType, OFTInteger = 0, @@ -36,6 +60,18 @@ const StringList = Ptr{Cstring} OFTMaxType = 14, # 13 ) +""" +The value of `OGRFieldSubType` could be different from `GDAL.OGRFieldSubType`. + +It maps correctly to `GDAL.OGRFieldSubType` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRFieldSubType, ArchGDAL.OFSTNone) + +# output +OFSTNone::OGRFieldSubType = 0x00000000 +``` +""" @enum( OGRFieldSubType, OFSTNone = 0, @@ -46,10 +82,46 @@ const StringList = Ptr{Cstring} OFSTMaxSubType = 5, # 4 ) +""" +The value of `OGRJustification` could be different from `GDAL.OGRJustification`. + +It maps correctly to `GDAL.OGRJustification` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRJustification, ArchGDAL.OJUndefined) + +# output +OJUndefined::OGRJustification = 0x00000000 +``` +""" @enum(OGRJustification, OJUndefined = 0, OJLeft = 1, OJRight = 2,) +""" +The value of `GDALRATFieldType` could be different from `GDAL.GDALRATFieldType`. + +It maps correctly to `GDAL.GDALRATFieldType` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALRATFieldType, ArchGDAL.GFT_Integer) + +# output +GFT_Integer::GDALRATFieldType = 0x00000000 +``` +""" @enum(GDALRATFieldType, GFT_Integer = 0, GFT_Real = 1, GFT_String = 2,) +""" +The value of `GDALRATFieldUsage` could be different from `GDAL.GDALRATFieldUsage`. + +It maps correctly to `GDAL.GDALRATFieldUsage` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALRATFieldUsage, ArchGDAL.GFU_Generic) + +# output +GFU_Generic::GDALRATFieldUsage = 0x00000000 +``` +""" @enum( GDALRATFieldUsage, GFU_Generic = 0, @@ -73,12 +145,60 @@ const StringList = Ptr{Cstring} GFU_MaxCount = 18, ) +""" +The value of `GDALAccess` could be different from `GDAL.GDALAccess`. + +It maps correctly to `GDAL.GDALAccess` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALAccess, ArchGDAL.GA_ReadOnly) + +# output +GA_ReadOnly::GDALAccess = 0x00000000 +``` +""" @enum(GDALAccess, GA_ReadOnly = 0, GA_Update = 1,) +""" +The value of `GDALRWFlag` could be different from `GDAL.GDALRWFlag`. + +It maps correctly to `GDAL.GDALRWFlag` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALRWFlag, ArchGDAL.GF_Read) + +# output +GF_Read::GDALRWFlag = 0x00000000 +``` +""" @enum(GDALRWFlag, GF_Read = 0, GF_Write = 1,) +""" +The value of `GDALPaletteInterp` could be different from `GDAL.GDALPaletteInterp`. + +It maps correctly to `GDAL.GDALPaletteInterp` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALPaletteInterp, ArchGDAL.GPI_Gray) + +# output +GPI_Gray::GDALPaletteInterp = 0x00000000 +``` +""" @enum(GDALPaletteInterp, GPI_Gray = 0, GPI_RGB = 1, GPI_CMYK = 2, GPI_HLS = 3,) +""" +The value of `GDALColorInterp` could be different from `GDAL.GDALColorInterp`. + +It maps correctly to `GDAL.GDALColorInterp` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALColorInterp, ArchGDAL.GCI_Undefined) + +# output +GCI_Undefined::GDALColorInterp = 0x00000000 +``` +""" @enum( GDALColorInterp, GCI_Undefined = 0, @@ -101,6 +221,18 @@ const StringList = Ptr{Cstring} GCI_Max = 17, # Max current value = 16 ) +""" +The value of `GDALAsyncStatusType` could be different from `GDAL.GDALAsyncStatusType`. + +It maps correctly to `GDAL.GDALAsyncStatusType` if you do e.g. + +```jldoctest; output = false +convert(GDAL.GDALAsyncStatusType, ArchGDAL.GARIO_PENDING) + +# output +GARIO_PENDING::GDALAsyncStatusType = 0x00000000 +``` +""" @enum( GDALAsyncStatusType, GARIO_PENDING = 0, @@ -110,6 +242,18 @@ const StringList = Ptr{Cstring} GARIO_TypeCount = 4, ) +""" +The value of `OGRSTClassId` could be different from `GDAL.OGRSTClassId`. + +It maps correctly to `GDAL.OGRSTClassId` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRSTClassId, ArchGDAL.OGRSTCNone) + +# output +OGRSTCNone::ogr_style_tool_class_id = 0x00000000 +``` +""" @enum( OGRSTClassId, OGRSTCNone = 0, @@ -120,6 +264,18 @@ const StringList = Ptr{Cstring} OGRSTCVector = 5, ) +""" +The value of `OGRSTUnitId` could be different from `GDAL.OGRSTUnitId`. + +It maps correctly to `GDAL.OGRSTUnitId` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRSTUnitId, ArchGDAL.OGRSTUGround) + +# output +OGRSTUGround::ogr_style_tool_units_id = 0x00000000 +``` +""" @enum( OGRSTUnitId, OGRSTUGround = 0, @@ -130,6 +286,18 @@ const StringList = Ptr{Cstring} OGRSTUInches = 5, ) +""" +The value of `OGRwkbGeometryType` could be different from `GDAL.OGRwkbGeometryType`. + +It maps correctly to `GDAL.OGRwkbGeometryType` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRwkbGeometryType, ArchGDAL.wkbUnknown) + +# output +wkbUnknown::OGRwkbGeometryType = 0x00000000 +``` +""" @enum( OGRwkbGeometryType, wkbUnknown = 0, @@ -205,6 +373,18 @@ const StringList = Ptr{Cstring} wkbGeometryCollection25D = 70, ) +""" +The value of `OGRwkbByteOrder` could be different from `GDAL.OGRwkbByteOrder`. + +It maps correctly to `GDAL.OGRwkbByteOrder` if you do e.g. + +```jldoctest; output = false +convert(GDAL.OGRwkbByteOrder, ArchGDAL.wkbXDR) + +# output +wkbXDR::OGRwkbByteOrder = 0x00000000 +``` +""" @enum(OGRwkbByteOrder, wkbXDR = 0, wkbNDR = 1,) @enum( diff --git a/test/runtests.jl b/test/runtests.jl index eba19932..b47a6f30 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,6 +7,7 @@ include("remotefiles.jl") @testset "ArchGDAL" begin cd(dirname(@__FILE__)) do isdir("tmp") || mkpath("tmp") + include("test_doctest.jl") include("test_convert.jl") include("test_tables.jl") include("test_gdal_tutorials.jl") diff --git a/test/test_doctest.jl b/test/test_doctest.jl new file mode 100644 index 00000000..c3524021 --- /dev/null +++ b/test/test_doctest.jl @@ -0,0 +1,3 @@ +using Test, Documenter, ArchGDAL +DocMeta.setdocmeta!(ArchGDAL, :DocTestSetup, :(using ArchGDAL, GDAL); recursive=true) +doctest(ArchGDAL) From ab2b9294fc4f8818bc37facc1a31ed75eb15cc23 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 15:47:03 -0700 Subject: [PATCH 151/169] annotate return types --- src/types.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types.jl b/src/types.jl index e4283566..affc7d17 100644 --- a/src/types.jl +++ b/src/types.jl @@ -552,9 +552,9 @@ import Base.| for T in (GDALOpenFlag, FieldValidation) eval(quote - |(x::$T, y::UInt8) = UInt8(x) | y - |(x::UInt8, y::$T) = x | UInt8(y) - |(x::$T, y::$T) = UInt8(x) | UInt8(y) + |(x::$T, y::UInt8)::UInt8 = UInt8(x) | y + |(x::UInt8, y::$T)::UInt8 = x | UInt8(y) + |(x::$T, y::$T)::UInt8 = UInt8(x) | UInt8(y) end) end From 38cbd06e9f38db9cf9b6e762e9adeebffd941268 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 15:47:31 -0700 Subject: [PATCH 152/169] Update test-specific dependencies Based on https://pkgdocs.julialang.org/v1/creating-packages/#Test-specific-dependencies-in-Julia-1.2-and-above. --- Project.toml | 11 ----------- test/Project.toml | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 test/Project.toml diff --git a/Project.toml b/Project.toml index 653ffa3c..0985d928 100644 --- a/Project.toml +++ b/Project.toml @@ -24,14 +24,3 @@ GeoInterface = "0.4, 0.5" ImageCore = "0.9" Tables = "1" julia = "1.3" - -[extras] -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" -Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["Dates", "Downloads", "Pkg", "Statistics", "SHA", "Test"] diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..134631c2 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,15 @@ +[deps] +ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a" +GeoFormatTypes = "68eda718-8dee-11e9-39e7-89f7f65f511f" +GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From 17301f91297e1b92ce3a205d0df9876f1b23dd61 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 16:25:18 -0700 Subject: [PATCH 153/169] Fix doc builds --- docs/make.jl | 2 ++ docs/src/reference.md | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/docs/make.jl b/docs/make.jl index 390c2f93..3492605f 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,5 +1,7 @@ using Documenter, ArchGDAL +DocMeta.setdocmeta!(ArchGDAL, :DocTestSetup, :(using ArchGDAL, GDAL); recursive=true) + # make sure you have run the tests before such that the test files are present makedocs( modules = [ArchGDAL], diff --git a/docs/src/reference.md b/docs/src/reference.md index 3519bf58..908d6856 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -7,6 +7,13 @@ Modules = [ArchGDAL] Pages = ["ArchGDAL.jl", "display.jl", "iterators.jl", "types.jl", "utils.jl"] ``` +## [GDAL Constants](@id API-GDAL-Constants) + +```@autodocs +Modules = [ArchGDAL] +Pages = ["constants.jl"] +``` + ## [GDAL Datasets](@id API-GDAL-Datasets) ```@autodocs From bba88d6271f3afb4c5db709e10f508eaf34b5d50 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 16:25:27 -0700 Subject: [PATCH 154/169] ignore tif files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index acd3f803..a110aa2e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ test/pyrasterio/ test/spatialite/ .DS_Store Manifest.toml +*.tif From 06b2885cb1f2b2006a70795374118a00e149b356 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 16:26:02 -0700 Subject: [PATCH 155/169] Be consistent in using module names as prefixes --- docs/src/geometries.md | 53 ++++++++++++++++++++--------------------- docs/src/images.md | 19 +++++++-------- docs/src/projections.md | 1 - docs/src/spatialite.md | 7 +++--- docs/src/tables.md | 7 +++--- 5 files changed, 41 insertions(+), 46 deletions(-) diff --git a/docs/src/geometries.md b/docs/src/geometries.md index aef12ab4..383aefa1 100644 --- a/docs/src/geometries.md +++ b/docs/src/geometries.md @@ -2,7 +2,6 @@ ```@setup geometries using ArchGDAL -const AG = ArchGDAL ``` In this section, we consider some of the common kinds of geometries that arises in applications. These include `Point`, `LineString`, `Polygon`, `GeometryCollection`, `MultiPolygon`, `MultiPoint`, and `MultiLineString`. For brevity in the examples, we will use the prefix `const AG = ArchGDAL`. @@ -11,53 +10,53 @@ In this section, we consider some of the common kinds of geometries that arises To create geometries of different types, ```@example geometries -point = AG.createpoint(1.0, 2.0) -linestring = AG.createlinestring([(i,i+1) for i in 1.0:3.0]) -linearring = AG.createlinearring([(0.,0.), (0.,1.), (1.,1.)]) -simplepolygon = AG.createpolygon([(0.,0.), (0.,1.), (1.,1.)]) -complexpolygon = AG.createpolygon([[(0.,0.), (0.,j), (j,j)] for j in 1.0:-0.1:0.9]) -multipoint = AG.createlinearring([(0.,0.), (0.,1.), (1.,1.)]) -multilinestring = AG.createmultilinestring([[(i,i+1) for i in j:j+3] for j in 1.0:5.0:6.0]) -multipolygon = AG.createmultipolygon([[[(0.,0.), (0.,j), (j,j)]] for j in 1.0:-0.1:0.9]) +point = ArchGDAL.createpoint(1.0, 2.0) +linestring = ArchGDAL.createlinestring([(i,i+1) for i in 1.0:3.0]) +linearring = ArchGDAL.createlinearring([(0.,0.), (0.,1.), (1.,1.)]) +simplepolygon = ArchGDAL.createpolygon([(0.,0.), (0.,1.), (1.,1.)]) +complexpolygon = ArchGDAL.createpolygon([[(0.,0.), (0.,j), (j,j)] for j in 1.0:-0.1:0.9]) +multipoint = ArchGDAL.createlinearring([(0.,0.), (0.,1.), (1.,1.)]) +multilinestring = ArchGDAL.createmultilinestring([[(i,i+1) for i in j:j+3] for j in 1.0:5.0:6.0]) +multipolygon = ArchGDAL.createmultipolygon([[[(0.,0.), (0.,j), (j,j)]] for j in 1.0:-0.1:0.9]) ``` Alternatively, they can be assembled from their components. ```@example geometries -point = AG.createpoint() -AG.addpoint!(point, 1.0, 2.0) +point = ArchGDAL.createpoint() +ArchGDAL.addpoint!(point, 1.0, 2.0) -linestring = AG.createlinestring() +linestring = ArchGDAL.createlinestring() for i in 1.0:3.0 - AG.addpoint!(linestring, i, i+1) + ArchGDAL.addpoint!(linestring, i, i+1) end -linearring = AG.createlinearring() +linearring = ArchGDAL.createlinearring() for i in 1.0:3.0 - AG.addpoint!(linearring, i, i+1) + ArchGDAL.addpoint!(linearring, i, i+1) end -polygon = AG.createpolygon() +polygon = ArchGDAL.createpolygon() for j in 1.0:-0.1:0.9 - ring = AG.createlinearring([(0.,0.), (0.,j), (j,j)]) - AG.addgeom!(polygon, ring) + ring = ArchGDAL.createlinearring([(0.,0.), (0.,j), (j,j)]) + ArchGDAL.addgeom!(polygon, ring) end -multipoint = AG.createmultipoint() +multipoint = ArchGDAL.createmultipoint() for i in 1.0:3.0 - pt = AG.createpoint(i, i+1) - AG.addgeom!(multipoint, pt) + pt = ArchGDAL.createpoint(i, i+1) + ArchGDAL.addgeom!(multipoint, pt) end -multilinestring = AG.createmultilinestring() +multilinestring = ArchGDAL.createmultilinestring() for j in 1.0:5.0:6.0 - line = AG.createlinestring([(i,i+1) for i in j:j+3]) - AG.addgeom!(multilinestring, line) + line = ArchGDAL.createlinestring([(i,i+1) for i in j:j+3]) + ArchGDAL.addgeom!(multilinestring, line) end -multipolygon = AG.createmultipolygon() +multipolygon = ArchGDAL.createmultipolygon() for j in 1.0:-0.1:0.9 - poly = AG.createpolygon([(0.,0.), (0.,j), (j,j)]) - AG.addgeom!(multipolygon, poly) + poly = ArchGDAL.createpolygon([(0.,0.), (0.,j), (j,j)]) + ArchGDAL.addgeom!(multipolygon, poly) end ``` diff --git a/docs/src/images.md b/docs/src/images.md index a3b03515..69c1c647 100644 --- a/docs/src/images.md +++ b/docs/src/images.md @@ -2,52 +2,51 @@ ```@setup rasters using ArchGDAL -const AG = ArchGDAL ``` In this section, we revisit the [`gdalworkshop/world.tif`](https://github.com/yeesian/ArchGDALDatasets/blob/307f8f0e584a39a050c042849004e6a2bd674f99/gdalworkshop/world.tif) dataset. ```@example rasters -dataset = AG.read("gdalworkshop/world.tif") +dataset = ArchGDAL.read("gdalworkshop/world.tif") ``` A description of the display is available in [Raster Datasets](@ref). ## Reading from Datasets We can construct an image from it in the following way: ```@example rasters -AG.imread(dataset) +ArchGDAL.imread(dataset) ``` ## Reading from Files We can read the file as an image instead: ```@example rasters -AG.imread("gdalworkshop/world.tif") +ArchGDAL.imread("gdalworkshop/world.tif") ``` ## Reading from Rasterbands We can also read from individual raster bands: ```@example rasters -AG.imread(AG.getband(dataset, 1)) +ArchGDAL.imread(ArchGDAL.getband(dataset, 1)) ``` Or equivalently, ```@example rasters -AG.imread(dataset, 1) +ArchGDAL.imread(dataset, 1) ``` It will interpret the color channel (for RGB) correctly if there is one. E.g. ```@example rasters -AG.imread(dataset, 2) +ArchGDAL.imread(dataset, 2) ``` and ```@example rasters -AG.imread(dataset, 3) +ArchGDAL.imread(dataset, 3) ``` ## Working with Colors Operations on colors behave as you think they might: ```@example rasters -AG.imread(dataset, 2) + AG.imread(dataset, 3) +ArchGDAL.imread(dataset, 2) + ArchGDAL.imread(dataset, 3) ``` and ```@example rasters -0.5 * AG.imread(dataset, 1) + AG.imread(dataset, 3) +0.5 * ArchGDAL.imread(dataset, 1) + ArchGDAL.imread(dataset, 3) ``` See [Colors.jl](https://juliagraphics.github.io/Colors.jl/stable/) for more on what you can do. diff --git a/docs/src/projections.md b/docs/src/projections.md index 738896ca..49f56d39 100644 --- a/docs/src/projections.md +++ b/docs/src/projections.md @@ -2,7 +2,6 @@ ```@setup projections using ArchGDAL -const AG = ArchGDAL ``` (This is based entirely on the [GDAL/OSR Tutorial](http://www.gdal.org/osr_tutorial.html) and [Python GDAL/OGR Cookbook](https://pcjericks.github.io/py-gdalogr-cookbook/projection.html).) diff --git a/docs/src/spatialite.md b/docs/src/spatialite.md index 063be83c..9534f8b5 100644 --- a/docs/src/spatialite.md +++ b/docs/src/spatialite.md @@ -12,7 +12,6 @@ We will work with the following database: ```@example spatialite import ArchGDAL -const AG = ArchGDAL filepath = download("https://github.com/yeesian/ArchGDALDatasets/raw/e0b15dca5ad493c5ebe8111688c5d14b031b7305/spatialite/test-2.3.sqlite", "test.sqlite") ``` @@ -20,7 +19,7 @@ filepath = download("https://github.com/yeesian/ArchGDALDatasets/raw/e0b15dca5ad Here's a quick summary of `test.sqlite`: ```@example spatialite -AG.read(filepath) do dataset +ArchGDAL.read(filepath) do dataset print(dataset) end ``` @@ -29,8 +28,8 @@ We will display the results of running `query` on the dataset using the followin ```@example spatialite function inspect(query, filename=filepath) - AG.read(filename) do dataset - AG.executesql(dataset, query) do results + ArchGDAL.read(filename) do dataset + ArchGDAL.executesql(dataset, query) do results print(results) end end diff --git a/docs/src/tables.md b/docs/src/tables.md index 424c6c12..bd80000b 100644 --- a/docs/src/tables.md +++ b/docs/src/tables.md @@ -1,8 +1,7 @@ # Tabular Interface ```@setup tables -using ArchGDAL -using DataFrames +using ArchGDAL, DataFrames ``` ArchGDAL now brings in greater flexibilty in terms of vector data handling via the @@ -15,7 +14,7 @@ dataset: ```@example tables dataset = ArchGDAL.read("data/point.geojson") -DataFrame(ArchGDAL.getlayer(dataset, 0)) +DataFrames.DataFrame(ArchGDAL.getlayer(dataset, 0)) ``` To illustrate multiple geometries, here is a second example based on the @@ -25,5 +24,5 @@ dataset: ```@example tables dataset1 = ArchGDAL.read("data/multi_geom.csv", options = ["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"]) -DataFrame(ArchGDAL.getlayer(dataset1, 0)) +DataFrames.DataFrame(ArchGDAL.getlayer(dataset1, 0)) ``` From 1939d1199f0020c32a6bbbb2b365b887253e228c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 16:30:03 -0700 Subject: [PATCH 156/169] add GDAL as dependency for docs --- docs/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Project.toml b/docs/Project.toml index 5b55e0dd..0b775dab 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -3,6 +3,7 @@ ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a" [compat] Documenter = "0.26.2" From 29c4a943a7cf1b6888561fa4774a8eceae5f07b7 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 31 May 2021 17:44:22 -0700 Subject: [PATCH 157/169] Update instructions for formatting code. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c49bdd1d..bdc451cc 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,9 @@ an autoformatting tool, and uses the options in [`.JuliaFormatter.toml`](https:/ If you wish to format code, `cd` to the ArchGDAL.jl directory, then run: ```julia -] add JuliaFormatter@0.13.10 +] add JuliaFormatter using JuliaFormatter -format("src") +format(".") ``` ### Dependencies From 4faa97979e5317727ca9f3a3d8a85ddfa88f071d Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 5 Jun 2021 10:10:55 -0700 Subject: [PATCH 158/169] Add details on AbstractDataset potentially having multiple tables --- docs/src/considerations.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/src/considerations.md b/docs/src/considerations.md index a592cedf..f10fab48 100644 --- a/docs/src/considerations.md +++ b/docs/src/considerations.md @@ -93,4 +93,6 @@ In general, `read()` will return `Array{UInt8}`, and `imread()` will return `Arr The interface is implemented in [`src/tables.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/tables.jl). The current API from GDAL makes it row-based in the conventions of Tables.jl. Therefore, * `ArchGDAL.Feature` meets the criteria for an [`AbstractRow`](https://tables.juliadata.org/dev/#Tables.AbstractRow-1) based on https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/tables.jl#L31-L58. -* `ArchGDAL.FeatureLayer` meets the criteria for an `AbstractRow`-iterator based on the previous bullet and meeting the criteria for [`Iteration`](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) in https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/base/iterators.jl#L1-L18 +* `ArchGDAL.FeatureLayer` meets the criteria for an `AbstractRow`-iterator based on the previous bullet and meeting the criteria for [`Iteration`](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) in [`base/iterators.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/base/iterators.jl#L1-L18). +* `ArchGDAL.AbstractDataset` might contain multiple layers, and might correspond to multiple tables. The way to construct tables would be to get the layers before forming the corresponding tables. + From 2fd5aeec811f4abd159de4c4a818407914e4b9eb Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 5 Jun 2021 10:17:56 -0700 Subject: [PATCH 159/169] Add a note about (lack of) support for spatialite --- docs/make.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/make.jl b/docs/make.jl index 3492605f..1b07ba1d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -23,6 +23,8 @@ makedocs( "Tables Interface" => "tables.md", "Geometric Operations" => "geometries.md", "Spatial Projections" => "projections.md", + # TODO: Uncomment the following line once we support Spatialite + # See https://github.com/JuliaGeo/GDAL.jl/issues/65#issuecomment-493890448. # "Working with Spatialite" => "spatialite.md", "Interactive versus Scoped Objects" => "memory.md", "Design Considerations" => "considerations.md", From 26a8010f1e904bda8ce345792aac1d29297f5af5 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 5 Jun 2021 10:18:09 -0700 Subject: [PATCH 160/169] Add an instruction for starting julia --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bdc451cc..51c48344 100644 --- a/README.md +++ b/README.md @@ -57,18 +57,24 @@ To manage the dependencies of this package, we work with [environments](https:// 1. Navigate to the directory corresponding to the package: ```julia -shell> cd /Users/yeesian/.julia/dev/ArchGDAL +$ cd /Users/yeesian/.julia/dev/ArchGDAL /Users/yeesian/.julia/dev/ArchGDAL ``` -2. Activate the environment corresponding to `Project.toml`): +2. Start a session: + +```shell +$ julia --project +``` + +3. Activate the environment corresponding to `Project.toml`): ```julia (@v1.6) pkg> activate . Activating environment at `~/.julia/environments/v1.6/Project.toml` ``` -3. Manage the dependencies using Pkg in https://pkgdocs.julialang.org/v1.6/managing-packages/, e.g. +4. Manage the dependencies using Pkg in https://pkgdocs.julialang.org/v1.6/managing-packages/, e.g. ```julia (ArchGDAL) pkg> st @@ -92,7 +98,7 @@ shell> cd /Users/yeesian/.julia/dev/ArchGDAL [bd369af6] + Tables v1.4.2 ``` -4. Update the `[compat]` section of `Project.toml` so that julia can resolve the versions, e.g. +5. Update the `[compat]` section of `Project.toml` so that julia can resolve the versions, e.g. ``` [compat] From b53179d0d133d510a3427bc4cefb4a4b9003bbd9 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 5 Jun 2021 10:22:08 -0700 Subject: [PATCH 161/169] Add note that tables are only for OGR features and geometries --- docs/src/considerations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/considerations.md b/docs/src/considerations.md index f10fab48..8b9ab4e0 100644 --- a/docs/src/considerations.md +++ b/docs/src/considerations.md @@ -90,7 +90,7 @@ In general, `read()` will return `Array{UInt8}`, and `imread()` will return `Arr ## Tables.jl Interface -The interface is implemented in [`src/tables.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/tables.jl). The current API from GDAL makes it row-based in the conventions of Tables.jl. Therefore, +The interface is implemented in [`src/tables.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/master/src/tables.jl), and is only for feature and geometries in OGR (and not for images and rasters). The current API from GDAL makes it row-based in the conventions of Tables.jl. Therefore, * `ArchGDAL.Feature` meets the criteria for an [`AbstractRow`](https://tables.juliadata.org/dev/#Tables.AbstractRow-1) based on https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/tables.jl#L31-L58. * `ArchGDAL.FeatureLayer` meets the criteria for an `AbstractRow`-iterator based on the previous bullet and meeting the criteria for [`Iteration`](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) in [`base/iterators.jl`](https://github.com/yeesian/ArchGDAL.jl/blob/a665f3407930b8221269f8949c246db022c3a85c/src/base/iterators.jl#L1-L18). From aecd4d89c1ef7e892e7e953001ff71913be18b24 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 5 Jun 2021 10:37:16 -0700 Subject: [PATCH 162/169] rewrite if-else to have a single return --- src/base/display.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index 6a0a4136..3ecfc6d2 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -1,9 +1,9 @@ function Base.show(io::IO, drv::Driver)::IO if drv.ptr == C_NULL print(io, "NULL Driver") - return io + else + print(io, "Driver: $(shortname(drv))/$(longname(drv))") end - print(io, "Driver: $(shortname(drv))/$(longname(drv))") return io end From c615a992d155209fd546ba447aab7333c8570374 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sat, 5 Jun 2021 11:01:37 -0700 Subject: [PATCH 163/169] Update show methods to return nothing --- src/base/display.jl | 78 ++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/base/display.jl b/src/base/display.jl index 3ecfc6d2..64b6e435 100644 --- a/src/base/display.jl +++ b/src/base/display.jl @@ -1,16 +1,16 @@ -function Base.show(io::IO, drv::Driver)::IO +function Base.show(io::IO, drv::Driver)::Nothing if drv.ptr == C_NULL print(io, "NULL Driver") else print(io, "Driver: $(shortname(drv))/$(longname(drv))") end - return io + return nothing end -function Base.show(io::IO, dataset::AbstractDataset)::IO +function Base.show(io::IO, dataset::AbstractDataset)::Nothing if dataset.ptr == C_NULL print(io, "NULL Dataset") - return io + return nothing end println(io, "GDAL Dataset ($(getdriver(dataset)))") println(io, "File(s): ") @@ -53,19 +53,19 @@ function Base.show(io::IO, dataset::AbstractDataset)::IO end end end - return io + return nothing end #Add method to avoid show from DiskArrays -Base.show(io::IO, raster::RasterDataset)::IO = show(io, raster.ds) +Base.show(io::IO, raster::RasterDataset)::Nothing = show(io, raster.ds) -Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::IO = +Base.show(io::IO, ::MIME"text/plain", raster::RasterDataset)::Nothing = show(io, raster.ds) -function summarize(io::IO, rasterband::AbstractRasterBand)::IO +function summarize(io::IO, rasterband::AbstractRasterBand)::Nothing if rasterband.ptr == C_NULL print(io, "NULL RasterBand") - return io + return nothing end access = accessflag(rasterband) color = getname(getcolorinterp(rasterband)) @@ -74,20 +74,20 @@ function summarize(io::IO, rasterband::AbstractRasterBand)::IO i = indexof(rasterband) pxtype = pixeltype(rasterband) println(io, "[$access] Band $i ($color): $xsize x $ysize ($pxtype)") - return io + return nothing end -Base.show(io::IO, rasterband::AbstractRasterBand)::IO = +Base.show(io::IO, rasterband::AbstractRasterBand)::Nothing = show(io, "text/plain", rasterband) function Base.show( io::IO, ::MIME"text/plain", rasterband::AbstractRasterBand, -)::IO +)::Nothing summarize(io, rasterband) if rasterband.ptr == C_NULL - return io + return nothing end (x, y) = blocksize(rasterband) sc = getscale(rasterband) @@ -103,14 +103,14 @@ function Base.show( print(io, "($(i - 1)) $(width(ovr_band))x$(height(ovr_band)) ") i % 3 == 0 && print(io, "\n ") end - return io + return nothing end # assumes that the layer is reset, and will reset it after display -function Base.show(io::IO, layer::AbstractFeatureLayer)::IO +function Base.show(io::IO, layer::AbstractFeatureLayer)::Nothing if layer.ptr == C_NULL print(io, "NULL FeatureLayer") - return io + return nothing end layergeomtype = getgeomtype(layer) println(io, "Layer: $(getname(layer))") @@ -169,13 +169,13 @@ function Base.show(io::IO, layer::AbstractFeatureLayer)::IO resetreading!(layer) end n > 5 && print(io, "...\n Number of Fields: $n") - return io + return nothing end -function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO +function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::Nothing if featuredefn.ptr == C_NULL print(io, "NULL FeatureDefn") - return io + return nothing end n = ngeom(featuredefn) ngeomdisplay = min(n, 3) @@ -192,31 +192,31 @@ function Base.show(io::IO, featuredefn::AbstractFeatureDefn)::IO println(io, " Field (index $(i - 1)): $fd") end n > 5 && print(io, "...\n Number of Fields: $n") - return io + return nothing end -function Base.show(io::IO, fd::AbstractFieldDefn)::IO +function Base.show(io::IO, fd::AbstractFieldDefn)::Nothing if fd.ptr == C_NULL print(io, "NULL FieldDefn") - return io + return nothing end print(io, "$(getname(fd)) ($(gettype(fd)))") - return io + return nothing end -function Base.show(io::IO, gfd::AbstractGeomFieldDefn)::IO +function Base.show(io::IO, gfd::AbstractGeomFieldDefn)::Nothing if gfd.ptr == C_NULL print(io, "NULL GeomFieldDefn") - return io + return nothing end print(io, "$(getname(gfd)) ($(gettype(gfd)))") - return io + return nothing end -function Base.show(io::IO, feature::Feature)::IO +function Base.show(io::IO, feature::Feature)::Nothing if feature.ptr == C_NULL print(io, "NULL Feature") - return io + return nothing end println(io, "Feature") n = ngeom(feature) @@ -232,13 +232,13 @@ function Base.show(io::IO, feature::Feature)::IO println(io, "$(getfield(feature, i - 1))") end n > 10 && print(io, "...\n Number of Fields: $n") - return io + return nothing end -function Base.show(io::IO, spref::AbstractSpatialRef)::IO +function Base.show(io::IO, spref::AbstractSpatialRef)::Nothing if spref.ptr == C_NULL print(io, "NULL Spatial Reference System") - return io + return nothing end projstr = toPROJ4(spref) if length(projstr) > 45 @@ -248,13 +248,13 @@ function Base.show(io::IO, spref::AbstractSpatialRef)::IO else print(io, "Spatial Reference System: $projstr") end - return io + return nothing end -function Base.show(io::IO, geom::AbstractGeometry)::IO +function Base.show(io::IO, geom::AbstractGeometry)::Nothing if geom.ptr == C_NULL print(io, "NULL Geometry") - return io + return nothing end compact = get(io, :compact, false) @@ -269,17 +269,17 @@ function Base.show(io::IO, geom::AbstractGeometry)::IO else print(io, "Geometry: $(getgeomtype(geom))") end - return io + return nothing end -function Base.show(io::IO, ct::ColorTable)::IO +function Base.show(io::IO, ct::ColorTable)::Nothing if ct.ptr == C_NULL print(io, "NULL ColorTable") - return io + return nothing end palette = paletteinterp(ct) print(io, "ColorTable[$palette]") - return io + return nothing end -Base.show(io::IO, ::MIME"text/plain", ct::ColorTable)::IO = show(io, ct) +Base.show(io::IO, ::MIME"text/plain", ct::ColorTable)::Nothing = show(io, ct) From fa7f005f60989648adae573415d00174b247814f Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 20 Jun 2021 14:18:07 -0400 Subject: [PATCH 164/169] run JuliaFormatter --- docs/make.jl | 7 ++++++- test/test_doctest.jl | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 1b07ba1d..664222fb 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,6 +1,11 @@ using Documenter, ArchGDAL -DocMeta.setdocmeta!(ArchGDAL, :DocTestSetup, :(using ArchGDAL, GDAL); recursive=true) +DocMeta.setdocmeta!( + ArchGDAL, + :DocTestSetup, + :(using ArchGDAL, GDAL); + recursive = true, +) # make sure you have run the tests before such that the test files are present makedocs( diff --git a/test/test_doctest.jl b/test/test_doctest.jl index c3524021..56f95aea 100644 --- a/test/test_doctest.jl +++ b/test/test_doctest.jl @@ -1,3 +1,8 @@ using Test, Documenter, ArchGDAL -DocMeta.setdocmeta!(ArchGDAL, :DocTestSetup, :(using ArchGDAL, GDAL); recursive=true) +DocMeta.setdocmeta!( + ArchGDAL, + :DocTestSetup, + :(using ArchGDAL, GDAL); + recursive = true, +) doctest(ArchGDAL) From 317272f99f8372203de67868b87eb2fb66f88bab Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Sun, 20 Jun 2021 17:30:01 -0400 Subject: [PATCH 165/169] Add support for GPI_RGB with GCI_PaletteIndex --- src/raster/colortable.jl | 42 ++++++ src/raster/images.jl | 269 +++++++++++++++------------------------ test/test_images.jl | 16 ++- 3 files changed, 155 insertions(+), 172 deletions(-) diff --git a/src/raster/colortable.jl b/src/raster/colortable.jl index 7b6bb0f3..260ffd95 100644 --- a/src/raster/colortable.jl +++ b/src/raster/colortable.jl @@ -36,3 +36,45 @@ palette interpretation enumeration value, usually `GPI_RGB`. """ paletteinterp(ct::ColorTable)::GDALPaletteInterp = GDAL.gdalgetpaletteinterpretation(ct.ptr) + +""" + getcolorentryasrgb(ct::ColorTable, i::Integer) + +Fetch a table entry in RGB format. + +In theory this method should support translation of color palettes in non-RGB +color spaces into RGB on the fly, but currently it only works on RGB color +tables. + +### Parameters +* `i` entry offset from zero to GetColorEntryCount()-1. + +### Returns +`true` on success, or `false` if the conversion isn't supported. +""" +function getcolorentryasrgb(ct::ColorTable, i::Integer)::GDAL.GDALColorEntry + colorentry = Ref{GDAL.GDALColorEntry}(GDAL.GDALColorEntry(0, 0, 0, 0)) + result = Bool(GDAL.gdalgetcolorentryasrgb(ct.ptr, i, colorentry)) + result || @warn("The conversion to RGB isn't supported.") + return colorentry[] +end + +""" + setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry) + +Set entry in color table. + +Note that the passed in color entry is copied, and no internal reference to it +is maintained. Also, the passed in entry must match the color interpretation of +the table to which it is being assigned. + +The table is grown as needed to hold the supplied offset. + +### Parameters +* `i` entry offset from `0` to `ncolorentry()-1`. +* `entry` value to assign to table. +""" +function setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry) + GDAL.gdalsetcolorentry(ct.ptr, i, Ref{GDAL.GDALColorEntry}(entry)) + return ct +end diff --git a/src/raster/images.jl b/src/raster/images.jl index 8d669586..98ebd81f 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -8,7 +8,11 @@ function imview(colortype::Type{<:ColorTypes.Colorant}, imgvalues...) ) end -function imview(gci::GDALColorInterp, imgvalues::AbstractMatrix) +function imview( + gci::GDALColorInterp, + imgvalues::AbstractMatrix; + colortable::ColorTable = ColorTable(C_NULL), +) return if gci == GCI_GrayIndex imview(ColorTypes.Gray, imgvalues) elseif gci == GCI_Undefined @@ -22,13 +26,47 @@ function imview(gci::GDALColorInterp, imgvalues::AbstractMatrix) elseif gci == GCI_BlueBand zerovalues = zeros(eltype(imgvalues), size(imgvalues)) imview(GPI_RGB, zerovalues, zerovalues, imgvalues) + elseif gci == GCI_PaletteIndex + if colortable.ptr == C_NULL + error( + """ + `imview` is only supported for `GCI_PaletteIndex` with non-null + colortables. + """, + ) + end + gpi = paletteinterp(colortable) + if gpi == GPI_Gray + imview(GPI_Gray, imgvalues) + elseif gpi == GPI_RGB + colorentries = GDAL.GDALColorEntry[ + getcolorentryasrgb(colortable, i - 1) for + i in 1:GDAL.gdalgetcolorentrycount(colortable.ptr) + ] + c1 = Matrix{UInt8}(undef, size(imgvalues)...) + c2 = Matrix{UInt8}(undef, size(imgvalues)...) + c3 = Matrix{UInt8}(undef, size(imgvalues)...) + c4 = Matrix{UInt8}(undef, size(imgvalues)...) + for i in eachindex(imgvalues) + c1[i] = UInt8(colorentries[imgvalues[i]+1].c1) + c2[i] = UInt8(colorentries[imgvalues[i]+1].c2) + c3[i] = UInt8(colorentries[imgvalues[i]+1].c3) + c4[i] = UInt8(colorentries[imgvalues[i]+1].c4) + end + imview(GPI_RGB, c1, c2, c3, c4) + else + error(""" + Unsupported GPI: $(paletteinterp(colortable)). Please file an + issue at https://github.com/yeesian/ArchGDAL.jl/issues if it + should be supported. + """) + end else - error( - """ - Unknown GCI: $gci. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. - """, - ) + error(""" + Unknown GCI: $gci. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be + supported. + """) end end @@ -36,12 +74,11 @@ function imview(gpi::GDALPaletteInterp, imgvalues::AbstractMatrix) return if gpi == GPI_Gray imview(ColorTypes.Gray, imgvalues) else - error( - """ - Unsupported GPI: $gpi. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. - """, - ) + error(""" + Unsupported GPI: $gpi. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be + supported. + """) end end @@ -56,12 +93,11 @@ function imview( elseif gpi == GPI_RGB imview(ColorTypes.RGB, c1, c2, c3) else - error( - """ - Unsupported GPI: $gpi. If it should be supported, please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. - """, - ) + error(""" + Unsupported GPI: $gpi. If it should be supported, please file an + issue at https://github.com/yeesian/ArchGDAL.jl/issues with the + desired output. + """) end end @@ -77,182 +113,79 @@ function imview( elseif gpi == GPI_RGB imview(ColorTypes.RGBA, c1, c2, c3, c4) else - error( - """ - Unsupported GPI: $gpi. If it should be supported, please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues with the desired output. - """, - ) + error(""" + Unsupported GPI: $gpi. If it should be supported, please file an + issue at https://github.com/yeesian/ArchGDAL.jl/issues with the + desired output. + """) end end -function imread( - colortype::Union{GDALPaletteInterp,GDALColorInterp}, - rb::AbstractRasterBand, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, -) - return imview(colortype, read(rb, xoffset, yoffset, xsize, ysize)) -end - function imread( colortype::Union{GDALPaletteInterp,GDALColorInterp}, dataset::AbstractDataset, i::Integer, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, + args..., ) - return imread( - colortype, - getband(dataset, i), - xoffset, - yoffset, - xsize, - ysize, - ) + return imread(colortype, getband(dataset, i), args...) end -function imread( - colortype::Union{GDALPaletteInterp,GDALColorInterp}, - rb::AbstractRasterBand, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, -) - return imview(colortype, read(rb, rows, cols)) +function imread(gpi::GDALPaletteInterp, rb::AbstractRasterBand, args...) + return imview(gpi, read(rb, args...)) end -function imread( - colortype::Union{GDALPaletteInterp,GDALColorInterp}, - dataset::AbstractDataset, - i::Integer, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, -) - return imread(colortype, getband(dataset, i), rows, cols) -end - -function imread( - colortype::Union{GDALPaletteInterp,GDALColorInterp}, - rb::AbstractRasterBand, -) - return imview(colortype, read(rb)) -end - -function imread( - colortype::Union{GDALPaletteInterp,GDALColorInterp}, - dataset::AbstractDataset, - i::Integer, -) - return imread(colortype, getband(dataset, i)) -end - -function imread( - rb::AbstractRasterBand, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, -) - return imview(getcolorinterp(rb), read(rb, xoffset, yoffset, xsize, ysize)) -end - -function imread( - dataset::AbstractDataset, - i::Integer, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, -) - return imread(getband(dataset, i), xoffset, yoffset, xsize, ysize) -end - -function imread( - rb::AbstractRasterBand, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, -) - return imview(getcolorinterp(rb), read(rb, rows, cols)) -end - -function imread( - dataset::AbstractDataset, - i::Integer, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, -) - return imread(getband(dataset, i), rows, cols) +function imread(gci::GDALColorInterp, rb::AbstractRasterBand, args...) + return getcolortable(rb) do colortable + return imview(gci, read(rb, args...), colortable = colortable) + end end -function imread(rb::AbstractRasterBand) - return imview(getcolorinterp(rb), read(rb)) +function imread(rb::AbstractRasterBand, args...) + return getcolortable(rb) do colortable + imview(getcolorinterp(rb), read(rb, args...), colortable = colortable) + end end -function imread(dataset::AbstractDataset, i::Integer) - return imread(getband(dataset, i)) +function imread(dataset::AbstractDataset, i::Integer, args...) + return imread(getband(dataset, i), args...) end -function _paletteindices(dataset::AbstractDataset, indices) +function _colorindices(dataset::AbstractDataset, indices) gci = unique( GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices], ) gciorder = sort(gci) - return if gciorder == [GCI_GrayIndex] - GPI_Gray, Tuple(indices[sortperm(gci)]) + colortype = if gciorder == [GCI_GrayIndex] + GCI_GrayIndex elseif gciorder == [GCI_PaletteIndex] - gpi = getcolortable(getband(dataset, indices[1])) do ct - return paletteinterp(ct) - end - gpi, Tuple(indices) + GCI_PaletteIndex elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand] - GPI_RGB, Tuple(indices[sortperm(gci)]) + GPI_RGB elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand] - GPI_RGB, Tuple(indices[sortperm(gci)]) + GPI_RGB else - error( - """ - Unknown GCI: $gciorder. Please file an issue at - https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported. - """, - ) + error(""" + Unknown GCI: $gciorder. Please file an issue at + https://github.com/yeesian/ArchGDAL.jl/issues if it should be + supported. + """) + end + return colortype, Tuple(indices[sortperm(gci)]) +end + +function imread(dataset::AbstractDataset, indices, args...) + colortype, idxs = _colorindices(dataset, indices) + return if colortype == GCI_PaletteIndex + getcolortable(getband(dataset, 1)) do colortable + return imview( + colortype, + (read(getband(dataset, i), args...) for i in idxs)..., + colortable = colortable, + ) + end + else + imview(colortype, (read(getband(dataset, i), args...) for i in idxs)...) end -end - -function imread( - dataset::AbstractDataset, - indices, - xoffset::Integer, - yoffset::Integer, - xsize::Integer, - ysize::Integer, -) - gpi, idxs = _paletteindices(dataset, indices) - return imview( - gpi, - ( - read(getband(dataset, i), xoffset, yoffset, xsize, ysize) for - i in idxs - )..., - ) -end - -function imread( - dataset::AbstractDataset, - indices, - rows::UnitRange{<:Integer}, - cols::UnitRange{<:Integer}, -) - gpi, idxs = _paletteindices(dataset, indices) - return imview(gpi, (read(getband(dataset, i), rows, cols) for i in idxs)...) -end - -function imread(dataset::AbstractDataset, indices) - gpi, idxs = _paletteindices(dataset, indices) - return imview(gpi, (read(getband(dataset, i)) for i in idxs)...) end imread(dataset::AbstractDataset) = imread(dataset, 1:nraster(dataset)) diff --git a/test/test_images.jl b/test/test_images.jl index d81faded..c52268d7 100644 --- a/test/test_images.jl +++ b/test/test_images.jl @@ -140,6 +140,11 @@ import ColorTypes AG.setcolorinterp!(AG.getband(dataset, 4), AG.GCI_PaletteIndex) AG.createcolortable(AG.GPI_RGB) do ct + AG.setcolorentry!( + ct, + typemax(UInt8), + GDAL.GDALColorEntry(0, 0, 0, 0), + ) AG.setcolortable!(AG.getband(dataset, 1), ct) AG.setcolortable!(AG.getband(dataset, 2), ct) AG.setcolortable!(AG.getband(dataset, 3), ct) @@ -148,12 +153,15 @@ import ColorTypes @test eltype(AG.imread(dataset)) == ColorTypes.RGBA{ImageCore.N0f8} AG.createcolortable(AG.GPI_Gray) do ct - AG.setcolortable!(AG.getband(dataset, 1), ct) - AG.setcolortable!(AG.getband(dataset, 2), ct) - AG.setcolortable!(AG.getband(dataset, 3), ct) + AG.setcolorentry!( + ct, + typemax(UInt8), + GDAL.GDALColorEntry(0, 0, 0, 0), + ) return AG.setcolortable!(AG.getband(dataset, 4), ct) end - @test eltype(AG.imread(dataset)) == ColorTypes.Gray{ImageCore.N0f8} + @test eltype(AG.imread(dataset, 4)) == + ColorTypes.Gray{ImageCore.N0f8} AG.createcolortable(AG.GPI_CMYK) do ct # CMYK not supported yet AG.setcolortable!(AG.getband(dataset, 1), ct) From 174e2d6f2e3c92597e3919e9d6b46b8064d952c2 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Mon, 21 Jun 2021 13:21:10 +1000 Subject: [PATCH 166/169] looser ImageCore and ColorTypes deps (#207) --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 0985d928..f86f75b4 100644 --- a/Project.toml +++ b/Project.toml @@ -16,11 +16,11 @@ ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" [compat] -ColorTypes = "0.11" +ColorTypes = "0.10, 0.11" DiskArrays = "0.2.4" GDAL = "1.1.3" GeoFormatTypes = "0.3" GeoInterface = "0.4, 0.5" -ImageCore = "0.9" +ImageCore = "0.8, 0.9" Tables = "1" julia = "1.3" From 800bf2c89bc418597f45eea50ee6cbb82b169730 Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 21 Jun 2021 00:36:58 -0400 Subject: [PATCH 167/169] Switch from `missing` to `nothing` This is for two reasons: 1. The nodata value isn't meant to be used as a "sentinel value" in the raster output. If ArchGDAL wants to provide a convenience function for returning `Array{Union{T, Missing}}`, the treatment of missing data should be based on the appropriate use of `getmaskband()` (https://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask for details). 2. Even if ArchGDAL does provide a convenience function for returning `Array{Union{T, Missing}}`, the proper place for using `missing` values is in the array being constructed, and not the value being returned from `getnodatavalue(band)`. --- src/raster/rasterband.jl | 8 ++++---- test/test_display.jl | 2 +- test/test_ospy_examples.jl | 4 ++-- test/test_rasterband.jl | 20 ++++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/raster/rasterband.jl b/src/raster/rasterband.jl index 4a5833e3..d31978db 100644 --- a/src/raster/rasterband.jl +++ b/src/raster/rasterband.jl @@ -176,15 +176,15 @@ end Fetch the no data value for this band. -If there is no out of data value, `missing` will be returned instead. The no +If there is no out of data value, `nothing` will be returned instead. The no data value for a band is generally a special marker value used to mark pixels that are not valid data. Such pixels should generally not be displayed, nor contribute to analysis operations. ### Returns -the nodata value for this band or `missing`. +the nodata value for this band or `nothing`. """ -function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Missing} +function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Nothing} # ### Parameters # * `pbSuccess` pointer to a boolean to use to indicate if a value is # actually associated with this layer. May be `NULL` (default). @@ -193,7 +193,7 @@ function getnodatavalue(band::AbstractRasterBand)::Union{Float64,Missing} return if Bool(hasnodatavalue[]) nodatavalue else - missing + nothing end end diff --git a/test/test_display.jl b/test/test_display.jl index ad4af648..3a995fea 100644 --- a/test/test_display.jl +++ b/test/test_display.jl @@ -68,7 +68,7 @@ const AG = ArchGDAL; @test sprint(print, AG.getband(dataset, 1)) == """ [GA_ReadOnly] Band 1 (Red): 2048 x 1024 (UInt8) - blocksize: 256×256, nodata: missing, units: 1.0px + 0.0 + blocksize: 256×256, nodata: nothing, units: 1.0px + 0.0 overviews: (0) 1024x512 (1) 512x256 (2) 256x128 (3) 128x64 (4) 64x32 (5) 32x16 (6) 16x8 """ diff --git a/test/test_ospy_examples.jl b/test/test_ospy_examples.jl index 0102134d..3913bb71 100644 --- a/test/test_ospy_examples.jl +++ b/test/test_ospy_examples.jl @@ -385,7 +385,7 @@ const AG = ArchGDAL; outband = AG.getband(outDS, 1) @test sprint(print, outband) == """ [GA_Update] Band 1 (Undefined): 5665 x 5033 (Float32) - blocksize: 5665×1, nodata: missing, units: 1.0px + 0.0 + blocksize: 5665×1, nodata: nothing, units: 1.0px + 0.0 overviews: """ AG.setnodatavalue!(outband, -99) # georeference the image and set the projection @@ -484,7 +484,7 @@ const AG = ArchGDAL; bandout = AG.getband(dsout, 1) @test sprint(print, bandout) == """ [GA_Update] Band 1 (Undefined): 4500 x 3000 (UInt8) - blocksize: 4500×1, nodata: missing, units: 1.0px + 0.0 + blocksize: 4500×1, nodata: nothing, units: 1.0px + 0.0 overviews: """ # set the geotransform and projection on the output diff --git a/test/test_rasterband.jl b/test/test_rasterband.jl index 83bfe780..059ba621 100644 --- a/test/test_rasterband.jl +++ b/test/test_rasterband.jl @@ -43,25 +43,25 @@ const AG = ArchGDAL; AG.setscale!(rb, 1) @test AG.getscale(rb) ≈ 1 - @test ismissing(AG.getnodatavalue(rb)) + @test isnothing(AG.getnodatavalue(rb)) AG.setnodatavalue!(rb, -100) @test AG.getnodatavalue(rb) ≈ -100 AG.deletenodatavalue!(rb) - @test ismissing(AG.getnodatavalue(rb)) + @test isnothing(AG.getnodatavalue(rb)) AG.copy(dataset) do dest destband = AG.getband(dest, 1) AG.copywholeraster!(rb, destband) @test sprint(print, destband) == """ [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: """ @test AG.noverview(destband) == 0 AG.buildoverviews!(dest, Cint[2, 4, 8]) @test AG.noverview(destband) == 3 @test sprint(print, destband) == """ [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: (0) 50x50 (1) 25x25 (2) 13x13 """ @test AG.getcolorinterp(destband) == AG.GCI_GrayIndex @@ -70,25 +70,25 @@ const AG = ArchGDAL; @test sprint(print, AG.sampleoverview(destband, 100)) == """ [GA_Update] Band 1 (Gray): 13 x 13 (UInt8) - blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 overviews: """ @test sprint(print, AG.sampleoverview(destband, 200)) == """ [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) - blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 overviews: """ @test sprint(print, AG.sampleoverview(destband, 500)) == """ [GA_Update] Band 1 (Gray): 25 x 25 (UInt8) - blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 overviews: """ AG.sampleoverview(destband, 1000) do result @test sprint(print, result) == """ [GA_Update] Band 1 (Gray): 50 x 50 (UInt8) - blocksize: 128×128, nodata: missing, units: 1.0px + 0.0 + blocksize: 128×128, nodata: nothing, units: 1.0px + 0.0 overviews: """ end @test sprint(print, AG.getmaskband(destband)) == """ [GA_ReadOnly] Band 0 (Undefined): 100 x 100 (UInt8) - blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: """ @test AG.maskflags(destband) == 1 @test AG.maskflaginfo(rb) == ( @@ -101,7 +101,7 @@ const AG = ArchGDAL; AG.getmaskband(destband) do maskband @test sprint(print, maskband) == """ [GA_Update] Band 1 (Gray): 100 x 100 (UInt8) - blocksize: 100×81, nodata: missing, units: 1.0px + 0.0 + blocksize: 100×81, nodata: nothing, units: 1.0px + 0.0 overviews: """ end @test AG.maskflags(destband) == 3 From 36c59698163177579a66f1c068fb8d55b9dd654c Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 21 Jun 2021 13:12:14 -0400 Subject: [PATCH 168/169] Return `nothing` rather than `missing` when no matching field is found --- src/ogr/feature.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 4d866380..2b4c225a 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -106,7 +106,7 @@ Fetch the field index given field name. * `name`: the name of the field to search for. ### Returns -the field index, or `missing` if no matching field is found. +the field index, or `nothing` if no matching field is found. ### Remarks This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. @@ -114,10 +114,10 @@ This is a cover for the `OGRFeatureDefn::GetFieldIndex()` method. function findfieldindex( feature::Feature, name::Union{AbstractString,Symbol}, -)::Union{Integer,Missing} +)::Union{Integer,Nothing} i = GDAL.ogr_f_getfieldindex(feature.ptr, name) return if i == -1 - missing + nothing else i end @@ -385,7 +385,7 @@ function getdefault(feature::Feature, i::Integer)::String return getdefault(getfielddefn(feature, i)) end -getfield(feature::Feature, i::Missing)::Missing = missing +getfield(feature::Feature, i::Nothing)::Missing = missing function getfield(feature::Feature, i::Integer) _FETCHFIELD = Dict{OGRFieldType,Function}( From eedf3d499cb29756ce3fd3c9525834092f9521ce Mon Sep 17 00:00:00 2001 From: Yeesian Ng Date: Mon, 21 Jun 2021 13:12:38 -0400 Subject: [PATCH 169/169] formatting --- src/raster/images.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/raster/images.jl b/src/raster/images.jl index 98ebd81f..c8ca69de 100644 --- a/src/raster/images.jl +++ b/src/raster/images.jl @@ -142,7 +142,11 @@ end function imread(rb::AbstractRasterBand, args...) return getcolortable(rb) do colortable - imview(getcolorinterp(rb), read(rb, args...), colortable = colortable) + return imview( + getcolorinterp(rb), + read(rb, args...), + colortable = colortable, + ) end end