Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Make EPSG a subset of some AgencyCode abstract type #35

Open
asinghvi17 opened this issue Jul 5, 2024 · 9 comments
Open

Make EPSG a subset of some AgencyCode abstract type #35

asinghvi17 opened this issue Jul 5, 2024 · 9 comments

Comments

@asinghvi17
Copy link
Member

asinghvi17 commented Jul 5, 2024

Motivation:

CRS can be addressed as eg ESRI:xyz or OGC:xyz as well, and such definitions exist online and in datasets. It would be useful to allow supporting arbitrary agencies (maybe with an error for unknown agencies) such that:

abstract type AgencyCodeCRS{AgencySymbol, NumTypes} end
const EPSG{N} = AgencyCodeCRS{:EPSG, N}
const EPSG = EPSG{1}

or something.

@rafaqz
Copy link
Member

rafaqz commented Jul 5, 2024

One problem is printing will be ugly

Can we just add OGC ?

@asinghvi17
Copy link
Member Author

You mean as another type? Sure, but we would have to implement all the converts in ArchGDAL too. An abstract supertype seems easier to extend, but the risk of typos also increases.

In terms of printing I think it should just print the alias?

@rafaqz
Copy link
Member

rafaqz commented Jul 5, 2024

Sorry guess I don't totally get your example, your EPSG is not concrete...

@asinghvi17
Copy link
Member Author

asinghvi17 commented Jul 6, 2024

Ah, I guess the AuthorityCRS should be a concrete type (changing terminology a bit):

struct AuthorityCRS{Authority, N} <: GFT.CoordinateReferenceSystemFormat
    val::NTuple{N,Int}
    function AuthorityCRS{Authority, N}(input::NTuple{N, Integer}) where {Authority, N}
        @assert Authority isa Symbol
        # maybe @assert Authority in (:EPSG, :OGC, :ESRI)
        return new{Authority, N}(input)
    end
end
AuthorityCRS{Authority}(input::NTuple{N,Integer}) where {Authority, N} = AuthorityCRS{Authority, N}(convert(NTuple{N,Int}, input))
AuthorityCRS{Authority}(input::Vararg{Integer}) where {Authority} = AuthorityCRS{Authority}(input)

AuthorityCRS(input::Vararg{Integer}) = AuthorityCRS{:EPSG}(input) # assume EPSG as the default
AuthorityCRS(authority::Symbol, input::NTuple{N,Integer}) where {N} = AuthorityCRS{authority, N}(convert(NTuple{N,Int}, input))

function AuthorityCRS{Authority}(input::AbstractString) where Authority
    startswith(input, String(Authority)) || throw(ArgumentError("String $(input) does not start with $(Authority)"))
    code = Tuple(parse.(Int, split(input[findlast(String(Authority), input).stop+2:end], "+")))
    AuthorityCRS{Authority}(code)
end

const EPSG{N} = AuthorityCRS{:EPSG, N}
const OGC{N} = AuthorityCRS{:OGC, N}
const ESRI{N} = AuthorityCRS{:ESRI, N}

With these definitions,

julia> EPSG(4326)
EPSG{1}((4326,))

julia> GFT.EPSG(4326)
GeoFormatTypes.EPSG{1}((4326,))

which is basically the same to me, just a bit more flexible maybe. Dispatch also works since the types are separated by a parameter.

@asinghvi17
Copy link
Member Author

Just edited that comment - this now has functionality fully equivalent to EPSG, just that adding OGC and ESRI was a 1-liner. Users can add their own authorities or personal databases as they desire, so long as they're expressed as symbols.

@rafaqz
Copy link
Member

rafaqz commented Jul 6, 2024

I still prefer struct OGC just for the stack trace brevity

@asinghvi17
Copy link
Member Author

I'll check but I think that the alias should work there too.

@asinghvi17
Copy link
Member Author

Injecting an error() at the last line of the string parsing function,

julia> EPSG("EPSG:4321")
ERROR: 
Stacktrace:
 [1] error()
   @ Base ./error.jl:44
 [2] (EPSG)(input::String)
   @ Main ~/.julia/dev/GeoMakie/examples/specialized/tyler_noninteractive.jl:50
 [3] top-level scope
   @ REPL[94]:1

and

julia> _beer(x::EPSG) = error()
julia> _beer(EPSG(1234))
ERROR: 
Stacktrace:
 [1] error()
   @ Base ./error.jl:44
 [2] _beer(x::EPSG{1})
   @ Main ~/.julia/dev/GeoMakie/examples/specialized/tyler_noninteractive.jl:54
 [3] top-level scope
   @ REPL[95]:1

@rafaqz
Copy link
Member

rafaqz commented Jul 6, 2024

Right. But I'm pretty sure there are places the alias fails

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

No branches or pull requests

2 participants