Can Julia types and multiple dispatch be used to handle multiple coordinate systems transparently to the user?

Viewed 61

[What I am trying to do is somewhat akin to what unitful.jl does with units, but I haven't figured out a clean Julian way to do it.]

My program is dealing with a lot of 3D coordinates, but in multiple different reference frames. Some calculations are best done in certain reference frames. I'd like the user to not need to handle the conversions, but at the same time not have to write multiple versions of the functions to handle every combination of reference frames. Some functions have multiple inputs which can be in different reference frames, so this can explode combinatorially.

Here is a simplified view of what I have, which works, but requires multiple versions of every function.

struct ECEF
    v::StaticArrays.SVector{3, Float64}
end

struct GEODETIC
    v::StaticArrays.SVector{3, Float64}
end

function mymag(pt::ECEF)
    return √sum(pt.v .^2)
end

function mymag(pt::GEODETIC)
    return mymag(convert(ECEF,pt))
end

function convert(::Type{ECEF}, pt::GEODETIC)
    return ECEF(geodetic_to_ecef(pt.v...))
end

Ideally, I would like to be able to have things autoconverted, just like Unitful.js does. Thanks!

1 Answers

The easiest thing you can do is to use abstract types. In your case the code could look like this:

abstract type AbstractPoint3D end

struct ECEF <: AbstractPoint3D 
    v::StaticArrays.SVector{3, Float64}
end

struct GEODETIC <: AbstractPoint3D 
    v::StaticArrays.SVector{3, Float64}
end

function convert(::Type{ECEF}, pt::GEODETIC)
    return ECEF(geodetic_to_ecef(pt.v...))
end
convert(::Type{ECEF}, pt::ECEF) = pt

function mymag(pt::AbstractPoint3D)
    return √sum(convert(ECEF,pt).v .^2)
end

Related