Skip to content

Commit 898cac6

Browse files
yeesianfelixcremerzerefwaynerafaqz
authored
[Breaking] Maintain a closed environment of GDAL-compatible types (#179)
* ignore .DS_Store files * Return errors for unknown datatypes when looking up gdaltypes * bugfix for looking up julia datatypes when given a gdaldatatype * throw informative error message for unknown field types * Add instructions for managing dependencies * remove cenum dependency * [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. * [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 #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. * Update the types in the API to be based on julia types (rather than C-types or GDAL-types) * [Breaking change] Introduce types for wkbGeometryType * Encapsulate the tests in their own testsets for better organization of test error reports * Refactor src/types.jl (i) move constants into its own file (ii) use a macro for generating conversion methods between enums * annotate function signatures with return types * [Breaking] copywholeraster -> copywholeraster! It now returns the dataset that was copied into as the return type. * annotate with return types * [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. * [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. * Annotate with return types * 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. * Annotate with return types * tighten the return type * white spacing * use isnothing() * whitespacing * Array -> Vector * Introduce enums for WKBByteOrder * 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. * [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. * improve test coverage for drivers * Remove unnecessary imports of GDAL in the tests * Add tests for geotransforms And fix a bug with the implementation for `composegeotransform!()`. * whitespacing * [Breaking] Update implementation of GeoInterface.coordinates() Coordinate dimensions should now only return 2 or 3. * 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. * Implement a basetype() method * 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.) * Add tests for tables.jl * Add tests for rasterio!(...) Spotted an indexing bug and fixed it along the way. * Add tests for raster/array.jl * [Breaking] Remove untested method for addfielddefn() * Add tests for displays of different objects * Add test for unsafe_getgeom(feature) * Improve test coverage for raster/array.jl * add tests for tables.jl * add prefix * 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} ``` * Add support for displaying color tables * got missed in the previous commit * Delete obsolete function It has an alternative implementation below, which is exercised in the unit test. * Whitespacing * Add test for reproject in the case of a no-op * Add test for copywholeraster! * Add test for unsafe_getgeom(feature, name) * Add test for unsafe_copy(layer) * Add tests for cloning null geometries * Update the documentation for working with the tables interface * Update API reference for geotransfromations * Add README for building the documentation * Fix command for activating the environment * Update macro name to reflect its usage and provide a docstring * 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.) * Add the return keyword * Add support for YCbCr * [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) ``` * Add tests for uncovered methods of features Namely, * getgeom(feature) * getgeom(feature, i) * unsafe_getgeom(feature) * unsafe_getgeom(feature, i) * getstyletable(feature) * Add support for options in toJSON * Increase test coverage for NULL geometries * Add support for kwargs in lineargeom * [Breaking] Remove initialize!(stylemanager, feature) Use initialize!(stylemanager, getstylestring(feature)) instead. * Use summarize(io, rasterband) for NULL bands * remove obsolete comment * Update README.md * Add tests for raster attribute tables and color tables * Add tests for ColorTable <-> RAT * Add test for cloning raster attribute tables * 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 ] }" ``` * Add tests for conversion errors * Add test to exercise `macro ogrerr(code, message)` * Add test to exercise `macro cplerr(code, message)` * Add tests for imread * Add tests for axisorder when importing CRS * Add tests for CRS conversion * whitespacing * [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. * Replace tabs with spaces I didn't realize my text editor was using tabs earlier * 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. * Remove untested code for HSL * Test for error cases * Add test for gray colortable * Add test cases for NULL SpatialRefs * Add test for color relief * Add test for conversion error * Add test for displaying dataset with many feature layers * Use format from JuliaFormatter See the README of https://github.com/domluna/JuliaFormatter.jl * Add github workflow for running JuliaFormatter * Add format configurations * Add a format checker for PRs * Update the README with the style guide * 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. * Update README.md * tweak phrasing * Include Julialang in the statement of support * provide a README.md for the tests In particular, documenting how to work with data (if needed). * Fix the return type * fix format * Tweak README * Add functionality and documentation for raster images * Fix file formatting * Allow to use interactive Datasets in unsafe_gdal functions in utilities.jl * Replace Pkg.PlatformEngine --> Custom download & verify * Move importing of Downloads and SHA to remotefiles.jl * Add contributor's guide * Ran JuliaFormatter * Fix tables example * ArchGDAL.getgeomdefn -> getgeomdefn * 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 <[email protected]> * add compat entries for ColorTypes and ImageCore * Add badges * rearrange badges for color * fix for table geometry v.s. field ordering * Add conversion for geometries to wkbUnknown This is useful when constructing vectors of geometries of multiple types * ran JuliaFormatter * Revamp implementation of imread() to be on-par with read() Needs corresponding unit tests * Add tests for images * Ran JuliaFormatter * remove obsolete code * Fix the description for updating compatibility * 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 * Re-enable test for gdal warp * Use JuliaFormatter * Use links instead of URLs * Use `=== nothing` instead of isnothing() for performance See JuliaLang/julia#36444 for context. * Future-proof the url to use the latest 1.* version. * Use the project environment for the docs * Format test cases that take up too much vertical whitespace * Bugfix to write out the file before reading it. * Remove unnecessary `Table{T<:AbstractFeatureLayer}` type. FeatureLayers now implement the table interface without having to go through a Table wrapper type. * 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. * Tweak wording * format file * fix typo and use https where possible * use abstract input types and fix indentation for multiline strings * remove conventions.md * Return missing rather than -1 or nothing if no matching field is found. * Added discussion on tables interface Based on the thread in #179 (comment). * Add discussion of enum values between base enums and cenums Based on the discussion in #179 (comment). * 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. * Capture the discussion on colors and images * Ran juliaformatter * Add docstrings for enum conversions * annotate return types * Update test-specific dependencies Based on https://pkgdocs.julialang.org/v1/creating-packages/#Test-specific-dependencies-in-Julia-1.2-and-above. * Fix doc builds * ignore tif files * Be consistent in using module names as prefixes * add GDAL as dependency for docs * Update instructions for formatting code. * Add details on AbstractDataset potentially having multiple tables * Add a note about (lack of) support for spatialite * Add an instruction for starting julia * Add note that tables are only for OGR features and geometries * rewrite if-else to have a single return * Update show methods to return nothing * run JuliaFormatter * Add support for GPI_RGB with GCI_PaletteIndex * looser ImageCore and ColorTypes deps (#207) * 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)`. * Return `nothing` rather than `missing` when no matching field is found * formatting Co-authored-by: Felix Cremer <[email protected]> Co-authored-by: Aayush Joglekar <[email protected]> Co-authored-by: Rafael Schouten <[email protected]>
1 parent 6d67ee6 commit 898cac6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+9762
-5799
lines changed

.JuliaFormatter.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Configuration file for JuliaFormatter.jl
2+
# For more information, see: https://domluna.github.io/JuliaFormatter.jl/stable/config/
3+
4+
always_for_in = true
5+
always_use_return = true
6+
margin = 80
7+
remove_extra_newlines = true
8+
short_to_long_function_def = true

.github/workflows/format_pr.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: format-pr
2+
on:
3+
schedule:
4+
- cron: '0 0 * * *'
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- name: Install JuliaFormatter and format
11+
run: |
12+
julia -e 'import Pkg; Pkg.add("JuliaFormatter")'
13+
julia -e 'using JuliaFormatter; format(".")'
14+
15+
# https://github.com/marketplace/actions/create-pull-request
16+
# https://github.com/peter-evans/create-pull-request#reference-example
17+
- name: Create Pull Request
18+
id: cpr
19+
uses: peter-evans/create-pull-request@v3
20+
with:
21+
token: ${{ secrets.GITHUB_TOKEN }}
22+
commit-message: Format .jl files
23+
title: 'Automatic JuliaFormatter.jl run'
24+
branch: auto-juliaformatter-pr
25+
delete-branch: true
26+
labels: formatting, automated pr, no changelog
27+
- name: Check outputs
28+
run: |
29+
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
30+
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ test/gdalworkshop/
1212
test/ospy/
1313
test/pyrasterio/
1414
test/spatialite/
15+
.DS_Store
16+
Manifest.toml
17+
*.tif

Project.toml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,21 @@ desc = "A high level API for GDAL - Geospatial Data Abstraction Library"
66
version = "0.6.0"
77

88
[deps]
9+
ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
910
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
1011
DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3"
1112
GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a"
1213
GeoFormatTypes = "68eda718-8dee-11e9-39e7-89f7f65f511f"
1314
GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f"
15+
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
1416
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
1517

1618
[compat]
19+
ColorTypes = "0.10, 0.11"
1720
DiskArrays = "0.2.4"
1821
GDAL = "1.1.3"
1922
GeoFormatTypes = "0.3"
2023
GeoInterface = "0.4, 0.5"
24+
ImageCore = "0.8, 0.9"
2125
Tables = "1"
2226
julia = "1.3"
23-
24-
[extras]
25-
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
26-
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
27-
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
28-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
29-
30-
[targets]
31-
test = ["Dates", "Pkg", "Statistics", "Test"]

README.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
# ArchGDAL
22
[![CI](https://github.com/yeesian/ArchGDAL.jl/workflows/CI/badge.svg)](https://github.com/yeesian/ArchGDAL.jl/actions?query=workflow%3ACI)
33
[![Coverage Status](https://coveralls.io/repos/github/yeesian/ArchGDAL.jl/badge.svg?branch=master)](https://coveralls.io/github/yeesian/ArchGDAL.jl?branch=master)
4+
[![version](https://juliahub.com/docs/ArchGDAL/version.svg)](https://juliahub.com/ui/Packages/ArchGDAL/MCIiB)
45
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://yeesian.com/ArchGDAL.jl/stable)
56
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://yeesian.com/ArchGDAL.jl/dev)
7+
[![deps](https://juliahub.com/docs/ArchGDAL/deps.svg)](https://juliahub.com/ui/Packages/ArchGDAL/MCIiB?t=2)
8+
[![ColPrac: Contributor's Guide](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac)
69

710
[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.
811

9-
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.
12+
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.
1013

1114
## Principles (The Arch Way)
1215
(adapted from: https://wiki.archlinux.org/index.php/Arch_Linux#Principles)
@@ -29,3 +32,76 @@ To test if it is installed correctly,
2932
```julia
3033
pkg> test ArchGDAL
3134
```
35+
36+
## Getting Involved
37+
38+
### Community
39+
40+
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.
41+
42+
### Style Guide
43+
44+
ArchGDAL.jl uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) as
45+
an autoformatting tool, and uses the options in [`.JuliaFormatter.toml`](https://github.com/yeesian/ArchGDAL.jl/blob/master/.JuliaFormatter.toml).
46+
47+
If you wish to format code, `cd` to the ArchGDAL.jl directory, then run:
48+
```julia
49+
] add JuliaFormatter
50+
using JuliaFormatter
51+
format(".")
52+
```
53+
54+
### Dependencies
55+
To manage the dependencies of this package, we work with [environments](https://pkgdocs.julialang.org/v1/environments/):
56+
57+
1. Navigate to the directory corresponding to the package:
58+
59+
```julia
60+
$ cd /Users/yeesian/.julia/dev/ArchGDAL
61+
/Users/yeesian/.julia/dev/ArchGDAL
62+
```
63+
64+
2. Start a session:
65+
66+
```shell
67+
$ julia --project
68+
```
69+
70+
3. Activate the environment corresponding to `Project.toml`):
71+
72+
```julia
73+
(@v1.6) pkg> activate .
74+
Activating environment at `~/.julia/environments/v1.6/Project.toml`
75+
```
76+
77+
4. Manage the dependencies using Pkg in https://pkgdocs.julialang.org/v1.6/managing-packages/, e.g.
78+
79+
```julia
80+
(ArchGDAL) pkg> st
81+
Project ArchGDAL v0.6.0
82+
Status `~/.julia/dev/ArchGDAL/Project.toml`
83+
[3c3547ce] DiskArrays
84+
[add2ef01] GDAL
85+
[68eda718] GeoFormatTypes
86+
[cf35fbd7] GeoInterface
87+
[bd369af6] Tables
88+
[ade2ca70] Dates
89+
90+
(ArchGDAL) pkg> add CEnum
91+
Resolving package versions...
92+
Updating `~/.julia/dev/ArchGDAL/Project.toml`
93+
[fa961155] + CEnum v0.4.1
94+
[3c3547ce] + DiskArrays v0.2.7
95+
[add2ef01] + GDAL v1.2.1
96+
[68eda718] + GeoFormatTypes v0.3.0
97+
[cf35fbd7] + GeoInterface v0.5.5
98+
[bd369af6] + Tables v1.4.2
99+
```
100+
101+
5. Update the `[compat]` section of `Project.toml` so that julia can resolve the versions, e.g.
102+
103+
```
104+
[compat]
105+
...
106+
CEnum = "0.4"
107+
```

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
33
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
44
DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3"
55
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
6+
GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a"
67

78
[compat]
89
Documenter = "0.26.2"

docs/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# ArchGDAL.jl documentation
2+
3+
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:
4+
5+
```shell
6+
$ julia --project make.jl
7+
```
8+
9+
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.

docs/make.jl

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
using Documenter, ArchGDAL
22

3+
DocMeta.setdocmeta!(
4+
ArchGDAL,
5+
:DocTestSetup,
6+
:(using ArchGDAL, GDAL);
7+
recursive = true,
8+
)
9+
310
# make sure you have run the tests before such that the test files are present
411
makedocs(
512
modules = [ArchGDAL],
@@ -17,15 +24,17 @@ makedocs(
1724
"GDAL Datasets" => "datasets.md",
1825
"Feature Data" => "features.md",
1926
"Raster Data" => "rasters.md",
27+
"Working with Images" => "images.md",
2028
"Tables Interface" => "tables.md",
2129
"Geometric Operations" => "geometries.md",
2230
"Spatial Projections" => "projections.md",
31+
# TODO: Uncomment the following line once we support Spatialite
32+
# See https://github.com/JuliaGeo/GDAL.jl/issues/65#issuecomment-493890448.
2333
# "Working with Spatialite" => "spatialite.md",
2434
"Interactive versus Scoped Objects" => "memory.md",
2535
"Design Considerations" => "considerations.md",
2636
"API Reference" => "reference.md",
27-
# "Naming Conventions" => "conventions.md", # table between GDAL, GDAL.jl, and ArchGDAL.jl
28-
]
37+
],
2938
)
3039

3140
deploydocs(; repo = "github.com/yeesian/ArchGDAL.jl.git")

docs/src/considerations.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,84 @@ Here's a collection of references for developers who are interested:
1515
- [https://github.com/mapbox/rasterio/pull/665](https://github.com/mapbox/rasterio/pull/665)
1616
- [https://github.com/mapbox/rasterio/issues/875](https://github.com/mapbox/rasterio/issues/875)
1717
- [https://rasterio.readthedocs.io/en/latest/topics/configuration.html](https://rasterio.readthedocs.io/en/latest/topics/configuration.html)
18+
19+
## GDAL Enum Values
20+
21+
[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):
22+
23+
```julia
24+
import Base.|
25+
26+
for T in (GDALOpenFlag, FieldValidation)
27+
eval(quote
28+
|(x::$T, y::UInt8) = UInt8(x) | y
29+
|(x::UInt8, y::$T) = x | UInt8(y)
30+
|(x::$T, y::$T) = UInt8(x) | UInt8(y)
31+
end)
32+
end
33+
```
34+
35+
and
36+
37+
```julia
38+
function basetype(gt::OGRwkbGeometryType)::OGRwkbGeometryType
39+
wkbGeomType = convert(GDAL.OGRwkbGeometryType, gt)
40+
wkbGeomType &= (~0x80000000) # Remove 2.5D flag.
41+
wkbGeomType %= 1000 # Normalize Z, M, and ZM types.
42+
return GDAL.OGRwkbGeometryType(wkbGeomType)
43+
end
44+
```
45+
46+
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:
47+
48+
```julia
49+
julia> Dict(GDAL.GCI_YCbCr_CrBand => "a", GDAL.GCI_Max => "b")
50+
Dict{GDAL.GDALColorInterp, String} with 1 entry:
51+
GCI_YCbCr_CrBand => "b"
52+
```
53+
54+
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.
55+
56+
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:
57+
58+
59+
```julia
60+
julia> Dict(ArchGDAL.GCI_YCbCr_CrBand => "a", ArchGDAL.GCI_Max => "b")
61+
Dict{ArchGDAL.GDALColorInterp, String} with 2 entries:
62+
GCI_YCbCr_CrBand => "a"
63+
GCI_Max => "b"
64+
```
65+
66+
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.
67+
68+
## Colors
69+
70+
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)
71+
72+
```julia
73+
range(startcolor, stop=endcolor, length=15)
74+
```
75+
76+
instead of
77+
78+
```julia
79+
createcolorramp!(colortable, startindex, startcolor, startindex+15, endcolor)
80+
```
81+
82+
## Images
83+
84+
To differentiate 2d arrays of colors from 3d arrays with band as the third dimension:
85+
86+
* 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".
87+
* 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.
88+
89+
In general, `read()` will return `Array{UInt8}`, and `imread()` will return `Array{<:Colorant}`.
90+
91+
## Tables.jl Interface
92+
93+
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,
94+
95+
* `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.
96+
* `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).
97+
* `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.
98+

docs/src/conventions.md

Whitespace-only changes.

0 commit comments

Comments
 (0)