icehouse-swedishgrid 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +3 -0
- data/Manifest.txt +5 -0
- data/README +28 -0
- data/lib/swedishgrid.rb +112 -0
- data/test/test_swedishgrid.rb +68 -0
- metadata +57 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
= swedishgrid
|
2
|
+
|
3
|
+
== DESCRIPTION:
|
4
|
+
|
5
|
+
Convert coordinates between geodetic WGS84 and Swedish grid RT90 and SWEREF99 systems.
|
6
|
+
Read more about Swedish grid systems at http://www.lantmateriet.se/templates/LMV_Page.aspx?id=5197
|
7
|
+
|
8
|
+
Original Javascript-version written by Arnold Andreasson can be found at: http://mellifica.se/geodesi/gausskruger.js
|
9
|
+
|
10
|
+
Rewritten in ruby by Magnus Enarsson at ICE House, 2009.
|
11
|
+
|
12
|
+
== SYNOPSIS:
|
13
|
+
|
14
|
+
grid = SwedishGrid.new(:rt90)
|
15
|
+
grid.grid_to_geodetic()
|
16
|
+
|
17
|
+
== DEPENDENCIES:
|
18
|
+
|
19
|
+
No dependencies.
|
20
|
+
|
21
|
+
== INSTALL:
|
22
|
+
|
23
|
+
sudo gem install icehouse-swedishgrid
|
24
|
+
|
25
|
+
== LICENSE:
|
26
|
+
|
27
|
+
http://creativecommons.org/licenses/by-nc-sa/3.0/
|
28
|
+
|
data/lib/swedishgrid.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
class SwedishGrid
|
2
|
+
|
3
|
+
def initialize(grid)
|
4
|
+
case grid
|
5
|
+
when :rt90
|
6
|
+
# rt90_2.5_gon_v
|
7
|
+
@axis = 6378137.0
|
8
|
+
@flattening = 1.0 / 298.257222101
|
9
|
+
@central_meridian = 15.806284529
|
10
|
+
@lat_of_origin = 0.0
|
11
|
+
@scale = 1.00000561024
|
12
|
+
@false_northing = -667.711
|
13
|
+
@false_easting = 1500064.274
|
14
|
+
when :sweref99tm
|
15
|
+
@axis = 6378137.0
|
16
|
+
@flattening = 1.0 / 298.257222101
|
17
|
+
@central_meridian = 15.00
|
18
|
+
@lat_of_origin = 0.0
|
19
|
+
@scale = 0.9996
|
20
|
+
@false_northing = 0.0
|
21
|
+
@false_easting = 500000.0
|
22
|
+
else
|
23
|
+
raise "Unknown grid"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Conversion from grid coordinates to geodetic coordinates.
|
28
|
+
def grid_to_geodetic(x, y)
|
29
|
+
# Prepare ellipsoid-based stuff.
|
30
|
+
e2 = @flattening * (2.0 - @flattening)
|
31
|
+
n = @flattening / (2.0 - @flattening)
|
32
|
+
a_roof = @axis / (1.0 + n) * (1.0 + n*n/4.0 + n*n*n*n/64.0)
|
33
|
+
delta1 = n/2.0 - 2.0*n*n/3.0 + 37.0*n*n*n/96.0 - n*n*n*n/360.0
|
34
|
+
delta2 = n*n/48.0 + n*n*n/15.0 - 437.0*n*n*n*n/1440.0
|
35
|
+
delta3 = 17.0*n*n*n/480.0 - 37*n*n*n*n/840.0
|
36
|
+
delta4 = 4397.0*n*n*n*n/161280.0
|
37
|
+
|
38
|
+
astar = e2 + e2*e2 + e2*e2*e2 + e2*e2*e2*e2
|
39
|
+
bstar = -(7.0*e2*e2 + 17.0*e2*e2*e2 + 30.0*e2*e2*e2*e2) / 6.0
|
40
|
+
cstar = (224.0*e2*e2*e2 + 889.0*e2*e2*e2*e2) / 120.0
|
41
|
+
dstar = -(4279.0*e2*e2*e2*e2) / 1260.0
|
42
|
+
|
43
|
+
# Convert.
|
44
|
+
deg_to_rad = Math::PI / 180
|
45
|
+
lambda_zero = @central_meridian * deg_to_rad
|
46
|
+
xi = (x - @false_northing) / (@scale * a_roof)
|
47
|
+
eta = (y - @false_easting) / (@scale * a_roof)
|
48
|
+
xi_prim = xi -
|
49
|
+
delta1*Math.sin(2.0*xi) * Math.cosh(2.0*eta) -
|
50
|
+
delta2*Math.sin(4.0*xi) * Math.cosh(4.0*eta) -
|
51
|
+
delta3*Math.sin(6.0*xi) * Math.cosh(6.0*eta) -
|
52
|
+
delta4*Math.sin(8.0*xi) * Math.cosh(8.0*eta)
|
53
|
+
eta_prim = eta -
|
54
|
+
delta1*Math.cos(2.0*xi) * Math.sinh(2.0*eta) -
|
55
|
+
delta2*Math.cos(4.0*xi) * Math.sinh(4.0*eta) -
|
56
|
+
delta3*Math.cos(6.0*xi) * Math.sinh(6.0*eta) -
|
57
|
+
delta4*Math.cos(8.0*xi) * Math.sinh(8.0*eta)
|
58
|
+
phi_star = Math.asin(Math.sin(xi_prim) / Math.cosh(eta_prim))
|
59
|
+
delta_lambda = Math.atan(Math.sinh(eta_prim) / Math.cos(xi_prim))
|
60
|
+
lng_radian = lambda_zero + delta_lambda
|
61
|
+
lat_radian = phi_star + Math.sin(phi_star) * Math.cos(phi_star) *
|
62
|
+
(astar +
|
63
|
+
bstar*(Math.sin(phi_star) ** 2) +
|
64
|
+
cstar*(Math.sin(phi_star) ** 4) +
|
65
|
+
dstar*(Math.sin(phi_star) ** 6))
|
66
|
+
return [lat_radian * 180.0 / Math::PI, lng_radian * 180.0 / Math::PI]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Conversion from geodetic coordinates to grid coordinates.
|
70
|
+
def geodetic_to_grid(latitude, longitude)
|
71
|
+
# Prepare ellipsoid-based stuff.
|
72
|
+
e2 = @flattening * (2.0 - @flattening)
|
73
|
+
n = @flattening / (2.0 - @flattening)
|
74
|
+
a_roof = @axis / (1.0 + n) * (1.0 + n*n/4.0 + n*n*n*n/64.0)
|
75
|
+
a = e2
|
76
|
+
b = (5.0*e2*e2 - e2*e2*e2) / 6.0
|
77
|
+
c = (104.0*e2*e2*e2 - 45.0*e2*e2*e2*e2) / 120.0
|
78
|
+
d = (1237.0*e2*e2*e2*e2) / 1260.0
|
79
|
+
beta1 = n/2.0 - 2.0*n*n/3.0 + 5.0*n*n*n/16.0 + 41.0*n*n*n*n/180.0
|
80
|
+
beta2 = 13.0*n*n/48.0 - 3.0*n*n*n/5.0 + 557.0*n*n*n*n/1440.0
|
81
|
+
beta3 = 61.0*n*n*n/240.0 - 103.0*n*n*n*n/140.0
|
82
|
+
beta4 = 49561.0*n*n*n*n/161280.0
|
83
|
+
|
84
|
+
# Convert.
|
85
|
+
deg_to_rad = Math::PI / 180.0
|
86
|
+
phi = latitude * deg_to_rad
|
87
|
+
lambda = longitude * deg_to_rad
|
88
|
+
lambda_zero = @central_meridian * deg_to_rad
|
89
|
+
|
90
|
+
phi_star = phi - Math.sin(phi) * Math.cos(phi) * (a +
|
91
|
+
b*(Math.sin(phi) ** 2) +
|
92
|
+
c*(Math.sin(phi) ** 4) +
|
93
|
+
d*(Math.sin(phi) ** 6))
|
94
|
+
delta_lambda = lambda - lambda_zero
|
95
|
+
xi_prim = Math.atan(Math.tan(phi_star) / Math.cos(delta_lambda))
|
96
|
+
eta_prim = Math.atanh(Math.cos(phi_star) * Math.sin(delta_lambda))
|
97
|
+
x = @scale * a_roof * (xi_prim +
|
98
|
+
beta1 * Math.sin(2.0*xi_prim) * Math.cosh(2.0*eta_prim) +
|
99
|
+
beta2 * Math.sin(4.0*xi_prim) * Math.cosh(4.0*eta_prim) +
|
100
|
+
beta3 * Math.sin(6.0*xi_prim) * Math.cosh(6.0*eta_prim) +
|
101
|
+
beta4 * Math.sin(8.0*xi_prim) * Math.cosh(8.0*eta_prim)) +
|
102
|
+
@false_northing
|
103
|
+
y = @scale * a_roof * (eta_prim +
|
104
|
+
beta1 * Math.cos(2.0*xi_prim) * Math.sinh(2.0*eta_prim) +
|
105
|
+
beta2 * Math.cos(4.0*xi_prim) * Math.sinh(4.0*eta_prim) +
|
106
|
+
beta3 * Math.cos(6.0*xi_prim) * Math.sinh(6.0*eta_prim) +
|
107
|
+
beta4 * Math.cos(8.0*xi_prim) * Math.sinh(8.0*eta_prim)) +
|
108
|
+
@false_easting
|
109
|
+
return [(x * 1000.0).round / 1000.0, (y * 1000.0).round / 1000.0]
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "swedishgrid"
|
3
|
+
|
4
|
+
class TestSwedishGrid < Test::Unit::TestCase
|
5
|
+
|
6
|
+
LAT_LNG_TOLERANCE = 1.0e-7
|
7
|
+
GRID_TOLERANCE = 0.001
|
8
|
+
|
9
|
+
def setup
|
10
|
+
# Points from dokument "Kontrollpunkter" at lantmateritet.se
|
11
|
+
# http://www.lantmateriet.se/upload/filer/kartor/geodesi_gps_och_detaljmatning/Transformationer/SWEREF99_RT90_Samband/kontrollpunkter.pdf
|
12
|
+
# http://latlong.mellifica.se/
|
13
|
+
# WGS 84 and SWEREF 99 are, in principle, interchangeable
|
14
|
+
|
15
|
+
@rt90 = [ [7453389.762, 1727060.905],
|
16
|
+
[7047738.415, 1522128.637],
|
17
|
+
[6671665.273, 1441843.186],
|
18
|
+
[6249111.351, 1380573.079] ]
|
19
|
+
|
20
|
+
@sweref99tm = [ [7454204.638, 761811.242],
|
21
|
+
[7046077.605, 562140.337],
|
22
|
+
[6669189.376, 486557.055],
|
23
|
+
[6246136.458, 430374.835] ]
|
24
|
+
|
25
|
+
@lat_lng = [ [67 + 5/60.0 + 26.452769/3600, 21 + 2/60.0 + 5.101575/3600],
|
26
|
+
[63 + 32/60.0 + 14.761735/3600, 16 + 14/60.0 + 59.594626/3600],
|
27
|
+
[60 + 9/60.0 + 33.882413/3600, 14 + 45/60.0 + 28.167152/3600],
|
28
|
+
[56 + 21/60.0 + 17.199245/3600, 13 + 52/60.0 + 23.754022/3600] ]
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def test_rt90_grid_to_geodetic
|
34
|
+
grid = SwedishGrid.new(:rt90)
|
35
|
+
(0..3).each do |i|
|
36
|
+
coord = grid.grid_to_geodetic(*@rt90[i])
|
37
|
+
assert (coord[0] - @lat_lng[i][0]).abs < LAT_LNG_TOLERANCE
|
38
|
+
assert (coord[1] - @lat_lng[i][1]).abs < LAT_LNG_TOLERANCE
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_rt90_geodetic_to_grid
|
43
|
+
grid = SwedishGrid.new(:rt90)
|
44
|
+
(0..3).each do |i|
|
45
|
+
coord = grid.geodetic_to_grid(*@lat_lng[i])
|
46
|
+
assert (coord[0] - @rt90[i][0]).abs < GRID_TOLERANCE
|
47
|
+
assert (coord[1] - @rt90[i][1]).abs < GRID_TOLERANCE
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_sweref99tm_grid_to_geodetic
|
52
|
+
grid = SwedishGrid.new(:sweref99tm)
|
53
|
+
(0..3).each do |i|
|
54
|
+
coord = grid.grid_to_geodetic(*@sweref99tm[i])
|
55
|
+
assert (coord[0] - @lat_lng[i][0]).abs < LAT_LNG_TOLERANCE
|
56
|
+
assert (coord[1] - @lat_lng[i][1]).abs < LAT_LNG_TOLERANCE
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_sweref99tm_geodetic_to_grid
|
61
|
+
grid = SwedishGrid.new(:sweref99tm)
|
62
|
+
(0..3).each do |i|
|
63
|
+
coord = grid.geodetic_to_grid(*@lat_lng[i])
|
64
|
+
assert (coord[0] - @sweref99tm[i][0]).abs < GRID_TOLERANCE
|
65
|
+
assert (coord[1] - @sweref99tm[i][1]).abs < GRID_TOLERANCE
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: icehouse-swedishgrid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Magnus Enarsson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-05 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Convert coordinates between geodetic WGS84 and Swedish grid RT90 and SWEREF99 systems.
|
17
|
+
email:
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- History.txt
|
26
|
+
- Manifest.txt
|
27
|
+
- README
|
28
|
+
- lib/swedishgrid.rb
|
29
|
+
- test/test_swedishgrid.rb
|
30
|
+
has_rdoc: false
|
31
|
+
homepage:
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: "0"
|
42
|
+
version:
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.2.0
|
53
|
+
signing_key:
|
54
|
+
specification_version: 2
|
55
|
+
summary: Grit is a Ruby library for extracting information from a git repository in an object oriented manner.
|
56
|
+
test_files: []
|
57
|
+
|