icehouse-swedishgrid 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|