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.
- checksums.yaml +4 -4
- data/Rakefile +0 -6
- data/ext/national_grid/extconf.rb +2 -0
- data/ext/ostn02c.rb +7 -2
- data/ext/ostn02c/.gitignore +2 -0
- data/ext/ostn02c/OSTN02.xcodeproj/project.pbxproj +280 -0
- data/ext/ostn02c/OSTN02.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/ext/ostn02c/OSTN02/OSTN02.c +510 -0
- data/ext/ostn02c/OSTN02/OSTN02.h +107 -0
- data/ext/ostn02c/OSTN02/constants.data +35 -0
- data/ext/ostn02c/OSTN02/crc32.c +41 -0
- data/ext/ostn02c/OSTN02/crc32.h +9 -0
- data/ext/ostn02c/OSTN02/dblRelated.h +36 -0
- data/ext/ostn02c/OSTN02/explorerMaps.data +631 -0
- data/ext/ostn02c/OSTN02/fancyOut.h +28 -0
- data/ext/ostn02c/OSTN02/geoids.data +35 -0
- data/ext/ostn02c/OSTN02/gridRef.data +18 -0
- data/ext/ostn02c/OSTN02/main.c +151 -0
- data/ext/ostn02c/OSTN02/shifts.data +329044 -0
- data/ext/ostn02c/OSTN02/shifts.index.data +1257 -0
- data/ext/ostn02c/OSTN02/testCoords.data +160 -0
- data/ext/ostn02c/README.textile +165 -0
- data/ext/ostn02c/csv-to-struct-array.rb +72 -0
- data/lib/national_grid/version.rb +1 -1
- data/national_grid.gemspec +26 -2
- metadata +20 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f41ecc57f8f9a7908bd0a4c0850bea186060eb1
|
4
|
+
data.tar.gz: 3db89a1bb90c25dd163d8cb3aaca85e5173c6ad9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4f670c8624ce08e88170b9034625b2b6825a9084670d4743a5be1cfbd03acae012a7d9a9b50ce6730cfec87eca49f1323c1d9e20b2fc028c5509e08b23910d3
|
7
|
+
data.tar.gz: b6ad55bbbf7e5cf61a51af91d3b86ee93ebb6f95d30583b3a35811bc1a43fc2ede6b167bf929575ca16add6de57a0d1ae032567a97f9150a8fbd09911f846396
|
data/Rakefile
CHANGED
@@ -5,16 +5,10 @@ require_relative "ext/ostn02c"
|
|
5
5
|
|
6
6
|
CLEAN.include OSTN02C.object_path
|
7
7
|
|
8
|
-
file OSTN02C.library => OSTN02C.sources do
|
9
|
-
OSTN02C.make or fail "Building libostn02 failed"
|
10
|
-
end
|
11
|
-
|
12
8
|
Rake::ExtensionTask.new "national_grid" do |ext|
|
13
9
|
ext.lib_dir = "lib/national_grid"
|
14
10
|
end
|
15
11
|
|
16
|
-
Rake::Task["compile"].prerequisites.unshift FileList[OSTN02C.library]
|
17
|
-
|
18
12
|
Rake::TestTask.new "test" => "compile" do |test|
|
19
13
|
test.pattern = "test/**/*_test.rb"
|
20
14
|
end
|
@@ -3,6 +3,8 @@ require_relative "../ostn02c"
|
|
3
3
|
|
4
4
|
dir_config "ostn02c", [OSTN02C.include_path], [OSTN02C.lib_path]
|
5
5
|
|
6
|
+
OSTN02C.make or abort "building libostn02 failed"
|
7
|
+
|
6
8
|
abort "libostn02 not found" unless have_library "ostn02", "test(false)", "OSTN02.h"
|
7
9
|
|
8
10
|
create_makefile "national_grid/national_grid"
|
data/ext/ostn02c.rb
CHANGED
@@ -12,14 +12,14 @@ module OSTN02C
|
|
12
12
|
puts "Compiling libostn02"
|
13
13
|
FileUtils.mkdir_p object_path
|
14
14
|
Dir.chdir object_path do
|
15
|
-
|
15
|
+
run RbConfig.expand("$(CC) -I#{include_path} $(CPPFLAGS) $(CFLAGS) -c #{sources.join(" ")}")
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
def package
|
20
20
|
puts "Packaging libostn02"
|
21
21
|
FileUtils.mkdir_p lib_path
|
22
|
-
|
22
|
+
run RbConfig.expand("$(AR) -crsv #{library} #{objects}")
|
23
23
|
end
|
24
24
|
|
25
25
|
def sources
|
@@ -49,4 +49,9 @@ module OSTN02C
|
|
49
49
|
def output_path
|
50
50
|
File.expand_path("../tmp/ostn02c", __dir__)
|
51
51
|
end
|
52
|
+
|
53
|
+
def run(command)
|
54
|
+
puts command
|
55
|
+
system command
|
56
|
+
end
|
52
57
|
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
// !$*UTF8*$!
|
2
|
+
{
|
3
|
+
archiveVersion = 1;
|
4
|
+
classes = {
|
5
|
+
};
|
6
|
+
objectVersion = 46;
|
7
|
+
objects = {
|
8
|
+
|
9
|
+
/* Begin PBXBuildFile section */
|
10
|
+
5E2FEDCD14B35558007849B4 /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = 5E2FEDCC14B35558007849B4 /* crc32.c */; };
|
11
|
+
5EBE804514A5FE4800CA9D70 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 5EBE804414A5FE4800CA9D70 /* main.c */; };
|
12
|
+
5EBE804F14A5FE9000CA9D70 /* OSTN02.c in Sources */ = {isa = PBXBuildFile; fileRef = 5EBE804E14A5FE9000CA9D70 /* OSTN02.c */; };
|
13
|
+
/* End PBXBuildFile section */
|
14
|
+
|
15
|
+
/* Begin PBXCopyFilesBuildPhase section */
|
16
|
+
5EBE803E14A5FE4800CA9D70 /* CopyFiles */ = {
|
17
|
+
isa = PBXCopyFilesBuildPhase;
|
18
|
+
buildActionMask = 2147483647;
|
19
|
+
dstPath = /usr/share/man/man1/;
|
20
|
+
dstSubfolderSpec = 0;
|
21
|
+
files = (
|
22
|
+
);
|
23
|
+
runOnlyForDeploymentPostprocessing = 1;
|
24
|
+
};
|
25
|
+
/* End PBXCopyFilesBuildPhase section */
|
26
|
+
|
27
|
+
/* Begin PBXFileReference section */
|
28
|
+
5E2FEDCC14B35558007849B4 /* crc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc32.c; sourceTree = "<group>"; };
|
29
|
+
5E2FEDCE14B35570007849B4 /* crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc32.h; sourceTree = "<group>"; };
|
30
|
+
5E2FEDCF14B35DD4007849B4 /* testCoords.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testCoords.data; sourceTree = "<group>"; };
|
31
|
+
5E2FEDDA14B3641B007849B4 /* geoids.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = geoids.data; sourceTree = "<group>"; };
|
32
|
+
5E2FEDDD14B374AF007849B4 /* README.textile */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.textile; sourceTree = "<group>"; };
|
33
|
+
5E67D47B14B212FE00F5D4BC /* shifts.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = shifts.data; sourceTree = "<group>"; };
|
34
|
+
5E67D47C14B212FE00F5D4BC /* shifts.index.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = shifts.index.data; sourceTree = "<group>"; };
|
35
|
+
5E7AD48014B0D26E00AA6C99 /* csv-to-struct-array.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; path = "csv-to-struct-array.rb"; sourceTree = "<group>"; };
|
36
|
+
5E7BD21415B99A5F0003C1E5 /* explorerMaps.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = explorerMaps.data; sourceTree = "<group>"; };
|
37
|
+
5E9AFE1214F2525900F82BD7 /* fancyOut.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fancyOut.h; sourceTree = "<group>"; };
|
38
|
+
5E9AFE1414F2560D00F82BD7 /* dblRelated.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dblRelated.h; sourceTree = "<group>"; };
|
39
|
+
5EB2BE9D14B7593100EE7A5D /* gridRef.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = gridRef.data; sourceTree = "<group>"; };
|
40
|
+
5EBE804014A5FE4800CA9D70 /* ostn02c */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ostn02c; sourceTree = BUILT_PRODUCTS_DIR; };
|
41
|
+
5EBE804414A5FE4800CA9D70 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
|
42
|
+
5EBE804D14A5FE7300CA9D70 /* OSTN02.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSTN02.h; sourceTree = "<group>"; };
|
43
|
+
5EBE804E14A5FE9000CA9D70 /* OSTN02.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = OSTN02.c; sourceTree = "<group>"; };
|
44
|
+
5ECB2EE414B863F00015B28A /* constants.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = constants.data; sourceTree = "<group>"; };
|
45
|
+
/* End PBXFileReference section */
|
46
|
+
|
47
|
+
/* Begin PBXFrameworksBuildPhase section */
|
48
|
+
5EBE803D14A5FE4800CA9D70 /* Frameworks */ = {
|
49
|
+
isa = PBXFrameworksBuildPhase;
|
50
|
+
buildActionMask = 2147483647;
|
51
|
+
files = (
|
52
|
+
);
|
53
|
+
runOnlyForDeploymentPostprocessing = 0;
|
54
|
+
};
|
55
|
+
/* End PBXFrameworksBuildPhase section */
|
56
|
+
|
57
|
+
/* Begin PBXGroup section */
|
58
|
+
5E2FEDDC14B364D6007849B4 /* Data */ = {
|
59
|
+
isa = PBXGroup;
|
60
|
+
children = (
|
61
|
+
5E67D47B14B212FE00F5D4BC /* shifts.data */,
|
62
|
+
5E67D47C14B212FE00F5D4BC /* shifts.index.data */,
|
63
|
+
5E2FEDCF14B35DD4007849B4 /* testCoords.data */,
|
64
|
+
5E2FEDDA14B3641B007849B4 /* geoids.data */,
|
65
|
+
5EB2BE9D14B7593100EE7A5D /* gridRef.data */,
|
66
|
+
5ECB2EE414B863F00015B28A /* constants.data */,
|
67
|
+
5E7BD21415B99A5F0003C1E5 /* explorerMaps.data */,
|
68
|
+
);
|
69
|
+
name = Data;
|
70
|
+
path = OSTN02;
|
71
|
+
sourceTree = "<group>";
|
72
|
+
};
|
73
|
+
5EBE803514A5FE4800CA9D70 = {
|
74
|
+
isa = PBXGroup;
|
75
|
+
children = (
|
76
|
+
5E2FEDDD14B374AF007849B4 /* README.textile */,
|
77
|
+
5E7AD48014B0D26E00AA6C99 /* csv-to-struct-array.rb */,
|
78
|
+
5EBE804314A5FE4800CA9D70 /* Source code */,
|
79
|
+
5E2FEDDC14B364D6007849B4 /* Data */,
|
80
|
+
5EBE804114A5FE4800CA9D70 /* Products */,
|
81
|
+
);
|
82
|
+
sourceTree = "<group>";
|
83
|
+
};
|
84
|
+
5EBE804114A5FE4800CA9D70 /* Products */ = {
|
85
|
+
isa = PBXGroup;
|
86
|
+
children = (
|
87
|
+
5EBE804014A5FE4800CA9D70 /* ostn02c */,
|
88
|
+
);
|
89
|
+
name = Products;
|
90
|
+
sourceTree = "<group>";
|
91
|
+
};
|
92
|
+
5EBE804314A5FE4800CA9D70 /* Source code */ = {
|
93
|
+
isa = PBXGroup;
|
94
|
+
children = (
|
95
|
+
5EBE804D14A5FE7300CA9D70 /* OSTN02.h */,
|
96
|
+
5EBE804E14A5FE9000CA9D70 /* OSTN02.c */,
|
97
|
+
5E2FEDCC14B35558007849B4 /* crc32.c */,
|
98
|
+
5E2FEDCE14B35570007849B4 /* crc32.h */,
|
99
|
+
5EBE804414A5FE4800CA9D70 /* main.c */,
|
100
|
+
5E9AFE1214F2525900F82BD7 /* fancyOut.h */,
|
101
|
+
5E9AFE1414F2560D00F82BD7 /* dblRelated.h */,
|
102
|
+
);
|
103
|
+
name = "Source code";
|
104
|
+
path = OSTN02;
|
105
|
+
sourceTree = "<group>";
|
106
|
+
};
|
107
|
+
/* End PBXGroup section */
|
108
|
+
|
109
|
+
/* Begin PBXNativeTarget section */
|
110
|
+
5EBE803F14A5FE4800CA9D70 /* OSTN02 */ = {
|
111
|
+
isa = PBXNativeTarget;
|
112
|
+
buildConfigurationList = 5EBE804A14A5FE4900CA9D70 /* Build configuration list for PBXNativeTarget "OSTN02" */;
|
113
|
+
buildPhases = (
|
114
|
+
5EBE803C14A5FE4800CA9D70 /* Sources */,
|
115
|
+
5EBE803D14A5FE4800CA9D70 /* Frameworks */,
|
116
|
+
5EBE803E14A5FE4800CA9D70 /* CopyFiles */,
|
117
|
+
);
|
118
|
+
buildRules = (
|
119
|
+
);
|
120
|
+
dependencies = (
|
121
|
+
);
|
122
|
+
name = OSTN02;
|
123
|
+
productName = OSTN02;
|
124
|
+
productReference = 5EBE804014A5FE4800CA9D70 /* ostn02c */;
|
125
|
+
productType = "com.apple.product-type.tool";
|
126
|
+
};
|
127
|
+
/* End PBXNativeTarget section */
|
128
|
+
|
129
|
+
/* Begin PBXProject section */
|
130
|
+
5EBE803714A5FE4800CA9D70 /* Project object */ = {
|
131
|
+
isa = PBXProject;
|
132
|
+
attributes = {
|
133
|
+
LastUpgradeCheck = 0430;
|
134
|
+
ORGANIZATIONNAME = "George MacKerron";
|
135
|
+
};
|
136
|
+
buildConfigurationList = 5EBE803A14A5FE4800CA9D70 /* Build configuration list for PBXProject "OSTN02" */;
|
137
|
+
compatibilityVersion = "Xcode 3.2";
|
138
|
+
developmentRegion = English;
|
139
|
+
hasScannedForEncodings = 0;
|
140
|
+
knownRegions = (
|
141
|
+
en,
|
142
|
+
);
|
143
|
+
mainGroup = 5EBE803514A5FE4800CA9D70;
|
144
|
+
productRefGroup = 5EBE804114A5FE4800CA9D70 /* Products */;
|
145
|
+
projectDirPath = "";
|
146
|
+
projectRoot = "";
|
147
|
+
targets = (
|
148
|
+
5EBE803F14A5FE4800CA9D70 /* OSTN02 */,
|
149
|
+
);
|
150
|
+
};
|
151
|
+
/* End PBXProject section */
|
152
|
+
|
153
|
+
/* Begin PBXSourcesBuildPhase section */
|
154
|
+
5EBE803C14A5FE4800CA9D70 /* Sources */ = {
|
155
|
+
isa = PBXSourcesBuildPhase;
|
156
|
+
buildActionMask = 2147483647;
|
157
|
+
files = (
|
158
|
+
5EBE804514A5FE4800CA9D70 /* main.c in Sources */,
|
159
|
+
5EBE804F14A5FE9000CA9D70 /* OSTN02.c in Sources */,
|
160
|
+
5E2FEDCD14B35558007849B4 /* crc32.c in Sources */,
|
161
|
+
);
|
162
|
+
runOnlyForDeploymentPostprocessing = 0;
|
163
|
+
};
|
164
|
+
/* End PBXSourcesBuildPhase section */
|
165
|
+
|
166
|
+
/* Begin XCBuildConfiguration section */
|
167
|
+
5EBE804814A5FE4800CA9D70 /* Debug */ = {
|
168
|
+
isa = XCBuildConfiguration;
|
169
|
+
buildSettings = {
|
170
|
+
ALWAYS_SEARCH_USER_PATHS = NO;
|
171
|
+
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
172
|
+
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
173
|
+
COPY_PHASE_STRIP = NO;
|
174
|
+
GCC_C_LANGUAGE_STANDARD = gnu99;
|
175
|
+
GCC_DYNAMIC_NO_PIC = NO;
|
176
|
+
GCC_ENABLE_OBJC_EXCEPTIONS = NO;
|
177
|
+
GCC_OPTIMIZATION_LEVEL = 0;
|
178
|
+
GCC_PREPROCESSOR_DEFINITIONS = (
|
179
|
+
"DEBUG=1",
|
180
|
+
"$(inherited)",
|
181
|
+
);
|
182
|
+
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
183
|
+
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
184
|
+
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
185
|
+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
186
|
+
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
187
|
+
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
188
|
+
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
189
|
+
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
190
|
+
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
191
|
+
GCC_WARN_SHADOW = YES;
|
192
|
+
GCC_WARN_SIGN_COMPARE = YES;
|
193
|
+
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
194
|
+
GCC_WARN_UNUSED_FUNCTION = YES;
|
195
|
+
GCC_WARN_UNUSED_PARAMETER = YES;
|
196
|
+
GCC_WARN_UNUSED_VARIABLE = YES;
|
197
|
+
MACOSX_DEPLOYMENT_TARGET = 10.4;
|
198
|
+
ONLY_ACTIVE_ARCH = YES;
|
199
|
+
SDKROOT = macosx;
|
200
|
+
};
|
201
|
+
name = Debug;
|
202
|
+
};
|
203
|
+
5EBE804914A5FE4800CA9D70 /* Release */ = {
|
204
|
+
isa = XCBuildConfiguration;
|
205
|
+
buildSettings = {
|
206
|
+
ALWAYS_SEARCH_USER_PATHS = NO;
|
207
|
+
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
208
|
+
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
209
|
+
COPY_PHASE_STRIP = YES;
|
210
|
+
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
211
|
+
GCC_C_LANGUAGE_STANDARD = gnu99;
|
212
|
+
GCC_ENABLE_OBJC_EXCEPTIONS = NO;
|
213
|
+
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
214
|
+
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
215
|
+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
216
|
+
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
217
|
+
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
218
|
+
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
219
|
+
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
220
|
+
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
221
|
+
GCC_WARN_SHADOW = YES;
|
222
|
+
GCC_WARN_SIGN_COMPARE = YES;
|
223
|
+
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
224
|
+
GCC_WARN_UNUSED_FUNCTION = YES;
|
225
|
+
GCC_WARN_UNUSED_PARAMETER = YES;
|
226
|
+
GCC_WARN_UNUSED_VARIABLE = YES;
|
227
|
+
MACOSX_DEPLOYMENT_TARGET = 10.4;
|
228
|
+
RUN_CLANG_STATIC_ANALYZER = YES;
|
229
|
+
SDKROOT = macosx;
|
230
|
+
VALIDATE_PRODUCT = YES;
|
231
|
+
};
|
232
|
+
name = Release;
|
233
|
+
};
|
234
|
+
5EBE804B14A5FE4900CA9D70 /* Debug */ = {
|
235
|
+
isa = XCBuildConfiguration;
|
236
|
+
buildSettings = {
|
237
|
+
LIBRARY_SEARCH_PATHS = (
|
238
|
+
"$(inherited)",
|
239
|
+
"\"$(SDKROOT)/usr/lib/system\"",
|
240
|
+
);
|
241
|
+
PRODUCT_NAME = ostn02c;
|
242
|
+
};
|
243
|
+
name = Debug;
|
244
|
+
};
|
245
|
+
5EBE804C14A5FE4900CA9D70 /* Release */ = {
|
246
|
+
isa = XCBuildConfiguration;
|
247
|
+
buildSettings = {
|
248
|
+
LIBRARY_SEARCH_PATHS = (
|
249
|
+
"$(inherited)",
|
250
|
+
"\"$(SDKROOT)/usr/lib/system\"",
|
251
|
+
);
|
252
|
+
PRODUCT_NAME = ostn02c;
|
253
|
+
};
|
254
|
+
name = Release;
|
255
|
+
};
|
256
|
+
/* End XCBuildConfiguration section */
|
257
|
+
|
258
|
+
/* Begin XCConfigurationList section */
|
259
|
+
5EBE803A14A5FE4800CA9D70 /* Build configuration list for PBXProject "OSTN02" */ = {
|
260
|
+
isa = XCConfigurationList;
|
261
|
+
buildConfigurations = (
|
262
|
+
5EBE804814A5FE4800CA9D70 /* Debug */,
|
263
|
+
5EBE804914A5FE4800CA9D70 /* Release */,
|
264
|
+
);
|
265
|
+
defaultConfigurationIsVisible = 0;
|
266
|
+
defaultConfigurationName = Release;
|
267
|
+
};
|
268
|
+
5EBE804A14A5FE4900CA9D70 /* Build configuration list for PBXNativeTarget "OSTN02" */ = {
|
269
|
+
isa = XCConfigurationList;
|
270
|
+
buildConfigurations = (
|
271
|
+
5EBE804B14A5FE4900CA9D70 /* Debug */,
|
272
|
+
5EBE804C14A5FE4900CA9D70 /* Release */,
|
273
|
+
);
|
274
|
+
defaultConfigurationIsVisible = 0;
|
275
|
+
defaultConfigurationName = Release;
|
276
|
+
};
|
277
|
+
/* End XCConfigurationList section */
|
278
|
+
};
|
279
|
+
rootObject = 5EBE803714A5FE4800CA9D70 /* Project object */;
|
280
|
+
}
|
@@ -0,0 +1,510 @@
|
|
1
|
+
//
|
2
|
+
// OSTN02.c
|
3
|
+
// OSTN02
|
4
|
+
//
|
5
|
+
// Created by George MacKerron on 24/12/2011.
|
6
|
+
// Copyright (c) 2011 George MacKerron. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
#include "OSTN02.h"
|
10
|
+
#include "dblRelated.h"
|
11
|
+
#include "crc32.h"
|
12
|
+
#include "fancyOut.h"
|
13
|
+
#include "constants.data"
|
14
|
+
#include "shifts.index.data"
|
15
|
+
#include "shifts.data"
|
16
|
+
#include "geoids.data"
|
17
|
+
#include "gridRef.data"
|
18
|
+
#include "testCoords.data"
|
19
|
+
#include "explorerMaps.data"
|
20
|
+
|
21
|
+
#define LENGTH_OF(x) (sizeof (x) / sizeof *(x))
|
22
|
+
#define ASPRINTF_OR_DIE(...) if (asprintf(__VA_ARGS__) < 0) exit(EXIT_FAILURE)
|
23
|
+
|
24
|
+
#define originalIndicesCRC 244629328L // these won't be robust against differing endianness or compiler packing of bit-structs
|
25
|
+
#define originalDataCRC 790474494L
|
26
|
+
|
27
|
+
static CDBL piOver180 = L(0.017453292519943295769236907684886127134428718885417254560971914401710091146034494436822415696345094822);
|
28
|
+
static CDBL oneEightyOverPi = L(57.29577951308232087679815481410517033240547246656432154916024386120284714832155263244096899585111094418);
|
29
|
+
|
30
|
+
|
31
|
+
DBL gridConvergenceDegreesFromLatLon(const LatLonDecimal latLon, const Ellipsoid ellipsoid, const MapProjection projection) {
|
32
|
+
|
33
|
+
CDBL phi = piOver180 * latLon.lat;
|
34
|
+
CDBL lambda = piOver180 * latLon.lon;
|
35
|
+
CDBL lambda0 = piOver180 * projection.trueOriginLatLon.lon;
|
36
|
+
|
37
|
+
CDBL a = ellipsoid.semiMajorAxis;
|
38
|
+
CDBL b = ellipsoid.semiMinorAxis;
|
39
|
+
CDBL f0 = projection.centralMeridianScale;
|
40
|
+
|
41
|
+
CDBL deltaLambda = lambda - lambda0;
|
42
|
+
CDBL deltaLambda2 = deltaLambda * deltaLambda;
|
43
|
+
CDBL deltaLambda3 = deltaLambda2 * deltaLambda;
|
44
|
+
CDBL deltaLambda5 = deltaLambda3 * deltaLambda2;
|
45
|
+
|
46
|
+
CDBL sinPhi = SIN(phi);
|
47
|
+
CDBL sinPhi2 = sinPhi * sinPhi;
|
48
|
+
CDBL cosPhi = COS(phi);
|
49
|
+
CDBL cosPhi2 = cosPhi * cosPhi;
|
50
|
+
CDBL cosPhi4 = cosPhi2 * cosPhi2;
|
51
|
+
CDBL tanPhi = TAN(phi);
|
52
|
+
CDBL tanPhi2 = tanPhi * tanPhi;
|
53
|
+
|
54
|
+
CDBL af0 = a * f0;
|
55
|
+
CDBL af02 = af0 * af0;
|
56
|
+
CDBL bf0 = b * f0;
|
57
|
+
CDBL bf02 = bf0 * bf0;
|
58
|
+
|
59
|
+
CDBL e2 = (af02 - bf02) / af02;
|
60
|
+
CDBL nu = af0 / SQRT(L(1.0) - (e2 * sinPhi2));
|
61
|
+
CDBL rho = (nu * (L(1.0) - e2)) / (L(1.0) - (e2 * sinPhi2));
|
62
|
+
CDBL eta2 = (nu / rho) - L(1.0);
|
63
|
+
CDBL xiv = ((sinPhi * cosPhi2) / L(3.0)) * (L(1.0) + L(3.0) * eta2 + L(2.0) * eta2 * eta2);
|
64
|
+
CDBL xv = ((sinPhi * cosPhi4) / L(15.0)) * (L(2.0) - tanPhi2);
|
65
|
+
|
66
|
+
CDBL cRads = (deltaLambda * sinPhi) + (deltaLambda3 * xiv) + (deltaLambda5 * xv);
|
67
|
+
return oneEightyOverPi * cRads;
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
DBL gridConvergenceDegreesFromEastingNorthing(const EastingNorthing en, const Ellipsoid ellipsoid, const MapProjection projection) {
|
72
|
+
|
73
|
+
LatLonDecimal latLon = latLonFromEastingNorthing(en, ellipsoid, projection);
|
74
|
+
CDBL phi = piOver180 * latLon.lat;
|
75
|
+
CDBL lambda = piOver180 * latLon.lon;
|
76
|
+
CDBL lambda0 = piOver180 * projection.trueOriginLatLon.lon;
|
77
|
+
|
78
|
+
CDBL a = ellipsoid.semiMajorAxis;
|
79
|
+
CDBL b = ellipsoid.semiMinorAxis;
|
80
|
+
CDBL f0 = projection.centralMeridianScale;
|
81
|
+
|
82
|
+
CDBL deltaLambda = lambda - lambda0;
|
83
|
+
CDBL deltaLambda2 = deltaLambda * deltaLambda;
|
84
|
+
CDBL deltaLambda3 = deltaLambda2 * deltaLambda;
|
85
|
+
CDBL deltaLambda5 = deltaLambda3 * deltaLambda2;
|
86
|
+
|
87
|
+
CDBL sinPhi = SIN(phi);
|
88
|
+
CDBL sinPhi2 = sinPhi * sinPhi;
|
89
|
+
CDBL cosPhi = COS(phi);
|
90
|
+
CDBL cosPhi2 = cosPhi * cosPhi;
|
91
|
+
CDBL cosPhi4 = cosPhi2 * cosPhi2;
|
92
|
+
CDBL tanPhi = TAN(phi);
|
93
|
+
CDBL tanPhi2 = tanPhi * tanPhi;
|
94
|
+
|
95
|
+
CDBL af0 = a * f0;
|
96
|
+
CDBL af02 = af0 * af0;
|
97
|
+
CDBL bf0 = b * f0;
|
98
|
+
CDBL bf02 = bf0 * bf0;
|
99
|
+
|
100
|
+
CDBL e2 = (af02 - bf02) / af02;
|
101
|
+
CDBL nu = af0 / SQRT(L(1.0) - (e2 * sinPhi2));
|
102
|
+
CDBL rho = (nu * (L(1.0) - e2)) / (L(1.0) - (e2 * sinPhi2));
|
103
|
+
CDBL eta2 = (nu / rho) - L(1.0);
|
104
|
+
CDBL xiv = ((sinPhi * cosPhi2) / L(3.0)) * (L(1.0) + L(3.0) * eta2 + L(2.0) * eta2 * eta2);
|
105
|
+
CDBL xv = ((sinPhi * cosPhi4) / L(15.0)) * (L(2.0) - tanPhi2);
|
106
|
+
|
107
|
+
CDBL cRads = (deltaLambda * sinPhi) + (deltaLambda3 * xiv) + (deltaLambda5 * xv);
|
108
|
+
return oneEightyOverPi * cRads;
|
109
|
+
}
|
110
|
+
|
111
|
+
int nextOSExplorerMap(EastingNorthing en, int prevMap) {
|
112
|
+
for (int i = prevMap + 1, len = LENGTH_OF(OSExplorerMaps); i < len; i ++) {
|
113
|
+
OSMap map = OSExplorerMaps[i];
|
114
|
+
if ( en.e >= (DBL) map.emin
|
115
|
+
&& en.e <= (DBL) map.emax
|
116
|
+
&& en.n >= (DBL) map.nmin
|
117
|
+
&& en.n <= (DBL) map.nmax) return i;
|
118
|
+
}
|
119
|
+
return -1;
|
120
|
+
}
|
121
|
+
|
122
|
+
EastingNorthing eastingNorthingFromLatLon(const LatLonDecimal latLon, const Ellipsoid ellipsoid, const MapProjection projection) {
|
123
|
+
CDBL a = ellipsoid.semiMajorAxis;
|
124
|
+
CDBL b = ellipsoid.semiMinorAxis;
|
125
|
+
CDBL f0 = projection.centralMeridianScale;
|
126
|
+
CDBL e0 = projection.trueOriginEastingNorthing.e;
|
127
|
+
CDBL n0 = projection.trueOriginEastingNorthing.n;
|
128
|
+
|
129
|
+
CDBL phi = piOver180 * latLon.lat;
|
130
|
+
CDBL lambda = piOver180 * latLon.lon;
|
131
|
+
CDBL phi0 = piOver180 * projection.trueOriginLatLon.lat;
|
132
|
+
CDBL lambda0 = piOver180 * projection.trueOriginLatLon.lon;
|
133
|
+
|
134
|
+
CDBL deltaPhi = phi - phi0;
|
135
|
+
CDBL sumPhi = phi + phi0;
|
136
|
+
CDBL sinPhi = SIN(phi);
|
137
|
+
CDBL sinPhi2 = sinPhi * sinPhi;
|
138
|
+
CDBL cosPhi = COS(phi);
|
139
|
+
CDBL cosPhi2 = cosPhi * cosPhi;
|
140
|
+
CDBL cosPhi3 = cosPhi2 * cosPhi;
|
141
|
+
CDBL cosPhi5 = cosPhi3 * cosPhi2;
|
142
|
+
CDBL tanPhi = TAN(phi);
|
143
|
+
CDBL tanPhi2 = tanPhi * tanPhi;
|
144
|
+
CDBL tanPhi4 = tanPhi2 * tanPhi2;
|
145
|
+
|
146
|
+
CDBL a2 = a * a;
|
147
|
+
CDBL e2 = (a2 - b * b) / a2;
|
148
|
+
CDBL n = (a - b) / (a + b);
|
149
|
+
CDBL n2 = n * n;
|
150
|
+
CDBL n3 = n2 * n;
|
151
|
+
CDBL oneMinusE2SinPhi2 = L(1.0) - e2 * sinPhi2;
|
152
|
+
CDBL sqrtOneMinusE2SinPhi2 = SQRT(oneMinusE2SinPhi2);
|
153
|
+
CDBL v = a * f0 / sqrtOneMinusE2SinPhi2;
|
154
|
+
CDBL rho = a * f0 * (L(1.0) - e2) / (oneMinusE2SinPhi2 * sqrtOneMinusE2SinPhi2);
|
155
|
+
CDBL eta2 = v / rho - L(1.0);
|
156
|
+
CDBL m = b * f0 * ( (L(1.0) + n + (L(5.0) / L(4.0)) * n2 + (L(5.0) / L(4.0)) * n3) * deltaPhi
|
157
|
+
- (L(3.0) * n + L(3.0) * n2 + (L(21.0) / L(8.0)) * n3) * SIN(deltaPhi) * COS(sumPhi)
|
158
|
+
+ ((L(15.0) / L(8.0)) * n2 + (L(15.0) / L(8.0)) * n3) * SIN(L(2.0) * deltaPhi) * COS(L(2.0) * sumPhi)
|
159
|
+
- (L(35.0) / L(24.0)) * n3 * SIN(L(3.0) * deltaPhi) * COS(L(3.0) * sumPhi)
|
160
|
+
);
|
161
|
+
|
162
|
+
CDBL one = m + n0;
|
163
|
+
CDBL two = (v / L(2.0)) * sinPhi * cosPhi;
|
164
|
+
CDBL three = (v / L(24.0)) * sinPhi * cosPhi3 * (L(5.0) - tanPhi2 + L(9.0) * eta2);
|
165
|
+
CDBL threeA = (v / L(720.0)) * sinPhi * cosPhi5 * (L(61.0) - L(58.0) * tanPhi2 + tanPhi4);
|
166
|
+
CDBL four = v * cosPhi;
|
167
|
+
CDBL five = (v / L(6.0)) * cosPhi3 * (v / rho - tanPhi2);
|
168
|
+
CDBL six = (v / L(120.0)) * cosPhi5 * (L(5.0) - L(18.0) * tanPhi2 + tanPhi4 + L(14.0) * eta2 - L(58.0) * tanPhi2 * eta2);
|
169
|
+
|
170
|
+
CDBL deltaLambda = lambda - lambda0;
|
171
|
+
CDBL deltaLambda2 = deltaLambda * deltaLambda;
|
172
|
+
CDBL deltaLambda3 = deltaLambda2 * deltaLambda;
|
173
|
+
CDBL deltaLambda4 = deltaLambda3 * deltaLambda;
|
174
|
+
CDBL deltaLambda5 = deltaLambda4 * deltaLambda;
|
175
|
+
CDBL deltaLambda6 = deltaLambda5 * deltaLambda;
|
176
|
+
|
177
|
+
EastingNorthing en;
|
178
|
+
en.n = one + two * deltaLambda2 + three * deltaLambda4 + threeA * deltaLambda6;
|
179
|
+
en.e = e0 + four * deltaLambda + five * deltaLambda3 + six * deltaLambda5;
|
180
|
+
en.elevation = latLon.elevation;
|
181
|
+
en.geoid = latLon.geoid;
|
182
|
+
|
183
|
+
return en;
|
184
|
+
}
|
185
|
+
|
186
|
+
EastingNorthing ETRS89EastingNorthingFromETRS89LatLon(const LatLonDecimal latLon) {
|
187
|
+
return eastingNorthingFromLatLon(latLon, GRS80Ellipsoid, NationalGridProj);
|
188
|
+
}
|
189
|
+
|
190
|
+
LatLonDecimal latLonFromEastingNorthing(const EastingNorthing en, const Ellipsoid ellipsoid, const MapProjection projection) {
|
191
|
+
CDBL a = ellipsoid.semiMajorAxis;
|
192
|
+
CDBL b = ellipsoid.semiMinorAxis;
|
193
|
+
CDBL f0 = projection.centralMeridianScale;
|
194
|
+
CDBL e0 = projection.trueOriginEastingNorthing.e;
|
195
|
+
CDBL n0 = projection.trueOriginEastingNorthing.n;
|
196
|
+
CDBL n = (a - b) / (a + b);
|
197
|
+
CDBL n2 = n * n;
|
198
|
+
CDBL n3 = n2 * n;
|
199
|
+
CDBL bf0 = b * f0;
|
200
|
+
|
201
|
+
CDBL phi0 = piOver180 * projection.trueOriginLatLon.lat;
|
202
|
+
CDBL lambda0 = piOver180 * projection.trueOriginLatLon.lon;
|
203
|
+
|
204
|
+
DBL phi = phi0; // this is phi' in the OS docs
|
205
|
+
DBL m = L(0.0);
|
206
|
+
DBL deltaPhi, sumPhi;
|
207
|
+
do {
|
208
|
+
phi = (en.n - n0 - m) / (a * f0) + phi;
|
209
|
+
deltaPhi = phi - phi0;
|
210
|
+
sumPhi = phi + phi0;
|
211
|
+
m = bf0 * ( (L(1.0) + n + (L(5.0) / L(4.0)) * n2 + (L(5.0) / L(4.0)) * n3) * deltaPhi
|
212
|
+
- (L(3.0) * n + L(3.0) * n2 + (L(21.0) / L(8.0)) * n3) * SIN(deltaPhi) * COS(sumPhi)
|
213
|
+
+ ((L(15.0) / L(8.0)) * n2 + (L(15.0) / L(8.0)) * n3) * SIN(L(2.0) * deltaPhi) * COS(L(2.0) * sumPhi)
|
214
|
+
- (L(35.0) / L(24.0)) * n3 * SIN(L(3.0) * deltaPhi) * COS(L(3.0) * sumPhi)
|
215
|
+
);
|
216
|
+
} while (ABS(en.n - n0 - m) >= L(0.00001));
|
217
|
+
|
218
|
+
CDBL sinPhi = SIN(phi);
|
219
|
+
CDBL sinPhi2 = sinPhi * sinPhi;
|
220
|
+
CDBL cosPhi = COS(phi);
|
221
|
+
CDBL secPhi = L(1.0) / cosPhi;
|
222
|
+
CDBL tanPhi = TAN(phi);
|
223
|
+
CDBL tanPhi2 = tanPhi * tanPhi;
|
224
|
+
CDBL tanPhi4 = tanPhi2 * tanPhi2;
|
225
|
+
CDBL tanPhi6 = tanPhi4 * tanPhi2;
|
226
|
+
|
227
|
+
CDBL a2 = a * a;
|
228
|
+
CDBL e2 = (a2 - b * b) / a2;
|
229
|
+
CDBL oneMinusE2SinPhi2 = L(1.0) - e2 * sinPhi2;
|
230
|
+
CDBL sqrtOneMinusE2SinPhi2 = SQRT(oneMinusE2SinPhi2);
|
231
|
+
CDBL v = a * f0 / sqrtOneMinusE2SinPhi2;
|
232
|
+
CDBL rho = a * f0 * (L(1.0) - e2) / (oneMinusE2SinPhi2 * sqrtOneMinusE2SinPhi2);
|
233
|
+
CDBL eta2 = v / rho - L(1.0);
|
234
|
+
|
235
|
+
CDBL v2 = v * v;
|
236
|
+
CDBL v3 = v2 * v;
|
237
|
+
CDBL v5 = v3 * v2;
|
238
|
+
CDBL v7 = v5 * v2;
|
239
|
+
|
240
|
+
CDBL seven = tanPhi / (L(2.0) * rho * v);
|
241
|
+
CDBL eight = (tanPhi * (L(5.0) + L(3.0) * tanPhi2 + eta2 - L(9.0) * tanPhi2 * eta2)) / (L(24.0) * rho * v3);
|
242
|
+
CDBL nine = (tanPhi * (L(61.0) + L(90.0) * tanPhi2 + L(45.0) * tanPhi4)) / (L(720.0) * rho * v5);
|
243
|
+
CDBL ten = secPhi / v;
|
244
|
+
CDBL eleven = (secPhi * ((v / rho) + L(2.0) * tanPhi2)) / (L(6.0) * v3);
|
245
|
+
CDBL twelve = (secPhi * (L(5.0) + L(28.0) * tanPhi2 + L(24.0) * tanPhi4)) / (L(120.0) * v5);
|
246
|
+
CDBL twelveA = (secPhi * (L(61.0) + L(662.0) * tanPhi2 + L(1320.0) * tanPhi4 + L(720.0) * tanPhi6)) / (L(5040.0) * v7);
|
247
|
+
|
248
|
+
CDBL deltaE = en.e - e0;
|
249
|
+
CDBL deltaE2 = deltaE * deltaE;
|
250
|
+
CDBL deltaE3 = deltaE2 * deltaE;
|
251
|
+
CDBL deltaE4 = deltaE2 * deltaE2;
|
252
|
+
CDBL deltaE5 = deltaE3 * deltaE2;
|
253
|
+
CDBL deltaE6 = deltaE3 * deltaE3;
|
254
|
+
CDBL deltaE7 = deltaE4 * deltaE3;
|
255
|
+
|
256
|
+
LatLonDecimal latLon;
|
257
|
+
latLon.lat = oneEightyOverPi * (phi - seven * deltaE2 + eight * deltaE4 - nine * deltaE6);
|
258
|
+
latLon.lon = oneEightyOverPi * (lambda0 + ten * deltaE - eleven * deltaE3 + twelve * deltaE5 - twelveA * deltaE7);
|
259
|
+
latLon.elevation = en.elevation;
|
260
|
+
latLon.geoid = en.geoid;
|
261
|
+
|
262
|
+
return latLon;
|
263
|
+
}
|
264
|
+
|
265
|
+
LatLonDecimal ETRS89LatLonFromETRS89EastingNorthing(const EastingNorthing en) {
|
266
|
+
return latLonFromEastingNorthing(en, GRS80Ellipsoid, NationalGridProj);
|
267
|
+
}
|
268
|
+
|
269
|
+
EastingNorthing OSTN02ShiftsForIndices(const int eIndex, const int nIndex) {
|
270
|
+
EastingNorthing shifts;
|
271
|
+
shifts.e = shifts.n = shifts.elevation = shifts.geoid = 0;
|
272
|
+
if (nIndex < 0 || nIndex > 1250) return shifts;
|
273
|
+
|
274
|
+
const OSTN02Index dataIndex = OSTN02Indices[nIndex];
|
275
|
+
if (eIndex < dataIndex.eMin || eIndex >= dataIndex.eMin + dataIndex.eCount) return shifts;
|
276
|
+
|
277
|
+
const unsigned int dataOffset = dataIndex.offset + (eIndex - dataIndex.eMin);
|
278
|
+
const OSTN02Datum record = OSTN02Data[dataOffset];
|
279
|
+
if (record.gFlag == 0) return shifts;
|
280
|
+
|
281
|
+
shifts.e = (((DBL) record.eShift) / L(1000.0)) + L(86.0);
|
282
|
+
shifts.n = (((DBL) record.nShift) / L(1000.0)) - L(82.0);
|
283
|
+
shifts.elevation = (((DBL) record.gShift) / L(1000.0)) + L(43.0);
|
284
|
+
shifts.geoid = record.gFlag;
|
285
|
+
return shifts;
|
286
|
+
}
|
287
|
+
|
288
|
+
EastingNorthing shiftsForEastingNorthing(const EastingNorthing en) {
|
289
|
+
EastingNorthing shifts;
|
290
|
+
shifts.e = shifts.n = shifts.elevation = shifts.geoid = 0;
|
291
|
+
|
292
|
+
const int e0 = (int) (en.e / L(1000.0));
|
293
|
+
const int n0 = (int) (en.n / L(1000.0));
|
294
|
+
CDBL dx = en.e - (DBL) (e0 * 1000);
|
295
|
+
CDBL dy = en.n - (DBL) (n0 * 1000);
|
296
|
+
CDBL t = dx / L(1000.0);
|
297
|
+
CDBL u = dy / L(1000.0);
|
298
|
+
|
299
|
+
const EastingNorthing shifts0 = OSTN02ShiftsForIndices(e0 , n0 );
|
300
|
+
if (shifts0.geoid == 0) return shifts;
|
301
|
+
|
302
|
+
const EastingNorthing shifts1 = OSTN02ShiftsForIndices(e0 + 1, n0 );
|
303
|
+
if (shifts1.geoid == 0) return shifts;
|
304
|
+
|
305
|
+
const EastingNorthing shifts2 = OSTN02ShiftsForIndices(e0 + 1, n0 + 1);
|
306
|
+
if (shifts2.geoid == 0) return shifts;
|
307
|
+
|
308
|
+
const EastingNorthing shifts3 = OSTN02ShiftsForIndices(e0 , n0 + 1);
|
309
|
+
if (shifts3.geoid == 0) return shifts;
|
310
|
+
|
311
|
+
CDBL weight0 = (L(1.0) - t) * (L(1.0) - u);
|
312
|
+
CDBL weight1 = t * (L(1.0) - u);
|
313
|
+
CDBL weight2 = t * u;
|
314
|
+
CDBL weight3 = (L(1.0) - t) * u;
|
315
|
+
|
316
|
+
shifts.e = weight0 * shifts0.e
|
317
|
+
+ weight1 * shifts1.e
|
318
|
+
+ weight2 * shifts2.e
|
319
|
+
+ weight3 * shifts3.e;
|
320
|
+
|
321
|
+
shifts.n = weight0 * shifts0.n
|
322
|
+
+ weight1 * shifts1.n
|
323
|
+
+ weight2 * shifts2.n
|
324
|
+
+ weight3 * shifts3.n;
|
325
|
+
|
326
|
+
shifts.elevation = weight0 * shifts0.elevation
|
327
|
+
+ weight1 * shifts1.elevation
|
328
|
+
+ weight2 * shifts2.elevation
|
329
|
+
+ weight3 * shifts3.elevation;
|
330
|
+
|
331
|
+
const bool left = dx < L(500.0);
|
332
|
+
const bool bottom = dy < L(500.0);
|
333
|
+
const EastingNorthing nearestShift = left ? (bottom ? shifts0 : shifts3) : (bottom ? shifts1 : shifts2);
|
334
|
+
shifts.geoid = nearestShift.geoid;
|
335
|
+
|
336
|
+
return shifts;
|
337
|
+
}
|
338
|
+
|
339
|
+
EastingNorthing OSGB36EastingNorthingFromETRS89EastingNorthing(const EastingNorthing en) {
|
340
|
+
EastingNorthing shifts = shiftsForEastingNorthing(en);
|
341
|
+
if (shifts.geoid == 0) return shifts;
|
342
|
+
|
343
|
+
EastingNorthing shifted;
|
344
|
+
shifted.e = en.e + shifts.e;
|
345
|
+
shifted.n = en.n + shifts.n;
|
346
|
+
shifted.elevation = en.elevation - shifts.elevation;
|
347
|
+
shifted.geoid = shifts.geoid;
|
348
|
+
|
349
|
+
return shifted;
|
350
|
+
}
|
351
|
+
|
352
|
+
EastingNorthing ETRS89EastingNorthingFromOSGB36EastingNorthing(const EastingNorthing en) {
|
353
|
+
EastingNorthing shifts, prevShifts, shifted;
|
354
|
+
shifts.e = shifts.n = shifted.elevation = shifted.geoid = 0; // initialising .elevation and .geoid just avoids warnings
|
355
|
+
do {
|
356
|
+
prevShifts.e = shifts.e;
|
357
|
+
prevShifts.n = shifts.n;
|
358
|
+
shifted.e = en.e - shifts.e;
|
359
|
+
shifted.n = en.n - shifts.n;
|
360
|
+
shifts = shiftsForEastingNorthing(shifted);
|
361
|
+
if (shifts.geoid == 0) return shifts;
|
362
|
+
} while (ABS(shifts.e - prevShifts.e) > L(0.0001) || ABS(shifts.n - prevShifts.n) > L(0.0001));
|
363
|
+
|
364
|
+
shifted.elevation = en.elevation + shifts.elevation;
|
365
|
+
shifted.geoid = shifts.geoid; // tells us which geoid datum was used in conversion
|
366
|
+
return shifted;
|
367
|
+
}
|
368
|
+
|
369
|
+
char *gridRefFromOSGB36EastingNorthing(const EastingNorthing en, const bool spaces, const int res) {
|
370
|
+
// res is expressed in metres: 1/10/100 -> 3/4/5-digit easting and northing
|
371
|
+
const int eRound = (int) round(en.e / (DBL) res) * res;
|
372
|
+
const int nRound = (int) round(en.n / (DBL) res) * res;
|
373
|
+
const int firstEIndex = eRound / 500000;
|
374
|
+
const int firstNIndex = nRound / 500000;
|
375
|
+
const int secondEIndex = (eRound % 500000) / 100000;
|
376
|
+
const int secondNIndex = (nRound % 500000) / 100000;
|
377
|
+
const char sq0 = firstLetters[firstNIndex][firstEIndex];
|
378
|
+
const char sq1 = secondLetters[secondNIndex][secondEIndex];
|
379
|
+
const int e = eRound - (500000 * firstEIndex) - (100000 * secondEIndex);
|
380
|
+
const int n = nRound - (500000 * firstNIndex) - (100000 * secondNIndex);
|
381
|
+
char *ref, *fmtStr;
|
382
|
+
const int digits = res == 100 ? 3 : (res == 10 ? 4 : 5);
|
383
|
+
ASPRINTF_OR_DIE(&fmtStr, "%%c%%c%%s%%0%dd%%s%%0%dd", digits, digits);
|
384
|
+
ASPRINTF_OR_DIE(&ref, fmtStr, sq0, sq1, (spaces ? " " : ""), e / res, (spaces ? " " : ""), n / res);
|
385
|
+
free(fmtStr);
|
386
|
+
return ref;
|
387
|
+
}
|
388
|
+
|
389
|
+
char *tetradFromOSGB36EastingNorthing(const EastingNorthing en) {
|
390
|
+
// see http://www.bto.org/volunteer-surveys/birdatlas/taking-part/correct-grid-references/know-your-place
|
391
|
+
const int eTrunc = (int) en.e; // note: unlike for a grid ref, we never round -- we (implictly) truncate
|
392
|
+
const int nTrunc = (int) en.n;
|
393
|
+
const int firstEIndex = eTrunc / 500000;
|
394
|
+
const int firstNIndex = nTrunc / 500000;
|
395
|
+
const int secondEIndex = (eTrunc % 500000) / 100000;
|
396
|
+
const int secondNIndex = (nTrunc % 500000) / 100000;
|
397
|
+
const char sq0 = firstLetters[firstNIndex][firstEIndex];
|
398
|
+
const char sq1 = secondLetters[secondNIndex][secondEIndex];
|
399
|
+
const int eMinusSq = eTrunc - (500000 * firstEIndex) - (100000 * secondEIndex);
|
400
|
+
const int nMinusSq = nTrunc - (500000 * firstNIndex) - (100000 * secondNIndex);
|
401
|
+
const int eDigit = eMinusSq / 10000;
|
402
|
+
const int nDigit = nMinusSq / 10000;
|
403
|
+
const int tetradEIndex = (eMinusSq % 10000) / 2000;
|
404
|
+
const int tetradNIndex = (nMinusSq % 10000) / 2000;
|
405
|
+
char tetradLetter = tetradLetters[tetradNIndex][tetradEIndex];
|
406
|
+
char *tetrad;
|
407
|
+
ASPRINTF_OR_DIE(&tetrad, "%c%c%d%d%c", sq0, sq1, eDigit, nDigit, tetradLetter);
|
408
|
+
return tetrad;
|
409
|
+
}
|
410
|
+
|
411
|
+
LatLonDecimal latLonDecimalFromLatLonDegMinSec(const LatLonDegMinSec dms) {
|
412
|
+
LatLonDecimal dec;
|
413
|
+
dec.lat = (dms.lat.westOrSouth ? L(-1.0) : L(1.0)) * (((DBL) dms.lat.deg) + ((DBL) dms.lat.min) / L(60.0) + dms.lat.sec / L(3600.0));
|
414
|
+
dec.lon = (dms.lon.westOrSouth ? L(-1.0) : L(1.0)) * (((DBL) dms.lon.deg) + ((DBL) dms.lon.min) / L(60.0) + dms.lon.sec / L(3600.0));
|
415
|
+
dec.elevation = dms.elevation;
|
416
|
+
dec.geoid = 0;
|
417
|
+
return dec;
|
418
|
+
}
|
419
|
+
|
420
|
+
bool test(const bool noisily) {
|
421
|
+
short numTested = 0;
|
422
|
+
short numPassed = 0;
|
423
|
+
bool testPassed;
|
424
|
+
|
425
|
+
// check data integrity
|
426
|
+
|
427
|
+
const unsigned long dataCRC = crc32((unsigned char *) OSTN02Data, sizeof(OSTN02Data));
|
428
|
+
testPassed = dataCRC == originalDataCRC;
|
429
|
+
numTested ++;
|
430
|
+
if (testPassed) numPassed ++;
|
431
|
+
if (noisily) {
|
432
|
+
printf("\nOriginal CRC32 (data): %li\n", originalDataCRC);
|
433
|
+
printf("%sComputed CRC32 (data): %li%s\n\n", (testPassed ? "" : BOLD), dataCRC, (testPassed ? "" : UNBOLD));
|
434
|
+
}
|
435
|
+
|
436
|
+
const unsigned long indicesCRC = crc32((unsigned char *) OSTN02Indices, sizeof(OSTN02Indices));
|
437
|
+
testPassed = indicesCRC == originalIndicesCRC;
|
438
|
+
numTested ++;
|
439
|
+
if (testPassed) numPassed ++;
|
440
|
+
if (noisily) {
|
441
|
+
printf("Original CRC32 (index): %li\n", originalIndicesCRC);
|
442
|
+
printf("%sComputed CRC32 (index): %li%s\n\n", (testPassed ? "" : BOLD), indicesCRC, (testPassed ? "" : UNBOLD));
|
443
|
+
}
|
444
|
+
|
445
|
+
// check test conversions against known good results
|
446
|
+
|
447
|
+
LatLonDecimal actualLatLon, computedLatLon;
|
448
|
+
EastingNorthing actualEN, computedEN;
|
449
|
+
char *actualLatLonStr, *computedLatLonStr, *actualENStr, *computedENStr;
|
450
|
+
|
451
|
+
const int len = LENGTH_OF(testETRSCoords);
|
452
|
+
for (int i = 0; i < len; i ++) {
|
453
|
+
|
454
|
+
// actual coords
|
455
|
+
|
456
|
+
actualLatLon = latLonDecimalFromLatLonDegMinSec(testETRSCoords[i]);
|
457
|
+
actualEN = testOSGB36Coords[i];
|
458
|
+
|
459
|
+
ASPRINTF_OR_DIE(&actualLatLonStr, LLFMT, actualLatLon.lat, actualLatLon.lon, actualLatLon.elevation);
|
460
|
+
ASPRINTF_OR_DIE(&actualENStr, ENFMT, actualEN.e, actualEN.n, actualEN.elevation, OSGB36GeoidRegions[actualEN.geoid], OSGB36GeoidNames[actualEN.geoid]);
|
461
|
+
|
462
|
+
if (noisily) {
|
463
|
+
printf("ETRS89 actual %s\n", actualLatLonStr);
|
464
|
+
printf("OSGB36 actual %s\n", actualENStr);
|
465
|
+
}
|
466
|
+
|
467
|
+
// computed coords
|
468
|
+
|
469
|
+
computedLatLon = ETRS89LatLonFromETRS89EastingNorthing(ETRS89EastingNorthingFromOSGB36EastingNorthing(actualEN));
|
470
|
+
computedEN = OSGB36EastingNorthingFromETRS89EastingNorthing(ETRS89EastingNorthingFromETRS89LatLon(actualLatLon));
|
471
|
+
|
472
|
+
ASPRINTF_OR_DIE(&computedLatLonStr, LLFMT, computedLatLon.lat, computedLatLon.lon, computedLatLon.elevation);
|
473
|
+
ASPRINTF_OR_DIE(&computedENStr, ENFMT, computedEN.e, computedEN.n, computedEN.elevation, OSGB36GeoidRegions[computedEN.geoid], OSGB36GeoidNames[computedEN.geoid]);
|
474
|
+
|
475
|
+
if (actualEN.geoid != 0) { // i.e. these coordinates are not zeroes, and can be converted sensibly
|
476
|
+
testPassed = strcmp(actualLatLonStr, computedLatLonStr) == 0;
|
477
|
+
numTested ++;
|
478
|
+
if (testPassed) numPassed ++;
|
479
|
+
if (noisily) printf("%sETRS89 computed %s\n%s", (testPassed ? "" : BOLD), computedLatLonStr, (testPassed ? "" : UNBOLD));
|
480
|
+
}
|
481
|
+
|
482
|
+
testPassed = strcmp(actualENStr, computedENStr) == 0;
|
483
|
+
numTested ++;
|
484
|
+
if (testPassed) numPassed ++;
|
485
|
+
if (noisily) printf("%sOSGB36 computed %s\n\n%s", (testPassed ? "" : BOLD), computedENStr, (testPassed ? "" : UNBOLD));
|
486
|
+
|
487
|
+
free(actualLatLonStr);
|
488
|
+
free(computedLatLonStr);
|
489
|
+
free(actualENStr);
|
490
|
+
free(computedENStr);
|
491
|
+
}
|
492
|
+
|
493
|
+
/*
|
494
|
+
EastingNorthing testEN;
|
495
|
+
testEN.e = 651409.903;
|
496
|
+
testEN.n = 313177.270;
|
497
|
+
printf("Convergence: %13.11lf \n\n", gridConvergenceDegreesFromEastingNorthing(testEN, Airy1830Ellipsoid, NationalGridProj));
|
498
|
+
*/
|
499
|
+
|
500
|
+
/*
|
501
|
+
LatLonDecimal testLL;
|
502
|
+
testLL.lat = 51.0;
|
503
|
+
testLL.lon = -2.0;
|
504
|
+
printf("Convergence: %13.11lf \n\n", gridConvergenceDegreesFromLatLon(testLL, Airy1830Ellipsoid, NationalGridProj));
|
505
|
+
*/
|
506
|
+
|
507
|
+
bool allPassed = numTested == numPassed;
|
508
|
+
if (noisily) printf("%i tests; %i passed; %s%i failed%s\n\n", numTested, numPassed, (allPassed ? "" : BOLD), numTested - numPassed, (allPassed ? "" : UNBOLD));
|
509
|
+
return allPassed;
|
510
|
+
}
|