/src/bag/api/bag_legacy_crs.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | #include "bag_errors.h" |
3 | | #include "bag_exceptions.h" |
4 | | #include "bag_legacy_crs.h" |
5 | | |
6 | | #include <algorithm> // std::transform |
7 | | #include <cctype> // std::tolower |
8 | | #include <cmath> // M_PI |
9 | | #include <cstring> |
10 | | #include <exception> // std::exception |
11 | | #include <fstream> // std::ifstream |
12 | | #include <iomanip> |
13 | | #include <iostream> |
14 | | #include <sstream> |
15 | | #include <string> |
16 | | #include <vector> |
17 | | |
18 | | |
19 | | namespace { |
20 | | |
21 | | //! Projection parameters WKT names. |
22 | | const char k_latitude_of_origin[] = "latitude_of_origin"; |
23 | | const char k_central_meridian[] = "central_meridian"; |
24 | | const char k_scale_factor[] = "scale_factor"; |
25 | | const char k_false_easting[] = "false_easting"; |
26 | | const char k_false_northing[] = "false_northing"; |
27 | | const char k_standard_parallel_1[] = "standard_parallel_1"; |
28 | | const char k_standard_parallel_2[] = "standard_parallel_2"; |
29 | | const char k_latitude_of_center[] = "latitude_of_center"; |
30 | | const char k_longitude_of_center[] = "longitude_of_center"; |
31 | | |
32 | | //! Projection type WKT names. |
33 | | const char k_albers_conic_equal_area[] = "albers_conic_equal_area"; |
34 | | const char k_azimuthal_equidistant[] = "azimuthal_equidistant"; |
35 | | const char k_bonne[] = "bonne"; |
36 | | const char k_cassini_soldner[] = "cassini_soldner"; |
37 | | const char k_cylindrical_equal_area[] = "cylindrical_equal_area"; |
38 | | const char k_eckert_iv[] = "eckert_iv"; |
39 | | const char k_eckert_vi[] = "eckert_vi"; |
40 | | const char k_equirectangular[] = "equirectangular"; |
41 | | const char k_gnomonic[] = "gnomonic"; |
42 | | const char k_lambert_conformal_conic[] = "lambert_conformal_conic_2sp"; |
43 | | const char k_mercator[] = "mercator_1sp"; |
44 | | const char k_miller_cylindrical[] = "miller_cylindrical"; |
45 | | const char k_mollweide[] = "mollweide"; |
46 | | const char k_new_zealand_map_grid[] = "new_zealand_map_grid"; |
47 | | const char k_orthographic[] = "orthographic"; |
48 | | const char k_polar_stereographic[] = "polar_stereographic"; |
49 | | const char k_polyconic[] = "polyconic"; |
50 | | const char k_sinusoidal[] = "sinusoidal"; |
51 | | const char k_oblique_stereographic[] = "oblique_stereographic"; |
52 | | const char k_transverse_mercator[] = "transverse_mercator"; |
53 | | const char k_vandergrinten[] = "vandergrinten"; |
54 | | |
55 | | //! Datum WKT names. |
56 | | const char k_wgs84[] = "wgs_1984"; |
57 | | const char k_wgs72[] = "wgs_1972"; |
58 | | const char k_nad83[] = "north_american_datum_1983"; |
59 | | |
60 | | //! Split a string by the specified separator. |
61 | | /*! |
62 | | \param str |
63 | | The string to split. |
64 | | \param separator |
65 | | The separator to split the string by. |
66 | | Defaults to space. |
67 | | |
68 | | \return |
69 | | A list of words split by separator. |
70 | | */ |
71 | | std::vector<std::string> split( |
72 | | const std::string& str, |
73 | | const char separator = ' ') |
74 | 0 | { |
75 | 0 | std::vector<std::string> tokens; |
76 | |
|
77 | 0 | const auto end = cend(str); |
78 | 0 | auto p1 = cbegin(str); |
79 | 0 | auto p2 = end; |
80 | |
|
81 | 0 | do |
82 | 0 | { |
83 | 0 | p2 = std::find(p1, end, separator); // find next separator |
84 | 0 | tokens.emplace_back(p1, p2); |
85 | |
|
86 | 0 | if (p2 != end) |
87 | 0 | { // More tokens left. |
88 | 0 | p1 = std::find_if(p2, end, [separator](char c) -> bool { |
89 | 0 | return c != separator; // skip all separators |
90 | 0 | }); |
91 | 0 | } |
92 | 0 | } while (p2 != end); |
93 | |
|
94 | 0 | return tokens; |
95 | 0 | } |
96 | | |
97 | | //************************************************************************ |
98 | | /*! |
99 | | \brief Convert the given string value to double. |
100 | | |
101 | | The string is expected to contain a decimal value in the classic locale. |
102 | | For example something like "20.0". The classic locale uses a '.' as the |
103 | | decimal separator. |
104 | | |
105 | | \param value |
106 | | \li The string to convert. |
107 | | \return |
108 | | \li The converted value. |
109 | | */ |
110 | | //************************************************************************ |
111 | | double toDouble(const std::string& value) |
112 | 0 | { |
113 | 0 | std::stringstream lineStream; |
114 | 0 |
|
115 | 0 | (void)lineStream.imbue(std::locale::classic()); |
116 | 0 | lineStream << value; |
117 | 0 |
|
118 | 0 | double dblValue = 0.0; |
119 | 0 | lineStream >> dblValue; |
120 | 0 |
|
121 | 0 | return dblValue; |
122 | 0 | } |
123 | | |
124 | | //************************************************************************ |
125 | | /*! |
126 | | \brief Convert the BAG ellipsoid to WKT. |
127 | | |
128 | | To convert the ellipsoid we need the semi-major and inverse flattening |
129 | | ratio. We will open the ellips.dat file to retrieve this information. |
130 | | |
131 | | \param ellipsoid |
132 | | \li The BAG ellipsoid type to convert. |
133 | | \return |
134 | | \li The WKT representation for that ellipsoid. |
135 | | */ |
136 | | //************************************************************************ |
137 | | std::string ellipsoidToWkt(const char* ellipsoid) |
138 | 0 | { |
139 | 0 | const char* onsHome = getenv("BAG_HOME"); |
140 | 0 | if (!onsHome) |
141 | 0 | throw BAG::InvalidEllipsoidError(); |
142 | | |
143 | | //Make the ellipsoid name all lower case so we can find it. |
144 | 0 | std::string ellipsoidName{ellipsoid}; |
145 | 0 | std::transform(begin(ellipsoidName), end(ellipsoidName), |
146 | 0 | begin(ellipsoidName), |
147 | 0 | [](unsigned char c) noexcept { |
148 | 0 | return static_cast<char>(std::tolower(c)); |
149 | 0 | }); |
150 | | |
151 | | //Build the full path to the ellips.dat file. |
152 | 0 | std::string ellipFile{onsHome}; |
153 | 0 | ellipFile += "/ellips.dat"; |
154 | |
|
155 | 0 | std::ifstream file{ellipFile.c_str()}; |
156 | 0 | if (!file.is_open()) |
157 | 0 | throw BAG::InvalidEllipsoidError(); |
158 | | |
159 | 0 | while (file.good()) |
160 | 0 | { |
161 | | //Get the current line in lower case. |
162 | 0 | std::string line; |
163 | 0 | std::getline(file, line); |
164 | |
|
165 | 0 | std::transform(begin(line), end(line), begin(line), |
166 | 0 | [](unsigned char c) noexcept { |
167 | 0 | return static_cast<char>(std::tolower(c)); |
168 | 0 | }); |
169 | |
|
170 | 0 | const size_t index = line.find(ellipsoidName); |
171 | 0 | if (index != 0) |
172 | 0 | continue; |
173 | | |
174 | 0 | auto elements = split(line, ' '); |
175 | 0 | const auto numItems = elements.size(); |
176 | | |
177 | | //We MUST have at least 5 elements (name, id, a, b, if) |
178 | 0 | if (numItems < 5) |
179 | 0 | throw BAG::InvalidEllipsoidError(); |
180 | | |
181 | | //The last item will be the inverse flattening. |
182 | 0 | const double invFlat = atof(elements[numItems - 1].c_str()); |
183 | | |
184 | | //The third to last item will be the semi-major. |
185 | 0 | const double semiMajor = atof(elements[numItems - 3].c_str()); |
186 | |
|
187 | 0 | std::stringstream wktStream; |
188 | 0 | (void)wktStream.imbue(std::locale::classic()); |
189 | 0 | wktStream << std::fixed << std::setprecision(9) << |
190 | 0 | R"(SPHEROID[")" << ellipsoid << R"(",)" << |
191 | 0 | semiMajor << ',' << invFlat << ']'; |
192 | |
|
193 | 0 | return wktStream.str(); |
194 | 0 | } |
195 | | |
196 | | //Couldn't find it :( |
197 | 0 | throw BAG::InvalidEllipsoidError(); |
198 | 0 | } |
199 | | |
200 | | //************************************************************************ |
201 | | /*! |
202 | | \brief Convert the BAG datum type to WKT. |
203 | | |
204 | | If we are unable to convert the specified ellipsoid, we will use |
205 | | a good default for the datum type. |
206 | | |
207 | | \param datum |
208 | | \li The BAG datum type to convert. |
209 | | \param ellipsoid |
210 | | \li The BAG ellipsoid to convert. |
211 | | \return |
212 | | \li The WKT representation for that datum. |
213 | | */ |
214 | | //************************************************************************ |
215 | | std::string datumToWkt( |
216 | | const BAG::BagDatum datum, |
217 | | const char* ellipsoid) |
218 | 0 | { |
219 | 0 | std::string ellipWkt; |
220 | | |
221 | | //Try to decode the ellipsoid, if we fail then we will use the 'default' ellipsoid. |
222 | 0 | try |
223 | 0 | { |
224 | | //Try to decode the ellipsoid |
225 | 0 | ellipWkt = ellipsoidToWkt(ellipsoid); |
226 | 0 | } |
227 | 0 | catch (...) |
228 | 0 | { |
229 | 0 | switch (datum) |
230 | 0 | { |
231 | 0 | case BAG::BagDatum::wgs84: |
232 | 0 | ellipWkt = R"(SPHEROID["WGS 84",6378137,298.257223563])"; |
233 | 0 | break; |
234 | | |
235 | 0 | case BAG::BagDatum::wgs72: |
236 | 0 | ellipWkt = R"(SPHEROID["WGS 72",6378135,298.26])"; |
237 | 0 | break; |
238 | | |
239 | 0 | case BAG::BagDatum::nad83: |
240 | 0 | ellipWkt = R"(SPHEROID["GRS 1980",6378137,298.257222101])"; |
241 | 0 | break; |
242 | | |
243 | 0 | case BAG::BagDatum::unknown: |
244 | 0 | ellipWkt = R"(SPHEROID["UNKNOWN",0,0.0])"; |
245 | 0 | break; |
246 | 0 | } |
247 | 0 | }; |
248 | |
|
249 | 0 | std::stringstream wktStream; |
250 | 0 | (void)wktStream.imbue(std::locale::classic()); |
251 | |
|
252 | 0 | switch (datum) |
253 | 0 | { |
254 | 0 | case BAG::BagDatum::wgs84: |
255 | 0 | { |
256 | 0 | wktStream << R"(GEOGCS["WGS 84", )" |
257 | 0 | << R"(DATUM["WGS_1984", )" |
258 | 0 | << ellipWkt << ", " |
259 | 0 | << "TOWGS84[0,0,0,0,0,0,0]], " |
260 | 0 | << R"(PRIMEM["Greenwich",0], )" |
261 | 0 | << R"(UNIT["degree",0.0174532925199433]])"; |
262 | |
|
263 | 0 | return wktStream.str(); |
264 | 0 | } |
265 | 0 | break; |
266 | | |
267 | 0 | case BAG::BagDatum::wgs72: |
268 | 0 | { |
269 | 0 | wktStream << R"(GEOGCS["WGS 72", )" |
270 | 0 | << R"(DATUM["WGS_1972", )" |
271 | 0 | << ellipWkt << ", " |
272 | 0 | << "TOWGS84[0,0,4.5,0,0,0.554,0.2263]], " |
273 | 0 | << R"(PRIMEM["Greenwich",0], )" |
274 | 0 | << R"(UNIT["degree",0.0174532925199433]])"; |
275 | |
|
276 | 0 | return wktStream.str(); |
277 | 0 | } |
278 | 0 | break; |
279 | | |
280 | 0 | case BAG::BagDatum::nad83: |
281 | 0 | { |
282 | 0 | wktStream << R"(GEOGCS["NAD83", )" |
283 | 0 | << R"(DATUM["North_American_Datum_1983", )" |
284 | 0 | << ellipWkt << ", " |
285 | 0 | << "TOWGS84[0,0,0,0,0,0,0]], " |
286 | 0 | << R"(PRIMEM["Greenwich",0], )" |
287 | 0 | << R"(UNIT["degree",0.0174532925199433]])"; |
288 | |
|
289 | 0 | return wktStream.str(); |
290 | 0 | } |
291 | 0 | break; |
292 | | |
293 | 0 | case BAG::BagDatum::unknown: |
294 | 0 | { |
295 | 0 | return wktStream.str(); |
296 | 0 | } |
297 | 0 | break; |
298 | |
|
299 | 0 | } |
300 | | |
301 | | //If we got here then we don't know what type of datum we have. |
302 | 0 | throw BAG::InvalidDatumError(); |
303 | 0 | } |
304 | | |
305 | | //************************************************************************ |
306 | | /*! |
307 | | \brief Retrieve the specified projection parameter. |
308 | | |
309 | | \param wkt |
310 | | \li The wkt string containing the coordinate system definition. |
311 | | \param paramName |
312 | | \li The name of the projection parameter to retrieve. |
313 | | \return |
314 | | \li The specified projection parameter. |
315 | | */ |
316 | | //************************************************************************ |
317 | | double getProjectionParam( |
318 | | const std::string& wkt, |
319 | | const std::string& paramName) |
320 | 0 | { |
321 | 0 | //Find the projection node in the wkt string. |
322 | 0 | const size_t startIndex = wkt.find(paramName); |
323 | 0 | if (startIndex == std::string::npos) |
324 | 0 | throw BAG::CoordSysError(); |
325 | 0 |
|
326 | 0 | const size_t valueStartIndex = wkt.find(",", startIndex); |
327 | 0 | if (valueStartIndex == std::string::npos) |
328 | 0 | throw BAG::CoordSysError(); |
329 | 0 |
|
330 | 0 | const size_t valueEndIndex = wkt.find("]", valueStartIndex); |
331 | 0 | if (valueEndIndex == std::string::npos) |
332 | 0 | throw BAG::CoordSysError(); |
333 | 0 |
|
334 | 0 | //Extract the value |
335 | 0 | const size_t startPos = valueStartIndex + 1; |
336 | 0 | const size_t length = valueEndIndex - startPos; |
337 | 0 | const std::string value = wkt.substr(startPos, length); |
338 | 0 |
|
339 | 0 | return toDouble(value); |
340 | 0 | } |
341 | | |
342 | | //************************************************************************ |
343 | | /*! |
344 | | \brief Retrieve the BAG coordinate type from the WKT definition. |
345 | | |
346 | | \param wkt |
347 | | \li The wkt string containing the coordinate system definition. |
348 | | \return |
349 | | \li The BAG coordiante system type. |
350 | | */ |
351 | | //************************************************************************ |
352 | | BAG::CoordinateType getCoordinateType(const std::string& wkt) |
353 | 0 | { |
354 | 0 | //Find the projection node in the wkt string. |
355 | 0 | const size_t startIndex = wkt.find("projection["); |
356 | 0 |
|
357 | 0 | //If no projection node, then we must have a Geographic system. |
358 | 0 | if (startIndex == std::string::npos) |
359 | 0 | return BAG::CoordinateType::Geodetic; |
360 | 0 |
|
361 | 0 | const size_t endIndex = wkt.find(R"("])", startIndex); |
362 | 0 | if (endIndex == std::string::npos) |
363 | 0 | throw BAG::CoordSysError(); |
364 | 0 |
|
365 | 0 | //Extract the projection name. |
366 | 0 | const size_t startPos = startIndex + 12; |
367 | 0 | const size_t length = endIndex - startPos; |
368 | 0 | const std::string projName = wkt.substr(startPos, length); |
369 | 0 |
|
370 | 0 | if (projName == k_albers_conic_equal_area) |
371 | 0 | return BAG::CoordinateType::Albers_Equal_Area_Conic; |
372 | 0 | else if (projName == k_azimuthal_equidistant) |
373 | 0 | return BAG::CoordinateType::Azimuthal_Equidistant; |
374 | 0 | else if (projName == k_bonne) |
375 | 0 | return BAG::CoordinateType::Bonne; |
376 | 0 | else if (projName == k_cassini_soldner) |
377 | 0 | return BAG::CoordinateType::Cassini; |
378 | 0 | else if (projName == k_cylindrical_equal_area) |
379 | 0 | return BAG::CoordinateType::Cylindrical_Equal_Area; |
380 | 0 | else if (projName == k_eckert_iv) |
381 | 0 | return BAG::CoordinateType::Eckert4; |
382 | 0 | else if (projName == k_eckert_vi) |
383 | 0 | return BAG::CoordinateType::Eckert6; |
384 | 0 | else if (projName == k_equirectangular) |
385 | 0 | return BAG::CoordinateType::Equidistant_Cylindrical; |
386 | 0 | else if (projName == k_gnomonic) |
387 | 0 | return BAG::CoordinateType::Gnomonic; |
388 | 0 | else if (projName == k_lambert_conformal_conic) |
389 | 0 | return BAG::CoordinateType::Lambert_Conformal_Conic; |
390 | 0 | else if (projName == k_mercator) |
391 | 0 | return BAG::CoordinateType::Mercator; |
392 | 0 | else if (projName == k_miller_cylindrical) |
393 | 0 | return BAG::CoordinateType::Miller_Cylindrical; |
394 | 0 | else if (projName == k_mollweide) |
395 | 0 | return BAG::CoordinateType::Mollweide; |
396 | 0 | else if (projName == k_new_zealand_map_grid) |
397 | 0 | return BAG::CoordinateType::NZMG; |
398 | 0 | else if (projName == k_orthographic) |
399 | 0 | return BAG::CoordinateType::Orthographic; |
400 | 0 | else if (projName == k_polar_stereographic) |
401 | 0 | return BAG::CoordinateType::Polar_Stereo; |
402 | 0 | else if (projName == k_polyconic) |
403 | 0 | return BAG::CoordinateType::Polyconic; |
404 | 0 | else if (projName == k_sinusoidal) |
405 | 0 | return BAG::CoordinateType::Sinusoidal; |
406 | 0 | else if (projName == k_oblique_stereographic) |
407 | 0 | return BAG::CoordinateType::Stereographic; |
408 | 0 | else if (projName == k_transverse_mercator) |
409 | 0 | return BAG::CoordinateType::Transverse_Mercator; |
410 | 0 | else if (projName == k_vandergrinten) |
411 | 0 | return BAG::CoordinateType::Van_der_Grinten; |
412 | 0 |
|
413 | 0 | //No idea... |
414 | 0 | throw BAG::CoordSysError(); |
415 | 0 | } |
416 | | |
417 | | //************************************************************************ |
418 | | /*! |
419 | | \brief Retrieve the BAG datum type from the WKT definition. |
420 | | |
421 | | \param wkt |
422 | | \li The wkt string containing the coordinate system definition. |
423 | | \return |
424 | | \li The BAG datum type. |
425 | | */ |
426 | | //************************************************************************ |
427 | | BAG::BagDatum getDatumType(const std::string &wkt) |
428 | 0 | { |
429 | 0 | //Find the horizontal datum node in the wkt string. |
430 | 0 | const size_t startIndex = wkt.find("datum["); |
431 | 0 | if (startIndex == std::string::npos) |
432 | 0 | throw BAG::InvalidDatumError(); |
433 | 0 |
|
434 | 0 | const size_t endIndex = wkt.find(",", startIndex); |
435 | 0 | if (endIndex == std::string::npos) |
436 | 0 | throw BAG::InvalidDatumError(); |
437 | 0 |
|
438 | 0 | //Extract the horizontal datum name. |
439 | 0 | const size_t startPos = startIndex + 7; |
440 | 0 | const size_t length = endIndex - startPos - 1; |
441 | 0 | const std::string hDatumName = wkt.substr(startPos, length); |
442 | 0 |
|
443 | 0 | if (hDatumName == k_wgs84) |
444 | 0 | return BAG::BagDatum::wgs84; |
445 | 0 | else if (hDatumName == k_wgs72) |
446 | 0 | return BAG::BagDatum::wgs72; |
447 | 0 | else if (hDatumName == k_nad83) |
448 | 0 | return BAG::BagDatum::nad83; |
449 | 0 |
|
450 | 0 | //Unknown, so we can not convert this coordinate system. |
451 | 0 | throw BAG::InvalidDatumError(); |
452 | 0 | } |
453 | | |
454 | | //************************************************************************ |
455 | | /*! |
456 | | \brief Retrieve the BAG ellipsoid name from the WKT definition. |
457 | | |
458 | | \param wkt |
459 | | \li The wkt string containing the coordinate system definition. |
460 | | \return |
461 | | \li The ellipsoid name. |
462 | | */ |
463 | | //************************************************************************ |
464 | | std::string getEllipsoid(const std::string& wkt) |
465 | 0 | { |
466 | 0 | //Find the ellipsoid node in the wkt string. |
467 | 0 | const size_t startIndex = wkt.find("spheroid["); |
468 | 0 | if (startIndex == std::string::npos) |
469 | 0 | throw BAG::InvalidDatumError(); |
470 | 0 |
|
471 | 0 | const size_t endIndex = wkt.find(",", startIndex); |
472 | 0 | if (endIndex == std::string::npos) |
473 | 0 | throw BAG::InvalidDatumError(); |
474 | 0 |
|
475 | 0 | //Extract the ellipsoid name. |
476 | 0 | const size_t startPos = startIndex + 10; |
477 | 0 | const size_t length = endIndex - startPos - 1; |
478 | 0 |
|
479 | 0 | return wkt.substr(startPos, length); |
480 | 0 | } |
481 | | |
482 | | //************************************************************************ |
483 | | /*! |
484 | | \brief Retrieve the vertical datum name from the WKT definition. |
485 | | |
486 | | \param wkt |
487 | | \li The wkt string containing the vertical reference system definition. |
488 | | \return |
489 | | \li The vertical datum name. |
490 | | */ |
491 | | //************************************************************************ |
492 | | std::string getVDatum(const std::string& wkt) |
493 | 0 | { |
494 | 0 | //Find the vertical datum node in the wkt string. |
495 | 0 | const size_t startIndex = wkt.find("vert_datum["); |
496 | 0 | if (startIndex == std::string::npos) |
497 | 0 | throw BAG::InvalidDatumError(); |
498 | 0 |
|
499 | 0 | const size_t endIndex = wkt.find(",", startIndex); |
500 | 0 | if (endIndex == std::string::npos) |
501 | 0 | throw BAG::InvalidDatumError(); |
502 | 0 |
|
503 | 0 | //Extract the vertical datum name. |
504 | 0 | const size_t startPos = startIndex + 12; |
505 | 0 | const size_t length = endIndex - startPos - 1; |
506 | 0 |
|
507 | 0 | return wkt.substr(startPos, length); |
508 | 0 | } |
509 | | |
510 | | } // namespace |
511 | | |
512 | | namespace BAG { |
513 | | |
514 | | //************************************************************************ |
515 | | // Method name: bagLegacyToWkt() |
516 | | // |
517 | | // - Initial implementation |
518 | | // Mike Van Duzee, 1/26/2012 |
519 | | // |
520 | | //************************************************************************ |
521 | | /*! |
522 | | \brief Convert a BAG coordinate system definition to wkt. |
523 | | |
524 | | \param system |
525 | | \li The projection parameters. |
526 | | \param hBuffer |
527 | | \li Modified to contain the horizontal reference system |
528 | | in the form of a WKT string. |
529 | | \param hBufferSize |
530 | | \li The size of the horizontal reference system buffer. |
531 | | \param vBuffer |
532 | | \li Modified to contain the vertical reference system |
533 | | in the form of a WKT string. |
534 | | \param vBufferSize |
535 | | \li The size of the vertical reference system buffer. |
536 | | \return |
537 | | \li 0 on success, else an error code. |
538 | | */ |
539 | | //************************************************************************ |
540 | | BagError bagLegacyToWkt( |
541 | | const BagLegacyReferenceSystem& system, |
542 | | char* hBuffer, |
543 | | size_t hBufferSize, |
544 | | char* vBuffer, |
545 | | size_t vBufferSize) |
546 | 0 | try |
547 | 0 | { |
548 | 0 | std::stringstream wktStream; |
549 | 0 | (void)wktStream.imbue(std::locale::classic()); |
550 | | |
551 | | //If we want the vertical system then... |
552 | 0 | if (vBuffer && vBufferSize > 0 && |
553 | 0 | strlen(system.geoParameters.vertical_datum) != 0) |
554 | 0 | { |
555 | 0 | wktStream << R"(VERT_CS[")" << system.geoParameters.vertical_datum << |
556 | 0 | R"(", VERT_DATUM[")" << system.geoParameters.vertical_datum << |
557 | 0 | R"(", 2000]])"; |
558 | | |
559 | | //Make sure our string is not too large. |
560 | 0 | if (wktStream.str().size() > vBufferSize) |
561 | 0 | wktStream.str().resize(vBufferSize); |
562 | |
|
563 | 0 | strcpy(vBuffer, wktStream.str().c_str()); |
564 | 0 | } |
565 | | |
566 | | //If we want the horizontal system then... |
567 | 0 | if (hBuffer && hBufferSize > 0) |
568 | 0 | { |
569 | 0 | switch (system.coordSys) |
570 | 0 | { |
571 | 0 | case CoordinateType::Geodetic: |
572 | 0 | { |
573 | 0 | wktStream << datumToWkt(system.geoParameters.datum, |
574 | 0 | system.geoParameters.ellipsoid); |
575 | 0 | } |
576 | 0 | break; |
577 | | |
578 | 0 | case CoordinateType::UTM: |
579 | 0 | { |
580 | | //We need to figure out what hemisphere we are in. |
581 | 0 | bool isNorth = false; |
582 | | |
583 | | //A false northing of 0.0 means north. |
584 | 0 | if (system.geoParameters.false_northing == 0.0) |
585 | 0 | isNorth = true; |
586 | | //A false northing of 10,000,000 means south. |
587 | 0 | else if (system.geoParameters.false_northing == 10'000'000) |
588 | 0 | isNorth = false; |
589 | | //If we don't have an appropriate false northing, then use the zone. |
590 | 0 | else |
591 | 0 | isNorth = (system.geoParameters.zone >= 0); |
592 | |
|
593 | 0 | wktStream << std::fixed << std::setprecision(6) |
594 | 0 | << R"(PROJCS["UTM Zone )" << abs(system.geoParameters.zone) |
595 | 0 | << ((isNorth) ? R"(, Northern Hemisphere")" : R"(, Southern Hemisphere")") |
596 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
597 | 0 | system.geoParameters.ellipsoid) |
598 | 0 | << R"(, PROJECTION["Transverse_Mercator"],)" |
599 | 0 | << R"( PARAMETER["latitude_of_origin",)" << 0 << "]," |
600 | 0 | << R"( PARAMETER["central_meridian",)" << (abs(system.geoParameters.zone) * 6 - 183) << "]," |
601 | 0 | << R"( PARAMETER["scale_factor",)" << 0.9996 << "]," |
602 | 0 | << R"( PARAMETER["false_easting",)" << 500'000 << "]," |
603 | 0 | << R"( PARAMETER["false_northing",)" << ((isNorth) ? 0 : 10'000'000) << "]," |
604 | 0 | << R"( UNIT["metre",1]])"; |
605 | 0 | } |
606 | 0 | break; |
607 | | |
608 | 0 | case CoordinateType::Albers_Equal_Area_Conic: |
609 | 0 | { |
610 | 0 | wktStream << std::fixed << std::setprecision(6) |
611 | 0 | << R"(PROJCS["unnamed")" |
612 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
613 | 0 | system.geoParameters.ellipsoid) |
614 | 0 | << R"(, PROJECTION["Albers_Conic_Equal_Area"],)" |
615 | 0 | << R"( PARAMETER["standard_parallel_1",)" << system.geoParameters.std_parallel_1 << "]," |
616 | 0 | << R"( PARAMETER["standard_parallel_2",)" << system.geoParameters.std_parallel_2 << "]," |
617 | 0 | << R"( PARAMETER["latitude_of_center",)" << system.geoParameters.latitude_of_centre << "]," |
618 | 0 | << R"( PARAMETER["longitude_of_center",)" << system.geoParameters.longitude_of_centre << "]," |
619 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
620 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
621 | 0 | << R"( UNIT["metre",1]])"; |
622 | 0 | } |
623 | 0 | break; |
624 | | |
625 | 0 | case CoordinateType::Azimuthal_Equidistant: |
626 | 0 | { |
627 | 0 | wktStream << std::fixed << std::setprecision(6) |
628 | 0 | << R"(PROJCS["unnamed")" |
629 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
630 | 0 | system.geoParameters.ellipsoid) |
631 | 0 | << R"(, PROJECTION["Azimuthal_Equidistant"],)" |
632 | 0 | << R"( PARAMETER["latitude_of_center",)" << system.geoParameters.latitude_of_centre << "]," |
633 | 0 | << R"( PARAMETER["longitude_of_center",)" << system.geoParameters.longitude_of_centre << "]," |
634 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
635 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
636 | 0 | << R"( UNIT["metre",1]])"; |
637 | 0 | } |
638 | 0 | break; |
639 | | |
640 | 0 | case CoordinateType::Bonne: |
641 | 0 | { |
642 | 0 | wktStream << std::fixed << std::setprecision(6) |
643 | 0 | << R"(PROJCS["unnamed")" |
644 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
645 | 0 | system.geoParameters.ellipsoid) |
646 | 0 | << R"(, PROJECTION["Bonne"],)" |
647 | 0 | << R"( PARAMETER["standard_parallel_1",)" << system.geoParameters.std_parallel_1 << "]," |
648 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
649 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
650 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
651 | 0 | << R"( UNIT["metre",1]])"; |
652 | 0 | } |
653 | 0 | break; |
654 | | |
655 | 0 | case CoordinateType::Cassini: |
656 | 0 | { |
657 | 0 | wktStream << std::fixed << std::setprecision(6) |
658 | 0 | << R"(PROJCS["unnamed")" |
659 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
660 | 0 | system.geoParameters.ellipsoid) |
661 | 0 | << R"(, PROJECTION["Cassini_Soldner"],)" |
662 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
663 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
664 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
665 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
666 | 0 | << R"( UNIT["metre",1]])"; |
667 | 0 | } |
668 | 0 | break; |
669 | | |
670 | 0 | case CoordinateType::Cylindrical_Equal_Area: |
671 | 0 | { |
672 | 0 | wktStream << std::fixed << std::setprecision(6) |
673 | 0 | << R"(PROJCS["unnamed")" |
674 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
675 | 0 | system.geoParameters.ellipsoid) |
676 | 0 | << R"(, PROJECTION["Cylindrical_Equal_Area"],)" |
677 | 0 | << R"( PARAMETER["standard_parallel_1",)" << system.geoParameters.std_parallel_1 << "]," |
678 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
679 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
680 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
681 | 0 | << R"( UNIT["metre",1]])"; |
682 | 0 | } |
683 | 0 | break; |
684 | | |
685 | 0 | case CoordinateType::Eckert4: |
686 | 0 | { |
687 | 0 | wktStream << std::fixed << std::setprecision(6) |
688 | 0 | << R"(PROJCS["unnamed")" |
689 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
690 | 0 | system.geoParameters.ellipsoid) |
691 | 0 | << R"(, PROJECTION["Eckert_IV"],)" |
692 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
693 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
694 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
695 | 0 | << R"( UNIT["metre",1]])"; |
696 | 0 | } |
697 | 0 | break; |
698 | | |
699 | 0 | case CoordinateType::Eckert6: |
700 | 0 | { |
701 | 0 | wktStream << std::fixed << std::setprecision(6) |
702 | 0 | << R"(PROJCS["unnamed")" |
703 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
704 | 0 | system.geoParameters.ellipsoid) |
705 | 0 | << R"(, PROJECTION["Eckert_VI"],)" |
706 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
707 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
708 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
709 | 0 | << R"( UNIT["metre",1]])"; |
710 | 0 | } |
711 | 0 | break; |
712 | | |
713 | 0 | case CoordinateType::Equidistant_Cylindrical: |
714 | 0 | { |
715 | | //Plate Caree, Equidistant Cylindrical, and Simple Cylindrical are all |
716 | | //aliases for Equirectangular. |
717 | |
|
718 | 0 | wktStream << std::fixed << std::setprecision(6) |
719 | 0 | << R"(PROJCS["unnamed")" |
720 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
721 | 0 | system.geoParameters.ellipsoid) |
722 | 0 | << R"(, PROJECTION["Equirectangular"],)" |
723 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
724 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
725 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
726 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
727 | 0 | << R"( UNIT["metre",1]])"; |
728 | 0 | } |
729 | 0 | break; |
730 | | |
731 | 0 | case CoordinateType::Gnomonic: |
732 | 0 | { |
733 | 0 | wktStream << std::fixed << std::setprecision(6) |
734 | 0 | << R"(PROJCS["unnamed")" |
735 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
736 | 0 | system.geoParameters.ellipsoid) |
737 | 0 | << R"(, PROJECTION["Gnomonic"],)" |
738 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
739 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
740 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
741 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
742 | 0 | << R"( UNIT["metre",1]])"; |
743 | 0 | } |
744 | 0 | break; |
745 | | |
746 | 0 | case CoordinateType::Lambert_Conformal_Conic: |
747 | 0 | { |
748 | 0 | wktStream << std::fixed << std::setprecision(6) |
749 | 0 | << R"(PROJCS["unnamed")" |
750 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
751 | 0 | system.geoParameters.ellipsoid) |
752 | 0 | << R"(, PROJECTION["Lambert_Conformal_Conic_2SP"],)" |
753 | 0 | << R"( PARAMETER["standard_parallel_1",)" << system.geoParameters.std_parallel_1 << "]," |
754 | 0 | << R"( PARAMETER["standard_parallel_2",)" << system.geoParameters.std_parallel_2 << "]," |
755 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
756 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
757 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
758 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
759 | 0 | << R"( UNIT["metre",1]])"; |
760 | 0 | } |
761 | 0 | break; |
762 | | |
763 | 0 | case CoordinateType::Mercator: |
764 | 0 | { |
765 | 0 | wktStream << std::fixed << std::setprecision(6) |
766 | 0 | << R"(PROJCS["unnamed")" |
767 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
768 | 0 | system.geoParameters.ellipsoid) |
769 | 0 | << R"(, PROJECTION["Mercator_1SP"],)" |
770 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
771 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
772 | 0 | << R"( PARAMETER["scale_factor",)" << system.geoParameters.scale_factor << "]," |
773 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
774 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
775 | 0 | << R"( UNIT["metre",1]])"; |
776 | 0 | } |
777 | 0 | break; |
778 | | |
779 | 0 | case CoordinateType::Miller_Cylindrical: |
780 | 0 | { |
781 | 0 | wktStream << std::fixed << std::setprecision(6) |
782 | 0 | << R"(PROJCS["unnamed")" |
783 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
784 | 0 | system.geoParameters.ellipsoid) |
785 | 0 | << R"(, PROJECTION["Miller_Cylindrical"],)" |
786 | 0 | << R"( PARAMETER["latitude_of_center",)" << system.geoParameters.latitude_of_centre << "]," |
787 | 0 | << R"( PARAMETER["longitude_of_center",)" << system.geoParameters.longitude_of_centre << "]," |
788 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
789 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
790 | 0 | << R"( UNIT["metre",1]])"; |
791 | 0 | } |
792 | 0 | break; |
793 | | |
794 | 0 | case CoordinateType::Mollweide: |
795 | 0 | { |
796 | 0 | wktStream << std::fixed << std::setprecision(6) |
797 | 0 | << R"(PROJCS["unnamed")" |
798 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
799 | 0 | system.geoParameters.ellipsoid) |
800 | 0 | << R"(, PROJECTION["Mollweide"],)" |
801 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
802 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
803 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
804 | 0 | << R"( UNIT["metre",1]])"; |
805 | 0 | } |
806 | 0 | break; |
807 | | |
808 | 0 | case CoordinateType::NZMG: |
809 | 0 | { |
810 | 0 | wktStream << std::fixed << std::setprecision(6) |
811 | 0 | << R"(PROJCS["unnamed")" |
812 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
813 | 0 | system.geoParameters.ellipsoid) |
814 | 0 | << R"(, PROJECTION["New_Zealand_Map_Grid"],)" |
815 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
816 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
817 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
818 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
819 | 0 | << R"( UNIT["metre",1]])"; |
820 | 0 | } |
821 | 0 | break; |
822 | | |
823 | 0 | case CoordinateType::Orthographic: |
824 | 0 | { |
825 | 0 | wktStream << std::fixed << std::setprecision(6) |
826 | 0 | << R"(PROJCS["unnamed")" |
827 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
828 | 0 | system.geoParameters.ellipsoid) |
829 | 0 | << R"(, PROJECTION["Orthographic"],)" |
830 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
831 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
832 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
833 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
834 | 0 | << R"( UNIT["metre",1]])"; |
835 | 0 | } |
836 | 0 | break; |
837 | | |
838 | 0 | case CoordinateType::Polar_Stereo: |
839 | 0 | { |
840 | 0 | wktStream << std::fixed << std::setprecision(6) |
841 | 0 | << R"(PROJCS["unnamed")" |
842 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
843 | 0 | system.geoParameters.ellipsoid) |
844 | 0 | << R"(, PROJECTION["Polar_Stereographic"],)" |
845 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
846 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
847 | 0 | << R"( PARAMETER["scale_factor",)" << system.geoParameters.scale_factor << "]," |
848 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
849 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
850 | 0 | << R"( UNIT["metre",1]])"; |
851 | 0 | } |
852 | 0 | break; |
853 | | |
854 | 0 | case CoordinateType::Polyconic: |
855 | 0 | { |
856 | 0 | wktStream << std::fixed << std::setprecision(6) |
857 | 0 | << R"(PROJCS["unnamed")" |
858 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
859 | 0 | system.geoParameters.ellipsoid) |
860 | 0 | << R"(, PROJECTION["Polyconic"],)" |
861 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
862 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
863 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
864 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
865 | 0 | << R"( UNIT["metre",1]])"; |
866 | 0 | } |
867 | 0 | break; |
868 | | |
869 | 0 | case CoordinateType::Sinusoidal: |
870 | 0 | { |
871 | 0 | wktStream << std::fixed << std::setprecision(6) |
872 | 0 | << R"(PROJCS["unnamed")" |
873 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
874 | 0 | system.geoParameters.ellipsoid) |
875 | 0 | << R"(, PROJECTION["Sinusoidal"],)" |
876 | 0 | << R"( PARAMETER["longitude_of_center",)" << system.geoParameters.longitude_of_centre << "]," |
877 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
878 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
879 | 0 | << R"( UNIT["metre",1]])"; |
880 | 0 | } |
881 | 0 | break; |
882 | | |
883 | 0 | case CoordinateType::Stereographic: |
884 | 0 | { |
885 | 0 | wktStream << std::fixed << std::setprecision(6) |
886 | 0 | << R"(PROJCS["unnamed")" |
887 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
888 | 0 | system.geoParameters.ellipsoid) |
889 | 0 | << R"(, PROJECTION["Oblique_Stereographic"],)" |
890 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
891 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
892 | 0 | << R"( PARAMETER["scale_factor",)" << system.geoParameters.scale_factor << "]," |
893 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
894 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
895 | 0 | << R"( UNIT["metre",1]])"; |
896 | 0 | } |
897 | 0 | break; |
898 | | |
899 | 0 | case CoordinateType::Transverse_Mercator: |
900 | 0 | { |
901 | 0 | wktStream << std::fixed << std::setprecision(6) |
902 | 0 | << R"(PROJCS["unnamed")" |
903 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
904 | 0 | system.geoParameters.ellipsoid) |
905 | 0 | << R"(, PROJECTION["Transverse_Mercator"],)" |
906 | 0 | << R"( PARAMETER["latitude_of_origin",)" << system.geoParameters.origin_latitude << "]," |
907 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
908 | 0 | << R"( PARAMETER["scale_factor",)" << system.geoParameters.scale_factor << "]," |
909 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
910 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
911 | 0 | << R"( UNIT["metre",1]])"; |
912 | 0 | } |
913 | 0 | break; |
914 | | |
915 | 0 | case CoordinateType::Van_der_Grinten: |
916 | 0 | { |
917 | 0 | wktStream << std::fixed << std::setprecision(6) |
918 | 0 | << R"(PROJCS["unnamed")" |
919 | 0 | << ", " << datumToWkt(system.geoParameters.datum, |
920 | 0 | system.geoParameters.ellipsoid) |
921 | 0 | << R"(, PROJECTION["VanDerGrinten"],)" |
922 | 0 | << R"( PARAMETER["central_meridian",)" << system.geoParameters.central_meridian << "]," |
923 | 0 | << R"( PARAMETER["false_easting",)" << system.geoParameters.false_easting << "]," |
924 | 0 | << R"( PARAMETER["false_northing",)" << system.geoParameters.false_northing << "]," |
925 | 0 | << R"( UNIT["metre",1]])"; |
926 | 0 | } |
927 | 0 | break; |
928 | | |
929 | 0 | default: |
930 | 0 | { |
931 | | //Currently unsupported type. |
932 | 0 | return BAG_METADTA_INVALID_PROJECTION; |
933 | 0 | } |
934 | |
|
935 | 0 | } |
936 | | |
937 | 0 | if (wktStream.str().size() > hBufferSize) |
938 | 0 | wktStream.str().resize(hBufferSize); |
939 | |
|
940 | 0 | strcpy(hBuffer, wktStream.str().c_str()); |
941 | 0 | } |
942 | | |
943 | 0 | return 0; |
944 | 0 | } |
945 | 0 | catch (const InvalidDatumError &/*e*/) |
946 | 0 | { |
947 | 0 | return BAG_METADTA_INVALID_DATUM; |
948 | 0 | } |
949 | 0 | catch (const std::exception &/*e*/) |
950 | 0 | { |
951 | | //Something bad happened. |
952 | 0 | return BAG_METADTA_INVALID_PROJECTION; |
953 | 0 | } |
954 | | |
955 | | |
956 | | |
957 | | |
958 | | /* function: bagCoordsys |
959 | | purpose: taken from geotrans' engine.h from their Coordinate Type |
960 | | Enumeration we have a matching string set. have included all |
961 | | coordinate sys types here although we only are supporting |
962 | | 0, 5, 6, 17, 18, 25, and 30 initially. |
963 | | |
964 | | author: dave fabre, us naval oceanographic office, jul 2005 |
965 | | */ |
966 | | |
967 | | static const char* COORDINATE_SYS_LIST[]= |
968 | | { |
969 | | "Geodetic", |
970 | | "GEOREF", |
971 | | "Geocentric", |
972 | | "Local_Cartesian", |
973 | | "MGRS", |
974 | | "UTM", |
975 | | "UPS", |
976 | | "Albers_Equal_Area_Conic", |
977 | | "Azimuthal_Equidistant", |
978 | | "BNG", |
979 | | "Bonne", |
980 | | "Cassini", |
981 | | "Cylindrical_Equal_Area", |
982 | | "Eckert4", |
983 | | "Eckert6", |
984 | | "Equidistant_Cylindrical", |
985 | | "Gnomonic", |
986 | | "Lambert_Conformal_Conic", |
987 | | "Mercator", |
988 | | "Miller_Cylindrical", |
989 | | "Mollweide", |
990 | | "Neys", |
991 | | "NZMG", |
992 | | "Oblique_Mercator", |
993 | | "Orthographic", |
994 | | "Polar_Stereo", |
995 | | "Polyconic", |
996 | | "Sinusoidal", |
997 | | "Stereographic", |
998 | | "Transverse_Cylindrical_Equal_Area", |
999 | | "Transverse_Mercator", |
1000 | | "Van_der_Grinten" |
1001 | | }; |
1002 | | |
1003 | | /******************************************************************************/ |
1004 | | CoordinateType bagCoordsys(const char* str) noexcept |
1005 | 0 | { |
1006 | 0 | constexpr auto MAX_NCOORD_SYS = 32; |
1007 | 0 | #define COORD_SYS_NAME(k) COORDINATE_SYS_LIST[k] |
1008 | |
|
1009 | 0 | for (size_t i = 0; i < MAX_NCOORD_SYS; i++) |
1010 | 0 | if (strncmp(str, COORD_SYS_NAME(i), strlen(COORD_SYS_NAME(i))) == 0 ) |
1011 | 0 | return static_cast<CoordinateType>(i); |
1012 | | |
1013 | 0 | return CoordinateType::Unknown; |
1014 | 0 | } |
1015 | | |
1016 | | |
1017 | | |
1018 | | |
1019 | | static const char* DATUM_NAME_LIST[] = |
1020 | | { |
1021 | | "WGS84", |
1022 | | "WGS72", |
1023 | | "NAD83" |
1024 | | }; |
1025 | | |
1026 | | /******************************************************************************/ |
1027 | | BagDatum bagDatumID(const char* str) noexcept |
1028 | 0 | { |
1029 | 0 | constexpr auto MAX_DATUMS = 3; |
1030 | 0 | #define DATUM_NAME(k) DATUM_NAME_LIST[k] |
1031 | |
|
1032 | 0 | for (uint32_t i = 0; i < MAX_DATUMS; i++) |
1033 | 0 | if (strncmp(str, DATUM_NAME(i), strlen(DATUM_NAME(i))) == 0) |
1034 | 0 | return static_cast<BagDatum>(i); |
1035 | | |
1036 | 0 | return BagDatum::unknown; |
1037 | 0 | } |
1038 | | |
1039 | | } // namespace BAG |
1040 | | |