national_grid 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,160 @@
1
+ static const LatLonDegMinSec testETRSCoords[] = {
2
+
3
+ // OSTN02 test coordinates provided by OS
4
+
5
+ {.lat = {.deg = 53, .min = 46, .sec = L(44.796925), .westOrSouth = false},
6
+ .lon = {.deg = 3, .min = 2, .sec = L(25.637665), .westOrSouth = true }, .elevation = L(64.940)},
7
+ {.lat = {.deg = 51, .min = 25, .sec = L(39.170761), .westOrSouth = false},
8
+ .lon = {.deg = 2, .min = 32, .sec = L(38.674270), .westOrSouth = true }, .elevation = L(104.018)},
9
+ {.lat = {.deg = 58, .min = 30, .sec = L(56.173025), .westOrSouth = false},
10
+ .lon = {.deg = 6, .min = 15, .sec = L(39.292403), .westOrSouth = true }, .elevation = L(115.026)},
11
+ {.lat = {.deg = 54, .min = 53, .sec = L(43.524259), .westOrSouth = false},
12
+ .lon = {.deg = 2, .min = 56, .sec = L(17.798693), .westOrSouth = true }, .elevation = L(93.541)},
13
+ {.lat = {.deg = 51, .min = 51, .sec = L(32.072283), .westOrSouth = false},
14
+ .lon = {.deg = 4, .min = 18, .sec = L(30.689158), .westOrSouth = true }, .elevation = L(81.351)},
15
+ {.lat = {.deg = 51, .min = 53, .sec = L(39.718951), .westOrSouth = false},
16
+ .lon = {.deg = 0, .min = 53, .sec = L(50.075790), .westOrSouth = false}, .elevation = L(75.273)},
17
+ {.lat = {.deg = 53, .min = 20, .sec = L(41.290104), .westOrSouth = false},
18
+ .lon = {.deg = 2, .min = 38, .sec = L(25.775546), .westOrSouth = true }, .elevation = L(88.411)},
19
+ {.lat = {.deg = 52, .min = 15, .sec = L(19.057739), .westOrSouth = false},
20
+ .lon = {.deg = 2, .min = 9, .sec = L(16.510138), .westOrSouth = true }, .elevation = L(101.526)},
21
+ {.lat = {.deg = 55, .min = 55, .sec = L(29.217549), .westOrSouth = false},
22
+ .lon = {.deg = 3, .min = 17, .sec = L(41.251876), .westOrSouth = true }, .elevation = L(119.032)},
23
+ {.lat = {.deg = 54, .min = 7, .sec = L(0.665196), .westOrSouth = false},
24
+ .lon = {.deg = 0, .min = 4, .sec = L(39.832776), .westOrSouth = true }, .elevation = L(86.778)},
25
+ {.lat = {.deg = 57, .min = 8, .sec = L(20.490695), .westOrSouth = false},
26
+ .lon = {.deg = 2, .min = 2, .sec = L(54.817138), .westOrSouth = true }, .elevation = L(108.610)},
27
+ {.lat = {.deg = 55, .min = 51, .sec = L(14.398307), .westOrSouth = false},
28
+ .lon = {.deg = 4, .min = 17, .sec = L(47.364560), .westOrSouth = true }, .elevation = L(71.617)},
29
+ {.lat = {.deg = 57, .min = 29, .sec = L(10.500012), .westOrSouth = false},
30
+ .lon = {.deg = 4, .min = 13, .sec = L(9.350362), .westOrSouth = true }, .elevation = L(66.178)},
31
+ {.lat = {.deg = 54, .min = 19, .sec = L(45.103478), .westOrSouth = false},
32
+ .lon = {.deg = 4, .min = 23, .sec = L(18.568248), .westOrSouth = true }, .elevation = L(94.503)},
33
+ {.lat = {.deg = 54, .min = 5, .sec = L(11.987451), .westOrSouth = false},
34
+ .lon = {.deg = 4, .min = 38, .sec = L(4.278066), .westOrSouth = true }, .elevation = L(84.366)},
35
+ {.lat = {.deg = 52, .min = 45, .sec = L(4.920748), .westOrSouth = false},
36
+ .lon = {.deg = 0, .min = 24, .sec = L(5.527717), .westOrSouth = false}, .elevation = L(66.431)},
37
+ {.lat = {.deg = 53, .min = 48, .sec = L(0.774717), .westOrSouth = false},
38
+ .lon = {.deg = 1, .min = 39, .sec = L(49.650033), .westOrSouth = true }, .elevation = L(215.609)},
39
+ {.lat = {.deg = 49, .min = 57, .sec = L(36.220979), .westOrSouth = false},
40
+ .lon = {.deg = 5, .min = 12, .sec = L(10.965961), .westOrSouth = true }, .elevation = L(124.269)},
41
+ {.lat = {.deg = 51, .min = 29, .sec = L(21.716326), .westOrSouth = false},
42
+ .lon = {.deg = 0, .min = 7, .sec = L(11.732031), .westOrSouth = true }, .elevation = L(66.057)},
43
+ {.lat = {.deg = 53, .min = 24, .sec = L(58.626568), .westOrSouth = false},
44
+ .lon = {.deg = 4, .min = 17, .sec = L(21.050495), .westOrSouth = true }, .elevation = L(100.776)},
45
+ {.lat = {.deg = 53, .min = 24, .sec = L(58.713306), .westOrSouth = false},
46
+ .lon = {.deg = 4, .min = 17, .sec = L(21.040535), .westOrSouth = true }, .elevation = L(100.854)},
47
+ {.lat = {.deg = 57, .min = 0, .sec = L(21.841075), .westOrSouth = false},
48
+ .lon = {.deg = 5, .min = 49, .sec = L(42.120935), .westOrSouth = true }, .elevation = L(68.494)},
49
+ {.lat = {.deg = 51, .min = 24, .sec = L(2.815934), .westOrSouth = false},
50
+ .lon = {.deg = 3, .min = 33, .sec = L(4.620554), .westOrSouth = true }, .elevation = L(112.371)},
51
+ {.lat = {.deg = 54, .min = 58, .sec = L(44.841864), .westOrSouth = false},
52
+ .lon = {.deg = 1, .min = 36, .sec = L(59.676644), .westOrSouth = true }, .elevation = L(125.878)},
53
+ {.lat = {.deg = 51, .min = 22, .sec = L(28.092933), .westOrSouth = false},
54
+ .lon = {.deg = 1, .min = 26, .sec = L(40.370305), .westOrSouth = false}, .elevation = L(99.439)},
55
+ {.lat = {.deg = 52, .min = 15, .sec = L(5.794233), .westOrSouth = false},
56
+ .lon = {.deg = 0, .min = 54, .sec = L(44.962452), .westOrSouth = true }, .elevation = L(131.594)},
57
+ {.lat = {.deg = 52, .min = 57, .sec = L(43.887942), .westOrSouth = false},
58
+ .lon = {.deg = 1, .min = 11, .sec = L(50.915622), .westOrSouth = true }, .elevation = L(93.825)},
59
+ {.lat = {.deg = 50, .min = 55, .sec = L(52.605759), .westOrSouth = false},
60
+ .lon = {.deg = 1, .min = 27, .sec = L(1.851626), .westOrSouth = true }, .elevation = L(100.405)},
61
+ {.lat = {.deg = 50, .min = 26, .sec = L(19.889717), .westOrSouth = false},
62
+ .lon = {.deg = 4, .min = 6, .sec = L(31.124303), .westOrSouth = true }, .elevation = L(215.251)},
63
+ {.lat = {.deg = 50, .min = 34, .sec = L(32.291946), .westOrSouth = false},
64
+ .lon = {.deg = 1, .min = 17, .sec = L(52.161977), .westOrSouth = true }, .elevation = L(94.688)},
65
+ {.lat = {.deg = 59, .min = 51, .sec = L(14.756913), .westOrSouth = false},
66
+ .lon = {.deg = 1, .min = 16, .sec = L(29.528804), .westOrSouth = true }, .elevation = L(149.890)},
67
+ {.lat = {.deg = 58, .min = 34, .sec = L(52.336612), .westOrSouth = false},
68
+ .lon = {.deg = 3, .min = 43, .sec = L(34.716767), .westOrSouth = true }, .elevation = L(98.634)},
69
+ {.lat = {.deg = 49, .min = 55, .sec = L(20.150196), .westOrSouth = false},
70
+ .lon = {.deg = 6, .min = 17, .sec = L(59.199098), .westOrSouth = true }, .elevation = L(100.000)},
71
+ {.lat = {.deg = 53, .min = 20, .sec = L(49.312599), .westOrSouth = false},
72
+ .lon = {.deg = 4, .min = 51, .sec = L(3.503091), .westOrSouth = true }, .elevation = L(100.000)},
73
+ {.lat = {.deg = 56, .min = 10, .sec = L(31.115299), .westOrSouth = false},
74
+ .lon = {.deg = 2, .min = 22, .sec = L(31.048596), .westOrSouth = true }, .elevation = L(100.000)},
75
+ {.lat = {.deg = 57, .min = 48, .sec = L(48.666318), .westOrSouth = false},
76
+ .lon = {.deg = 8, .min = 34, .sec = L(42.760597), .westOrSouth = true }, .elevation = L(100.000)},
77
+ {.lat = {.deg = 58, .min = 12, .sec = L(45.440933), .westOrSouth = false},
78
+ .lon = {.deg = 7, .min = 35, .sec = L(33.200272), .westOrSouth = true }, .elevation = L(140.404)},
79
+ {.lat = {.deg = 59, .min = 5, .sec = L(48.178240), .westOrSouth = false},
80
+ .lon = {.deg = 5, .min = 49, .sec = L(40.776272), .westOrSouth = true }, .elevation = L(140.716)},
81
+ {.lat = {.deg = 59, .min = 5, .sec = L(36.061263), .westOrSouth = false},
82
+ .lon = {.deg = 4, .min = 25, .sec = L(3.276270), .westOrSouth = true }, .elevation = L(100.000)},
83
+ {.lat = {.deg = 60, .min = 7, .sec = L(59.091315), .westOrSouth = false},
84
+ .lon = {.deg = 2, .min = 4, .sec = L(25.781605), .westOrSouth = true }, .elevation = L(140.716)},
85
+ {.lat = {.deg = 59, .min = 32, .sec = L(4.948596), .westOrSouth = false},
86
+ .lon = {.deg = 1, .min = 37, .sec = L(30.610770), .westOrSouth = true }, .elevation = L(100.000)},
87
+ {.lat = {.deg = 59, .min = 2, .sec = L(14.779356), .westOrSouth = false},
88
+ .lon = {.deg = 3, .min = 12, .sec = L(52.344038), .westOrSouth = true }, .elevation = L(100.000)},
89
+ {.lat = {.deg = 58, .min = 43, .sec = L(8.173859), .westOrSouth = false},
90
+ .lon = {.deg = 3, .min = 4, .sec = L(26.133727), .westOrSouth = true }, .elevation = L(100.000)},
91
+ {.lat = {.deg = 58, .min = 43, .sec = L(15.898312), .westOrSouth = false},
92
+ .lon = {.deg = 3, .min = 8, .sec = L(16.378343), .westOrSouth = true }, .elevation = L(100.000)},
93
+
94
+ // extra (extreme) coords
95
+
96
+ {.lat = {.deg = 90, .min = 0, .sec = L(0.000000), .westOrSouth = false},
97
+ .lon = {.deg = 0, .min = 0, .sec = L(0.000000), .westOrSouth = false}, .elevation = L(100.000)}, // N pole
98
+ {.lat = {.deg = 90, .min = 0, .sec = L(0.000000), .westOrSouth = true },
99
+ .lon = {.deg = 0, .min = 0, .sec = L(0.000000), .westOrSouth = false}, .elevation = L(100.000)}, // S pole
100
+ {.lat = {.deg = 51, .min = 0, .sec = L(0.000000), .westOrSouth = true },
101
+ .lon = {.deg = 180, .min = 0, .sec = L(0.000000), .westOrSouth = false}, .elevation = L(100.000)}, // other side of world
102
+ {.lat = {.deg = 0, .min = 0, .sec = L(0.000000), .westOrSouth = false},
103
+ .lon = {.deg = 0, .min = 0, .sec = L(0.000000), .westOrSouth = false}, .elevation = L(100.000)}, // equator/Greenwich Meridian
104
+ };
105
+
106
+ static const EastingNorthing testOSGB36Coords[] = {
107
+
108
+ // these coordinates come either from the OSTN02 test files, or from one of the online OS conversion tools (marked '*')
109
+ // -- sometimes the elevations differ by 1mm, presumably because of rounding policies
110
+
111
+ {.e = L(331534.552), .n = L(431920.792), .elevation = L(12.636), .geoid = 1},
112
+ {.e = L(362269.979), .n = L(169978.688), .elevation = L(54.467), .geoid = 1},
113
+ {.e = L(151968.641), .n = L(966483.777), .elevation = L(58.836), .geoid = 4},
114
+ {.e = L(339921.133), .n = L(556034.759), .elevation = L(41.077), .geoid = 1},
115
+ {.e = L(241124.573), .n = L(220332.638), .elevation = L(27.590), .geoid = 1},
116
+ {.e = L(599445.578), .n = L(225722.824), .elevation = L(30.192), .geoid = 1},
117
+ {.e = L(357455.831), .n = L(383290.434), .elevation = L(36.750), .geoid = 1},
118
+ {.e = L(389544.178), .n = L(261912.151), .elevation = L(51.977), .geoid = 1},
119
+ {.e = L(319188.423), .n = L(670947.532), .elevation = L(66.361), .geoid = 1}, // *
120
+ {.e = L(525745.658), .n = L(470703.211), .elevation = L(41.217), .geoid = 1},
121
+ {.e = L(397160.479), .n = L(805349.734), .elevation = L(58.902), .geoid = 1},
122
+ {.e = L(256340.914), .n = L(664697.266), .elevation = L(17.414), .geoid = 1},
123
+ {.e = L(267056.756), .n = L(846176.969), .elevation = L(13.230), .geoid = 1},
124
+ {.e = L(244780.625), .n = L(495254.884), .elevation = L(39.891), .geoid = 3},
125
+ {.e = L(227778.318), .n = L(468847.386), .elevation = L(29.335), .geoid = 3},
126
+ {.e = L(562180.535), .n = L(319784.993), .elevation = L(20.889), .geoid = 1}, // *
127
+ {.e = L(422242.174), .n = L(433818.699), .elevation = L(165.891), .geoid = 1},
128
+ {.e = L(170370.706), .n = L(11572.404), .elevation = L(71.223), .geoid = 1}, // *
129
+ {.e = L(530624.963), .n = L(178388.461), .elevation = L(20.518), .geoid = 1},
130
+ {.e = L(247958.959), .n = L(393492.906), .elevation = L(46.315), .geoid = 1}, // *
131
+ {.e = L(247959.229), .n = L(393495.580), .elevation = L(46.393), .geoid = 1},
132
+ {.e = L(167634.190), .n = L(797067.142), .elevation = L(13.190), .geoid = 1},
133
+ {.e = L(292184.858), .n = L(168003.462), .elevation = L(60.615), .geoid = 1},
134
+ {.e = L(424639.343), .n = L(565012.700), .elevation = L(76.551), .geoid = 1},
135
+ {.e = L(639821.823), .n = L(169565.856), .elevation = L(55.110), .geoid = 1},
136
+ {.e = L(474335.957), .n = L(262047.752), .elevation = L(83.961), .geoid = 1},
137
+ {.e = L(454002.822), .n = L(340834.941), .elevation = L(45.252), .geoid = 1}, // *
138
+ {.e = L(438710.908), .n = L(114792.248), .elevation = L(54.029), .geoid = 1},
139
+ {.e = L(250359.798), .n = L(62016.567), .elevation = L(163.081), .geoid = 1},
140
+ {.e = L(449816.359), .n = L(75335.859), .elevation = L(48.570), .geoid = 1}, // *
141
+ {.e = L(440725.061), .n = L(1107878.445), .elevation = L(100.992), .geoid = 6}, // *
142
+ {.e = L(299721.879), .n = L(967202.99), .elevation = L(46.011), .geoid = 1},
143
+ {.e = L(91492.135), .n = L(11318.801), .elevation = L(46.882), .geoid = 2},
144
+ {.e = L(0.000), .n = L(0.000), .elevation = L(0.000), .geoid = 0},
145
+ {.e = L(0.000), .n = L(0.000), .elevation = L(0.000), .geoid = 0},
146
+ {.e = L(9587.897), .n = L(899448.993), .elevation = L(43.424), .geoid = 5},
147
+ {.e = L(71713.120), .n = L(938516.401), .elevation = L(83.594), .geoid = 9},
148
+ {.e = L(180862.449), .n = L(1029604.111), .elevation = L(85.197), .geoid = 10},
149
+ {.e = L(261596.767), .n = L(1025447.599), .elevation = L(46.348), .geoid = 11}, // *
150
+ {.e = L(395999.656), .n = L(1138728.948), .elevation = L(89.901), .geoid = 12},
151
+ {.e = L(421300.513), .n = L(1072147.236), .elevation = L(50.951), .geoid = 8},
152
+ {.e = L(330398.311), .n = L(1017347.013), .elevation = L(47.978), .geoid = 7},
153
+ {.e = L(337898.195), .n = L(981746.359), .elevation = L(48.631), .geoid = 7},
154
+ {.e = L(334198.101), .n = L(982046.419), .elevation = L(48.439), .geoid = 1},
155
+
156
+ {.e = L(0.000), .n = L(0.000), .elevation = L(0.000), .geoid = 0},
157
+ {.e = L(0.000), .n = L(0.000), .elevation = L(0.000), .geoid = 0},
158
+ {.e = L(0.000), .n = L(0.000), .elevation = L(0.000), .geoid = 0},
159
+ {.e = L(0.000), .n = L(0.000), .elevation = L(0.000), .geoid = 0},
160
+ };
@@ -0,0 +1,165 @@
1
+ *This is a C implementation of Ordnance Survey's definitive transformation model "OSTN02":http://www.ordnancesurvey.co.uk/oswebsite/gps/osnetfreeservices/about/surveying_osnet.html#6 and Geoid model "OSGM02":http://www.ordnancesurvey.co.uk/oswebsite/gps/osnetfreeservices/about/surveying_osnet.html#7, with tests.*
2
+
3
+ It's intended to power a future update of my "GridPoint GB":http://mackerron.com/gridpointgb/ iOS app. It also includes a simple command-line tool.
4
+
5
+
6
+ h2. Licence
7
+
8
+ I'm releasing the code under the "MIT licence":http://www.opensource.org/licenses/mit-license.php (note, however, that OSTN02 and OSGM02 are trademarks of Ordnance Survey, and that the OSTN02 and OSGM02 data are © Crown copyright 2002. All rights reserved).
9
+
10
+
11
+ h2. Installing the command-line tool
12
+
13
+ h3. For Mac
14
+
15
+ You can "download a binary for Mac OS X 10.4+, Intel 32/64-bit":http://jawj.github.com/OSTN02C/ostn02c.bz2. You'll need to uncompress, @chmod +x@ and @mv@ this somewhere appropriate.
16
+
17
+ Alternatively, use "Homebrew":http://mxcl.github.com/homebrew/. In Terminal.app, type:
18
+
19
+ @brew install http://jawj.github.com/OSTN02C/ostn02c.rb@
20
+
21
+ h3. From source
22
+
23
+ Otherwise, with the relevant build tools installed -- Xcode on the Mac, @sudo aptitude install build-essential@ on Debian/Ubuntu, etc. -- download or clone the source to your machine, and compile like so:
24
+
25
+ @gcc OSTN02/*.c -std=gnu99 -D_GNU_SOURCE -lm -Wall -O2 -o ostn02c@
26
+
27
+ To compile with long double precision arithmetic (not recommended, since the outputs are the same to within 1mm), add the option @-DUSE_LONG@. To suppress fancy formatting (bold/inverse/underlined) in the tool's output, add the option @-DUNFANCY_OUTPUT@.
28
+
29
+
30
+ h2. Using the command-line tool
31
+
32
+ The command-line tool works like this:
33
+
34
+ bc.. dyn204:OSTN02 George$ ostn02c help
35
+
36
+ OSTN02C -- https://github.com/jawj/OSTN02C -- Built Feb 14 2012 11:53:48 (double precision)
37
+
38
+ This tool converts coordinates between ETRS89 (WGS84, GPS) lat/lon/elevation and OSGB36 easting/northing/elevation.
39
+ Conversions make use of Ordnance Survey's OSTN02 and OSGM02 transformations, and should thus be accurate to within 1m.
40
+
41
+ Usage: ostn02c gps-to-grid [lat lon elevation] converts ETRS89 to OSGB36
42
+ ostn02c grid-to-gps [easting northing elevation] converts OSGB36 to ETRS89
43
+ ostn02c list-geoids lists the geoid datum flags, names and regions
44
+ ostn02c test checks embedded data integrity and runs conversion tests with known coordinates
45
+ ostn02c help displays this message
46
+
47
+ The conversion commands gps-to-grid and grid-to-gps can be used in two ways:
48
+ * Given a set of coordinates as command-line arguments, they will convert this set with user-friendly output
49
+ * Given no command-line arguments, they will convert batches of coordinates, reading from STDIN and writing to STDOUT
50
+
51
+ In the batch conversion case:
52
+ * Input rows must have 3 columns -- lat or easting, lon or northing, elevation -- with any reasonable separator (,;:| \t)
53
+ * Output rows have 4 columns -- easting or lat, northing or lon, elevation, geoid datum flag -- separated with tabs
54
+ * In case of out-of-range input coordinates, all output columns will be zero
55
+ * Malformatted input terminates processing and results in a non-zero exit code
56
+
57
+ Software copyright (c) George MacKerron 2012 (http://mackerron.com)
58
+ Released under the MIT licence (http://www.opensource.org/licenses/mit-license.php)
59
+
60
+ OSTN02 and OSGM02 are trademarks of Ordnance Survey
61
+ Embedded OSTN02 and OSGM02 data (c) Crown copyright 2002. All rights reserved.
62
+
63
+
64
+ dyn204:OSTN02 George$ ostn02c gps-to-grid 51.0 -0.5 100.0
65
+
66
+ ETRS89 in lat: 51.000000, lon: -0.500000, elevation: 100.000
67
+ OSGB36 out E: 505349.663, N: 123360.984, elevation: 54.635 (UK mainland / Newlyn)
68
+
69
+
70
+ dyn204:OSTN02 George$ ostn02c grid-to-gps 505349.663 123360.984 54.635
71
+
72
+ OSGB36 in E: 505349.663, N: 123360.984, elevation: 54.635 (UK mainland / Newlyn)
73
+ ETRS89 out lat: 51.000000, lon: -0.500000, elevation: 100.000
74
+
75
+
76
+ dyn204:OSTN02 George$ echo "51.0, -0.5, 100.0
77
+ > 51.5, -1.0, 50.0" | ostn02c gps-to-grid
78
+ 505349.663 123360.984 54.635 1
79
+ 469509.184 178369.364 3.360 1
80
+
81
+ dyn204:OSTN02 George$ echo $?
82
+ 0
83
+
84
+
85
+ dyn204:OSTN02 George$ echo "51.0, -0.5, 100.0
86
+ > 20.0 40.0 0.0
87
+ > an invalid line
88
+ > 51.5, -1.0, 50.0" | ostn02c gps-to-grid
89
+ 505349.663 123360.984 54.635 1
90
+ 0.000 0.000 0.000 0
91
+
92
+ dyn204:OSTN02 George$ echo $?
93
+ 1
94
+
95
+
96
+ dyn204:OSTN02 George$ ostn02c list-geoids
97
+
98
+ Flag Datum Region
99
+ 0 N/A Outside model boundary
100
+ 1 Newlyn UK mainland
101
+ 2 St Marys Scilly Isles
102
+ 3 Douglas02 Isle of Man
103
+ 4 Stornoway Outer Hebrides
104
+ 5 St Kilda St Kilda
105
+ 6 Lerwick Shetland Isles
106
+ 7 Newlyn Orkney Isles
107
+ 8 Fair Isle Fair Isle
108
+ 9 Flannan Isles Flannan Isles
109
+ 10 North Rona North Rona
110
+ 11 Sule Skerry Sule Skerry
111
+ 12 Foula Foula
112
+ 13 Malin Head Republic of Ireland
113
+ 14 Belfast Northern Ireland
114
+
115
+
116
+ dyn204:OSTN02 George$ ostn02c test
117
+
118
+ Original CRC32 (data): 790474494
119
+ Computed CRC32 (data): 790474494
120
+
121
+ Original CRC32 (index): 244629328
122
+ Computed CRC32 (index): 244629328
123
+
124
+ ETRS89 actual lat: 53.779110, lon: -3.040455, elevation: 64.940
125
+ OSGB36 actual E: 331534.552, N: 431920.792, elevation: 12.636 (UK mainland / Newlyn)
126
+ ETRS89 computed lat: 53.779110, lon: -3.040455, elevation: 64.940
127
+ OSGB36 computed E: 331534.552, N: 431920.792, elevation: 12.636 (UK mainland / Newlyn)
128
+
129
+ ETRS89 actual lat: 51.427547, lon: -2.544076, elevation: 104.018
130
+ OSGB36 actual E: 362269.979, N: 169978.688, elevation: 54.467 (UK mainland / Newlyn)
131
+ ETRS89 computed lat: 51.427547, lon: -2.544076, elevation: 104.018
132
+ OSGB36 computed E: 362269.979, N: 169978.688, elevation: 54.467 (UK mainland / Newlyn)
133
+
134
+ [...]
135
+
136
+ ETRS89 actual lat: -51.000000, lon: 180.000000, elevation: 100.000
137
+ OSGB36 actual E: 0.000, N: 0.000, elevation: 0.000 (Outside model boundary / N/A)
138
+ OSGB36 computed E: 0.000, N: 0.000, elevation: 0.000 (Outside model boundary / N/A)
139
+
140
+ ETRS89 actual lat: 0.000000, lon: 0.000000, elevation: 100.000
141
+ OSGB36 actual E: 0.000, N: 0.000, elevation: 0.000 (Outside model boundary / N/A)
142
+ OSGB36 computed E: 0.000, N: 0.000, elevation: 0.000 (Outside model boundary / N/A)
143
+
144
+ 92 tests; 92 passed; 0 failed
145
+
146
+
147
+
148
+ h3. Output buffering
149
+
150
+ If you're using the command line tool from another script (e.g. from Ruby or Python), alternately writing coordinates to its STDIN and reading the converted results from its STDOUT, you'll need to ensure that your I/O isn't being buffered.
151
+
152
+ To help with this, the tool checks for an environment variable named OSTN02C_LINE_BUFFERED, and does buffering at line level only (i.e. output is flushed after every newline character) if it's set.
153
+
154
+ As an example, you can use this snippet to convert WGS84 to OSGB36 in Ruby:
155
+
156
+ bc. @ostn02 = IO.popen([{'OSTN02C_LINE_BUFFERED' => 'Y'}, 'ostn02c', 'gps-to-grid'], 'r+')
157
+ @ostn02.sync = true # this is actually the default on my system
158
+ def ll_to_en(lat, lon, elev)
159
+ @ostn02.puts "#{lat} #{lon} #{elev}"
160
+ osgb = @ostn02.gets.split("\t")
161
+ datum = osgb[3].to_i
162
+ return nil unless datum > 0
163
+ osgb[0..2].map(&:to_f)
164
+ end
165
+
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # this script processes the OSTN02/OSGM02 data in OS-supplied CSV format
5
+ # into a packed array of structs, and an index thereto
6
+
7
+ require 'CSV'
8
+ puts 'loading'
9
+ data = []
10
+ last_n = nil
11
+ CSV.foreach("OSTN02_OSGM02_GB.txt") do |csv_row|
12
+ e = csv_row[1].to_i / 1000
13
+ n = csv_row[2].to_i / 1000
14
+ dflag = csv_row[6].to_i
15
+ if dflag == 0
16
+ eshift = nshift = gshift = 0
17
+ else
18
+ # these offsets (-86000, 82000, -43000) minimise the number of bits required to store
19
+ eshift = csv_row[3].sub('.', '').to_i - 86000
20
+ nshift = csv_row[4].sub('.', '').to_i + 82000
21
+ gshift = csv_row[5].sub('.', '').to_i - 43000
22
+ end
23
+ if n != last_n
24
+ data.push([])
25
+ print n.to_s + ' '
26
+ end
27
+ data.last.push(e: e, n: n, dflag: dflag, eshift: eshift, nshift: nshift, gshift: gshift)
28
+ last_n = n
29
+ end
30
+
31
+ puts "\n\ntrimming"
32
+ data.each do |row|
33
+ print row[0][:n].to_s + ' '
34
+ first_non_zero_index = row.find_index { |cell| cell[:dflag] != 0 }
35
+ if first_non_zero_index.nil?
36
+ row.clear
37
+ next
38
+ end
39
+ row.slice!(0...first_non_zero_index)
40
+ last_non_zero_index = row.length - row.reverse_each.find_index { |cell| cell[:dflag] != 0 } # actually the index of the following zero
41
+ row.slice!(last_non_zero_index..row.length)
42
+ print row.length.to_s + ', '
43
+ end
44
+
45
+ c_notice = %{
46
+ // OSTN02/OSGM02 data (derived from OSTN02_OSGM02_GB.txt in http://www.ordnancesurvey.co.uk/oswebsite/gps/docs/OSTN02_OSGM02files.zip)
47
+ // © Crown copyright 2002. All rights reserved
48
+
49
+ }
50
+
51
+ puts "\n\nwriting"
52
+ indices_written = data_written = 0
53
+ File.open("shifts.index.data", "w") do |index_file|
54
+ index_file.puts(c_notice + 'static const OSTN02Index OSTN02Indices[] = {')
55
+ File.open("shifts.data", "w") do |data_file|
56
+ data_file.puts(c_notice + 'static const OSTN02Datum OSTN02Data[] = {')
57
+ data.each do |row|
58
+ print row.empty? ? '- ' : row[0][:n].to_s + ' '
59
+ emin = row.empty? ? 0 : row.first[:e]
60
+ index_file.write(indices_written == 0 ? ' ' : ',')
61
+ index_file.puts("{#{emin},#{row.length},#{data_written}}")
62
+ indices_written += 1
63
+ row.each do |cell|
64
+ data_file.write(data_written == 0 ? ' ' : ',')
65
+ data_file.puts("{#{cell[:eshift]},#{cell[:nshift]},#{cell[:gshift]},#{cell[:dflag]}}")
66
+ data_written += 1
67
+ end
68
+ end
69
+ data_file.puts('};')
70
+ end
71
+ index_file.puts('};')
72
+ end
@@ -1,3 +1,3 @@
1
1
  module NationalGrid
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -1,7 +1,31 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path("lib", __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require "national_grid/version"
4
4
 
5
+ module Files
6
+ module_function
7
+
8
+ def all
9
+ git_files + git_submodule_files
10
+ end
11
+
12
+ def git_files(dir = ".")
13
+ Dir.chdir File.expand_path(dir, __dir__) do
14
+ `git ls-files -z`.split("\x0")
15
+ end
16
+ end
17
+
18
+ def git_submodules
19
+ `git submodule -q foreach 'printf "$path\\0"'`.split("\x0")
20
+ end
21
+
22
+ def git_submodule_files
23
+ git_submodules.flat_map {|submodule|
24
+ git_files(submodule).map {|file| File.join(submodule, file)}
25
+ }
26
+ end
27
+ end
28
+
5
29
  Gem::Specification.new do |spec|
6
30
  spec.name = "national_grid"
7
31
  spec.version = NationalGrid::VERSION
@@ -11,7 +35,7 @@ Gem::Specification.new do |spec|
11
35
  spec.homepage = "https://github.com/haines/national_grid"
12
36
  spec.license = "MIT"
13
37
 
14
- spec.files = `git ls-files -z`.split("\x0")
38
+ spec.files = Files.all
15
39
  spec.test_files = spec.files.grep(%r{^test/})
16
40
  spec.require_paths = ["lib"]
17
41
  spec.extensions = ["ext/national_grid/extconf.rb"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: national_grid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Haines
@@ -90,6 +90,25 @@ files:
90
90
  - ext/national_grid/national_grid_latitude_longitude.c
91
91
  - ext/national_grid/national_grid_latitude_longitude.h
92
92
  - ext/ostn02c.rb
93
+ - ext/ostn02c/.gitignore
94
+ - ext/ostn02c/OSTN02.xcodeproj/project.pbxproj
95
+ - ext/ostn02c/OSTN02.xcodeproj/project.xcworkspace/contents.xcworkspacedata
96
+ - ext/ostn02c/OSTN02/OSTN02.c
97
+ - ext/ostn02c/OSTN02/OSTN02.h
98
+ - ext/ostn02c/OSTN02/constants.data
99
+ - ext/ostn02c/OSTN02/crc32.c
100
+ - ext/ostn02c/OSTN02/crc32.h
101
+ - ext/ostn02c/OSTN02/dblRelated.h
102
+ - ext/ostn02c/OSTN02/explorerMaps.data
103
+ - ext/ostn02c/OSTN02/fancyOut.h
104
+ - ext/ostn02c/OSTN02/geoids.data
105
+ - ext/ostn02c/OSTN02/gridRef.data
106
+ - ext/ostn02c/OSTN02/main.c
107
+ - ext/ostn02c/OSTN02/shifts.data
108
+ - ext/ostn02c/OSTN02/shifts.index.data
109
+ - ext/ostn02c/OSTN02/testCoords.data
110
+ - ext/ostn02c/README.textile
111
+ - ext/ostn02c/csv-to-struct-array.rb
93
112
  - lib/national_grid.rb
94
113
  - lib/national_grid/easting_northing.rb
95
114
  - lib/national_grid/inspect.rb