swedishgrid 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +46 -0
- data/Rakefile +55 -0
- data/VERSION.yml +4 -0
- data/lib/swedishgrid.rb +112 -0
- data/test/swedishgrid_test.rb +67 -0
- data/test/test_helper.rb +9 -0
- metadata +55 -0
data/README.rdoc
ADDED
@@ -0,0 +1,46 @@
|
|
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
|
+
== SYNOPSIS:
|
9
|
+
|
10
|
+
grid = SwedishGrid.new(:rt90)
|
11
|
+
grid.grid_to_geodetic(7453389.762, 1727060.905)
|
12
|
+
# Outputs => [67.0906813246069, 21.034750437141]
|
13
|
+
|
14
|
+
== DEPENDENCIES:
|
15
|
+
|
16
|
+
No dependencies.
|
17
|
+
|
18
|
+
== INSTALL:
|
19
|
+
|
20
|
+
sudo gem install icehouse-swedishgrid
|
21
|
+
|
22
|
+
== LICENSE:
|
23
|
+
|
24
|
+
SwedishGrid is released under MIT license with permission from Arnold Andreasson.
|
25
|
+
Original Javascript-version written by Arnold Andreasson can be
|
26
|
+
found at: http://mellifica.se/geodesi/gausskruger.js
|
27
|
+
|
28
|
+
Copyright (c) 2009 ICE House
|
29
|
+
|
30
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
31
|
+
copy of this software and associated documentation files (the "Software"),
|
32
|
+
to deal in the Software without restriction, including without limitation
|
33
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
34
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
35
|
+
Software is furnished to do so, subject to the following conditions:
|
36
|
+
|
37
|
+
The above copyright notice and this permission notice shall be included
|
38
|
+
in all copies or substantial portions of the Software.
|
39
|
+
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
41
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
42
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
43
|
+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
44
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
45
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
46
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "swedishgrid"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "info@entanke.se"
|
10
|
+
gem.homepage = "http://github.com/icehouse/swedishgrid"
|
11
|
+
gem.authors = ["Magnus Enarsson"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rake/testtask'
|
19
|
+
Rake::TestTask.new(:test) do |test|
|
20
|
+
test.libs << 'lib' << 'test'
|
21
|
+
test.pattern = 'test/**/*_test.rb'
|
22
|
+
test.verbose = true
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'rcov/rcovtask'
|
27
|
+
Rcov::RcovTask.new do |test|
|
28
|
+
test.libs << 'test'
|
29
|
+
test.pattern = 'test/**/*_test.rb'
|
30
|
+
test.verbose = true
|
31
|
+
end
|
32
|
+
rescue LoadError
|
33
|
+
task :rcov do
|
34
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
task :default => :test
|
40
|
+
|
41
|
+
require 'rake/rdoctask'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
if File.exist?('VERSION.yml')
|
44
|
+
config = YAML.load(File.read('VERSION.yml'))
|
45
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
46
|
+
else
|
47
|
+
version = ""
|
48
|
+
end
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "swedishgrid #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
55
|
+
|
data/VERSION.yml
ADDED
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,67 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestSwedishGrid < Test::Unit::TestCase
|
4
|
+
|
5
|
+
LAT_LNG_TOLERANCE = 1.0e-7
|
6
|
+
GRID_TOLERANCE = 0.001
|
7
|
+
|
8
|
+
def setup
|
9
|
+
# Points from dokument "Kontrollpunkter" at lantmateritet.se
|
10
|
+
# http://www.lantmateriet.se/upload/filer/kartor/geodesi_gps_och_detaljmatning/Transformationer/SWEREF99_RT90_Samband/kontrollpunkter.pdf
|
11
|
+
# http://latlong.mellifica.se/
|
12
|
+
# WGS 84 and SWEREF 99 are, in principle, interchangeable
|
13
|
+
|
14
|
+
@rt90 = [ [7453389.762, 1727060.905],
|
15
|
+
[7047738.415, 1522128.637],
|
16
|
+
[6671665.273, 1441843.186],
|
17
|
+
[6249111.351, 1380573.079] ]
|
18
|
+
|
19
|
+
@sweref99tm = [ [7454204.638, 761811.242],
|
20
|
+
[7046077.605, 562140.337],
|
21
|
+
[6669189.376, 486557.055],
|
22
|
+
[6246136.458, 430374.835] ]
|
23
|
+
|
24
|
+
@lat_lng = [ [67 + 5/60.0 + 26.452769/3600, 21 + 2/60.0 + 5.101575/3600],
|
25
|
+
[63 + 32/60.0 + 14.761735/3600, 16 + 14/60.0 + 59.594626/3600],
|
26
|
+
[60 + 9/60.0 + 33.882413/3600, 14 + 45/60.0 + 28.167152/3600],
|
27
|
+
[56 + 21/60.0 + 17.199245/3600, 13 + 52/60.0 + 23.754022/3600] ]
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def test_rt90_grid_to_geodetic
|
33
|
+
grid = SwedishGrid.new(:rt90)
|
34
|
+
(0..3).each do |i|
|
35
|
+
coord = grid.grid_to_geodetic(*@rt90[i])
|
36
|
+
assert (coord[0] - @lat_lng[i][0]).abs < LAT_LNG_TOLERANCE
|
37
|
+
assert (coord[1] - @lat_lng[i][1]).abs < LAT_LNG_TOLERANCE
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_rt90_geodetic_to_grid
|
42
|
+
grid = SwedishGrid.new(:rt90)
|
43
|
+
(0..3).each do |i|
|
44
|
+
coord = grid.geodetic_to_grid(*@lat_lng[i])
|
45
|
+
assert (coord[0] - @rt90[i][0]).abs < GRID_TOLERANCE
|
46
|
+
assert (coord[1] - @rt90[i][1]).abs < GRID_TOLERANCE
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_sweref99tm_grid_to_geodetic
|
51
|
+
grid = SwedishGrid.new(:sweref99tm)
|
52
|
+
(0..3).each do |i|
|
53
|
+
coord = grid.grid_to_geodetic(*@sweref99tm[i])
|
54
|
+
assert (coord[0] - @lat_lng[i][0]).abs < LAT_LNG_TOLERANCE
|
55
|
+
assert (coord[1] - @lat_lng[i][1]).abs < LAT_LNG_TOLERANCE
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_sweref99tm_geodetic_to_grid
|
60
|
+
grid = SwedishGrid.new(:sweref99tm)
|
61
|
+
(0..3).each do |i|
|
62
|
+
coord = grid.geodetic_to_grid(*@lat_lng[i])
|
63
|
+
assert (coord[0] - @sweref99tm[i][0]).abs < GRID_TOLERANCE
|
64
|
+
assert (coord[1] - @sweref99tm[i][1]).abs < GRID_TOLERANCE
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: swedishgrid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Magnus Enarsson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2009-05-05 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: magnus@icehouse.se
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README.rdoc
|
20
|
+
files:
|
21
|
+
- README.rdoc
|
22
|
+
- Rakefile
|
23
|
+
- VERSION.yml
|
24
|
+
- lib/swedishgrid.rb
|
25
|
+
- test/swedishgrid_test.rb
|
26
|
+
- test/test_helper.rb
|
27
|
+
homepage:
|
28
|
+
licenses: []
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options:
|
31
|
+
- --charset=UTF-8
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.8.24
|
49
|
+
signing_key:
|
50
|
+
specification_version: 2
|
51
|
+
summary: Convert coordinates between geodetic WGS84 and Swedish grid RT90 and SWEREF99
|
52
|
+
systems.
|
53
|
+
test_files:
|
54
|
+
- test/swedishgrid_test.rb
|
55
|
+
- test/test_helper.rb
|