national_grid 0.1.1 → 0.1.2
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.
- 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
|
+
}
|