Skip to content

Commit

Permalink
add src and update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
hydrocoast committed Feb 10, 2020
1 parent 7e651f9 commit de67731
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ os:
- linux
- osx
julia:
- 1.0
- 1.1
- 1.2
- 1.3
- nightly
matrix:
Expand Down
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# CoordinateConverterGK
# Coordinate conversion with the Gauss-Krüger Projection

[![Build Status](https://travis-ci.com/hydrocoast/CoordinateConverterGK.jl.svg?branch=master)](https://travis-ci.com/hydrocoast/CoordinateConverterGK.jl)
[![Codecov](https://codecov.io/gh/hydrocoast/CoordinateConverterGK.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/hydrocoast/CoordinateConverterGK.jl)
[![Coveralls](https://coveralls.io/repos/github/hydrocoast/CoordinateConverterGK.jl/badge.svg?branch=master)](https://coveralls.io/github/hydrocoast/CoordinateConverterGK.jl?branch=master)

<p align="center">
<img src="https://github.com/hydrocoast/CoordinateConverterGK.jl/blob/master/examples/samplefig.png", width="800">
</p>

## Overview
CoordinateConverterGK.jl is a Julia package for conversion between the Cartesian coordinates and the geographic coordinates for a point with the Gauss-Krüger Projection. The formulae are based on some documentations in websites of [the Geospatial Information Authority of Japan](https://www.gsi.go.jp/ENGLISH/index.html) and publications of this organization (see **References**).

## Installation
You can install the latest version using the built-in package manager (accessed by pressing `]` in the Julia REPL) to add the package.
```julia
pkg> add CoordinateConverterGK
```

## Usage
### General use
Given a central meridian `λ₀` and latitude of origin `φ₀`, Cartesian coordinates can be converted with the following code:
```julia
using CoordinateConverterGK
λ, φ = xy2lonlat(λ₀, φ₀, easting, northing)
```
where `λ` and `φ` are the converted longitude and latitude, `easting` and `northing` are the eastward and northward distances (in meter) from the origin, respectively.
A function `yx2latlon` is available in the same manner:
```julia
φ, λ = yx2latlon(φ₀, λ₀, northing, easting)
```
Similarly, functions `lonlat2xy` and `latlon2yx` can convert geographic coordinates to Cartesian coordinates for a point.
```julia
x, y = lonlat2xy(λ₀, φ₀, λ, φ)
```

### Japan Plane Rectangular Coordinate System
When the Japan Plane Rectangular Coordinate System is adopted,
functions such as `xy2lonlat_ja` and `lonlat2xy_ja` can omit the coordinates of origin `λ₀`, `φ₀`.
Instead, these functions require the zone number of interest (1 to 19).
```julia
λ, φ = xy2lonlat_ja(9, easting, northing) # in case of zone IX
```


## References
- Kawase, K. (2013) Concise Derivation of Extensive Coordinate Conversion Formulae in the Gauss-Krüger Projection, Bulletin of the Geospatial Information Authority of Japan, **60**, pp.1&ndash;6

- Kawase, K. (2011) A More Concise Method of Calculation for the Coordinate Conversion between Geographic and Plane Rectangular Coordinates on the Gauss-Krüger Projection (in Japanese), 国土地理院時報, **121**, pp.109&ndash;124.
Binary file added examples/samplefig.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 9 additions & 4 deletions src/CoordinateConverterGK.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
module CoordinateConverterGK

greet() = print("Hello World!")

end # module
include("defconstant.jl")
include("arclength.jl")
include("yx2latlon.jl")
include("latlon2yx.jl")
export yx2latlon, xy2lonlat
export yx2latlon_ja, xy2lonlat_ja
export latlon2yx, lonlat2xy
export latlon2yx_ja, lonlat2xy_ja
end
15 changes: 15 additions & 0 deletions src/arclength.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function arclength(φ₀) where T <: Float64
# A terms
Acoef = [ -3/2*[ 1.0 0.0 -1/8 0.0 -1/64]; # A₁
15/16*[ 0.0 1.0 0.0 -1/4 0.0]; # A₂
-35/48*[ 0.0 0.0 1.0 0.0 -5/16]; # A₃
[ 0.0 0.0 0.0 315/512 0.0]; # A₄
[ 0.0 0.0 0.0 0.0 -693/1280]; # A₅
]
Aj = Acoef * [n^k for k=1:5]

ΣA = sum([Aj[j]*sin(2j*φ₀) for j=1:5])
S̅φ₀ = (m₀*a)/(1+n) * (A₀*φ₀ + ΣA)

return S̅φ₀
end
30 changes: 30 additions & 0 deletions src/defconstant.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# constants
const a = 6.378137e6 # the semi-major axis of the earth
const F = 298.257222101 # the inverse 1st flattening
const n = 1/(2F-1)
const m₀ = 0.9999 # central meridian scale factor
A₀ = 1 + n^2/4 + n^4/64
const= A₀/(1+n) *m₀*a


## longitude, latitude of origin for zones in Japan
Origin_LatLon_Japan = [ 33.0 129.5 ; # 1
33.0 131.0 ; # 2
36.0 132.0+1/6; # 3
33.0 133.5 ; # 4
36.0 134.0+1/3; # 5
36.0 136.0 ; # 6
36.0 137.0+1/6; # 7
36.0 138.5 ; # 8
36.0 139.0+5/6; # 9
40.0 140.0+5/6; # 10
44.0 140.25 ; # 11
44.0 142.25 ; # 12
44.0 144.25 ; # 13
26.0 142.0 ; # 14
26.0 127.5 ; # 15
26.0 124.0 ; # 16
26.0 131.0 ; # 17
20.0 136.0 ; # 18
26.0 154.0 ; # 19
]
61 changes: 61 additions & 0 deletions src/latlon2yx.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
N, E = latlon2yx(φ₀::T, λ₀::T, φ::T, λ::T) where T <: Float64
Coordinate transformation between geographic and plane rectangular coordinates on the Gauss-Krüger Projection
This function is based on the following documents:
https://www.gsi.go.jp/common/000061216.pdf
https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/algorithm/xy2bl/xy2bl.htm
https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/algorithm/bl2xy/bl2xy.htm
### input arguments
- φ₀, λ₀ : latitude of origin and central meridian
- φ , λ : geographic latitude and longitude
### return values
- N, E : plane rectangular coordinates northing and easting
"""
function latlon2yx(φ₀::T, λ₀::T, φ::T, λ::T) where T <: Float64

φ₀ = deg2rad(φ₀)
λ₀ = deg2rad(λ₀)
φ = deg2rad(φ)
λ = deg2rad(λ)

S̅φ₀ = arclength(φ₀)

ncoef1 = 2sqrt(n)/(1+n)

t = sinh(atanh(sin(φ)) - ncoef1*atanh(ncoef1*sin(φ)))
= sqrt(1+t^2)
λc = cos-λ₀)
λs = sin-λ₀)
ξ′ = atan(t,λc)
η′ = atanh(λs/t̅)

# α terms
αcoef = [1/2 -2/3 5/16 41/180 -127/288; # α₁
0.0 13/48 -3/5 557/1440 281/630; # α₂
0.0 0.0 61/240 -103/140 15061/26880; # α₃
0.0 0.0 0.0 49561/161280 -179/168; # α₄
0.0 0.0 0.0 0.0 34729/80460; # α₅
]
αj = αcoef * [n^k for k=1:5]

N =*(ξ′ + sum([αj[j]sin(2j*ξ′)cosh(2j*η′) for j=1:5])) - S̅φ₀
E =*(η′ + sum([αj[j]cos(2j*ξ′)sinh(2j*η′) for j=1:5]))

return N, E
end
# -------------------------------------
lonlat2xy(λ₀::T, φ₀::T, λ::T, φ::T) where T <: Float64 = reverse(latlon2yx(φ₀, λ₀, φ, λ))

# -------------------------------------
function latlon2yx_ja(zone::Int, φ::T, λ::T) where T <: Float64
if !(0 < zone < 20)
error("system must be a integer from 1 to 19")
end
return latlon2yx(Origin_LatLon_Japan[zone,:]..., φ, λ)
end
# -------------------------------------
lonlat2xy_ja(zone::Int, λ::T, φ::T) where T <: Float64 = reverse(latlon2yx_ja(zone, φ, λ))
# -------------------------------------
74 changes: 74 additions & 0 deletions src/yx2latlon.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
φ , λ = yx2latlon(φ₀::T, λ₀::T, N::T, E::T) where T <: Float64
Coordinate transformation between geographic and plane rectangular coordinates on the Gauss-Krüger Projection
This function is based on the following documents:
https://www.gsi.go.jp/common/000061216.pdf
https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/algorithm/xy2bl/xy2bl.htm
https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/algorithm/bl2xy/bl2xy.htm
### input arguments
- φ₀, λ₀ : latitude of origin and central meridian
- N, E : plane rectangular coordinates northing and easting
### return values
- φ , λ : geographic latitude and longitude
"""
function yx2latlon(φ₀::T, λ₀::T, N::T, E::T) where T <: Float64

S̅φ₀ = arclength(deg2rad(φ₀))

# ξ and η
ξ = (N + S̅φ₀)/
η = E/


# β terms
βcoef = [1/2 -2/3 37/96 -1/360 -81/512; # β₁
0.0 1/48 1/15 -437/1440 46/105; # β₂
0.0 0.0 17/480 -37/840 -209/4480; # β₃
0.0 0.0 0.0 4397/161280 -11/504; # β₄
0.0 0.0 0.0 0.0 4583/161280; # β₅
]
βj = βcoef * [n^k for k=1:5]

ξ′ = ξ - sum([βj[j]sin(2j*ξ)cosh(2j*η) for j=1:5])
η′ = η - sum([βj[j]cos(2j*ξ)sinh(2j*η) for j=1:5])

# χ
χ = asin(sin(ξ′)/cosh(η′))

# δ terms
δcoef = [2.0 -2/3 -2.0 116/45 26/45 -2854/675; # δ₁
0.0 7/3 -8/5 -227/45 2704/315 2323/945; # δ₂
0.0 0.0 56/15 -136/35 -1262/105 73814/2835; # δ₃
0.0 0.0 0.0 4279/630 -332/35 -339572/14175; # δ₄
0.0 0.0 0.0 0.0 4174/315 -144838/6237; # δ₅
0.0 0.0 0.0 0.0 0.0 601676/22275; # δ₆
]
δj = δcoef * [n^k for k=1:6]

φ = rad2deg( χ + sum([δj[j]sin(2j*χ) for j=1:6]) )
λ = λ₀ + rad2deg( atan(sinh(η′),cos(ξ′)) )

#=
σ′ = 1 - sum([2j*βj[j]*cos(2j*ξ)*cosh(2j*η) for j=1:5])
τ′ = sum([2j*βj[j]*sin(2j*ξ)*sinh(2j*η) for j=1:5])
γ = atan(τ′+σ′*tan(ξ′)tanh(η′), σ′-τ′*tan(ξ′)tanh(η′))
m = m₀*A₀*(1/(1+n))*sqrt( (cos(ξ′)^2+sinh(η′)^2)/(σ′^2+τ′^2) * (1+((1-n)tan(φ)/(1+n))^2) )
=#

return φ, λ
end
# -------------------------------------
xy2lonlat(λ₀::T, φ₀::T, E::T, N::T) where T <: Float64 = reverse(yx2latlon(φ₀, λ₀, N, E))
# -------------------------------------
function yx2latlon_ja(zone::Int, N::T, E::T) where T <: Float64
if !(0 < zone < 20)
error("system must be a integer from 1 to 19")
end
return yx2latlon(Origin_LatLon_Japan[zone,:]..., N, E)
end
# -------------------------------------
xy2lonlat_ja(zone::Int, E::T, N::T) where T <: Float64 = reverse(yx2latlon_ja(zone, N, E))
# -------------------------------------
16 changes: 16 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,20 @@ using Test

@testset "CoordinateConverterGK.jl" begin
# Write your own tests here.

# xy to lonlat
northing = 11573.375
easting = 22694.980
φ, λ = yx2latlon_ja(9, northing, easting)
@test (abs- 36.10404755) < 1e-4) & (abs- 140.08539843) < 1e-4)

# lonlat to xy
lat = 36.103774791666666
lon = 140.08785504166664
y, x = latlon2yx_ja(9, lat, lon)
@test (abs(y - 11543.6883) < 1e-4) & (abs(x - 22916.2436) < 1e-4)

# args in reverse order
@test yx2latlon_ja(9, northing, easting) === reverse(xy2lonlat_ja(9, easting, northing))
@test latlon2yx_ja(9, lat, lon) === reverse(lonlat2xy_ja(9, lon, lat))
end

0 comments on commit de67731

Please sign in to comment.