1 /******************************************************************************
2 *
3 * Project: PROJ
4 * Purpose: Test ISO19111:2019 implementation
5 * Author: Even Rouault <even dot rouault at spatialys dot com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "gtest_include.h"
30
31 // to be able to use internal::replaceAll
32 #ifndef FROM_PROJ_CPP
33 #define FROM_PROJ_CPP
34 #endif
35
36 #include "proj/common.hpp"
37 #include "proj/coordinateoperation.hpp"
38 #include "proj/coordinatesystem.hpp"
39 #include "proj/crs.hpp"
40 #include "proj/datum.hpp"
41 #include "proj/io.hpp"
42 #include "proj/metadata.hpp"
43 #include "proj/util.hpp"
44
45 #include "proj/internal/internal.hpp"
46
47 #include "proj_constants.h"
48
49 #include <string>
50 #include <vector>
51
52 using namespace osgeo::proj::common;
53 using namespace osgeo::proj::crs;
54 using namespace osgeo::proj::cs;
55 using namespace osgeo::proj::datum;
56 using namespace osgeo::proj::io;
57 using namespace osgeo::proj::internal;
58 using namespace osgeo::proj::metadata;
59 using namespace osgeo::proj::operation;
60 using namespace osgeo::proj::util;
61
62 namespace {
63 struct UnrelatedObject : public IComparable {
64 UnrelatedObject() = default;
65
_isEquivalentTo__anon321e84e00111::UnrelatedObject66 bool _isEquivalentTo(const IComparable *, Criterion,
67 const DatabaseContextPtr &) const override {
68 assert(false);
69 return false;
70 }
71 };
72
createUnrelatedObject()73 static nn<std::shared_ptr<UnrelatedObject>> createUnrelatedObject() {
74 return nn_make_shared<UnrelatedObject>();
75 }
76 } // namespace
77
78 // ---------------------------------------------------------------------------
79
TEST(operation,method)80 TEST(operation, method) {
81
82 auto method = OperationMethod::create(
83 PropertyMap(), std::vector<OperationParameterNNPtr>{});
84 EXPECT_TRUE(method->isEquivalentTo(method.get()));
85 EXPECT_FALSE(method->isEquivalentTo(createUnrelatedObject().get()));
86 auto otherMethod = OperationMethod::create(
87 PropertyMap(),
88 std::vector<OperationParameterNNPtr>{OperationParameter::create(
89 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))});
90 EXPECT_TRUE(otherMethod->isEquivalentTo(otherMethod.get()));
91 EXPECT_FALSE(method->isEquivalentTo(otherMethod.get()));
92 auto otherMethod2 = OperationMethod::create(
93 PropertyMap(),
94 std::vector<OperationParameterNNPtr>{OperationParameter::create(
95 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"))});
96 EXPECT_FALSE(otherMethod->isEquivalentTo(otherMethod2.get()));
97 EXPECT_FALSE(otherMethod->isEquivalentTo(
98 otherMethod2.get(), IComparable::Criterion::EQUIVALENT));
99 }
100
101 // ---------------------------------------------------------------------------
102
TEST(operation,method_parameter_different_order)103 TEST(operation, method_parameter_different_order) {
104
105 auto method1 = OperationMethod::create(
106 PropertyMap(), std::vector<OperationParameterNNPtr>{
107 OperationParameter::create(PropertyMap().set(
108 IdentifiedObject::NAME_KEY, "paramName")),
109 OperationParameter::create(PropertyMap().set(
110 IdentifiedObject::NAME_KEY, "paramName2"))});
111
112 auto method2 = OperationMethod::create(
113 PropertyMap(), std::vector<OperationParameterNNPtr>{
114 OperationParameter::create(PropertyMap().set(
115 IdentifiedObject::NAME_KEY, "paramName2")),
116 OperationParameter::create(PropertyMap().set(
117 IdentifiedObject::NAME_KEY, "paramName"))});
118
119 auto method3 = OperationMethod::create(
120 PropertyMap(), std::vector<OperationParameterNNPtr>{
121 OperationParameter::create(PropertyMap().set(
122 IdentifiedObject::NAME_KEY, "paramName3")),
123 OperationParameter::create(PropertyMap().set(
124 IdentifiedObject::NAME_KEY, "paramName"))});
125
126 EXPECT_FALSE(method1->isEquivalentTo(method2.get()));
127 EXPECT_TRUE(method1->isEquivalentTo(method2.get(),
128 IComparable::Criterion::EQUIVALENT));
129 EXPECT_FALSE(method1->isEquivalentTo(method3.get(),
130 IComparable::Criterion::EQUIVALENT));
131 }
132
133 // ---------------------------------------------------------------------------
134
TEST(operation,ParameterValue)135 TEST(operation, ParameterValue) {
136
137 auto valStr1 = ParameterValue::create("str1");
138 auto valStr2 = ParameterValue::create("str2");
139 EXPECT_TRUE(valStr1->isEquivalentTo(valStr1.get()));
140 EXPECT_FALSE(valStr1->isEquivalentTo(createUnrelatedObject().get()));
141 EXPECT_FALSE(valStr1->isEquivalentTo(valStr2.get()));
142
143 auto valMeasure1 = ParameterValue::create(Angle(-90.0));
144 auto valMeasure1Eps = ParameterValue::create(Angle(-90.0 - 1e-11));
145 auto valMeasure2 = ParameterValue::create(Angle(-89.0));
146 EXPECT_TRUE(valMeasure1->isEquivalentTo(valMeasure1.get()));
147 EXPECT_TRUE(valMeasure1->isEquivalentTo(
148 valMeasure1.get(), IComparable::Criterion::EQUIVALENT));
149 EXPECT_FALSE(valMeasure1->isEquivalentTo(valMeasure1Eps.get()));
150 EXPECT_TRUE(valMeasure1->isEquivalentTo(
151 valMeasure1Eps.get(), IComparable::Criterion::EQUIVALENT));
152
153 EXPECT_FALSE(valMeasure1->isEquivalentTo(valStr1.get()));
154 EXPECT_FALSE(valMeasure1->isEquivalentTo(valMeasure2.get()));
155 EXPECT_FALSE(valMeasure1->isEquivalentTo(
156 valMeasure2.get(), IComparable::Criterion::EQUIVALENT));
157
158 auto valInt1 = ParameterValue::create(1);
159 auto valInt2 = ParameterValue::create(2);
160 EXPECT_TRUE(valInt1->isEquivalentTo(valInt1.get()));
161 EXPECT_FALSE(valInt1->isEquivalentTo(valInt2.get()));
162
163 auto valTrue = ParameterValue::create(true);
164 auto valFalse = ParameterValue::create(false);
165 EXPECT_TRUE(valTrue->isEquivalentTo(valTrue.get()));
166 EXPECT_FALSE(valTrue->isEquivalentTo(valFalse.get()));
167 }
168
169 // ---------------------------------------------------------------------------
170
TEST(operation,OperationParameter)171 TEST(operation, OperationParameter) {
172
173 auto op1 = OperationParameter::create(
174 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"));
175 auto op2 = OperationParameter::create(
176 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"));
177 EXPECT_TRUE(op1->isEquivalentTo(op1.get()));
178 EXPECT_FALSE(op1->isEquivalentTo(createUnrelatedObject().get()));
179 EXPECT_FALSE(op1->isEquivalentTo(op2.get()));
180 }
181
182 // ---------------------------------------------------------------------------
183
TEST(operation,OperationParameterValue)184 TEST(operation, OperationParameterValue) {
185
186 auto op1 = OperationParameter::create(
187 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"));
188 auto op2 = OperationParameter::create(
189 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"));
190 auto valStr1 = ParameterValue::create("str1");
191 auto valStr2 = ParameterValue::create("str2");
192 auto opv11 = OperationParameterValue::create(op1, valStr1);
193 EXPECT_TRUE(opv11->isEquivalentTo(opv11.get()));
194 EXPECT_FALSE(opv11->isEquivalentTo(createUnrelatedObject().get()));
195 auto opv12 = OperationParameterValue::create(op1, valStr2);
196 EXPECT_FALSE(opv11->isEquivalentTo(opv12.get()));
197 auto opv21 = OperationParameterValue::create(op2, valStr1);
198 EXPECT_FALSE(opv11->isEquivalentTo(opv12.get()));
199 }
200
201 // ---------------------------------------------------------------------------
202
TEST(operation,SingleOperation)203 TEST(operation, SingleOperation) {
204
205 auto sop1 = Transformation::create(
206 PropertyMap(), nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
207 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807),
208 static_cast<CRSPtr>(GeographicCRS::EPSG_4979.as_nullable()),
209 PropertyMap(),
210 std::vector<OperationParameterNNPtr>{OperationParameter::create(
211 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
212 std::vector<ParameterValueNNPtr>{
213 ParameterValue::createFilename("foo.bin")},
214 std::vector<PositionalAccuracyNNPtr>{
215 PositionalAccuracy::create("0.1")});
216
217 EXPECT_TRUE(sop1->isEquivalentTo(sop1.get()));
218 EXPECT_FALSE(sop1->isEquivalentTo(createUnrelatedObject().get()));
219
220 EXPECT_TRUE(
221 sop1->isEquivalentTo(sop1->CoordinateOperation::shallowClone().get()));
222 EXPECT_TRUE(sop1->inverse()->isEquivalentTo(
223 sop1->inverse()->CoordinateOperation::shallowClone().get()));
224
225 auto sop2 = Transformation::create(
226 PropertyMap(), nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
227 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807),
228 static_cast<CRSPtr>(GeographicCRS::EPSG_4979.as_nullable()),
229 PropertyMap(),
230 std::vector<OperationParameterNNPtr>{OperationParameter::create(
231 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"))},
232 std::vector<ParameterValueNNPtr>{
233 ParameterValue::createFilename("foo.bin")},
234 std::vector<PositionalAccuracyNNPtr>{
235 PositionalAccuracy::create("0.1")});
236 EXPECT_FALSE(sop1->isEquivalentTo(sop2.get()));
237
238 auto sop3 = Transformation::create(
239 PropertyMap(), nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
240 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807),
241 static_cast<CRSPtr>(GeographicCRS::EPSG_4979.as_nullable()),
242 PropertyMap(),
243 std::vector<OperationParameterNNPtr>{
244 OperationParameter::create(
245 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName")),
246 OperationParameter::create(
247 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"))},
248 std::vector<ParameterValueNNPtr>{
249 ParameterValue::createFilename("foo.bin"),
250 ParameterValue::createFilename("foo2.bin")},
251 std::vector<PositionalAccuracyNNPtr>{
252 PositionalAccuracy::create("0.1")});
253 EXPECT_FALSE(sop1->isEquivalentTo(sop3.get()));
254
255 auto sop4 = Transformation::create(
256 PropertyMap(), nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
257 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807),
258 static_cast<CRSPtr>(GeographicCRS::EPSG_4979.as_nullable()),
259 PropertyMap(),
260 std::vector<OperationParameterNNPtr>{OperationParameter::create(
261 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
262 std::vector<ParameterValueNNPtr>{
263 ParameterValue::createFilename("foo2.bin")},
264 std::vector<PositionalAccuracyNNPtr>{
265 PositionalAccuracy::create("0.1")});
266 EXPECT_FALSE(sop1->isEquivalentTo(sop4.get()));
267 }
268
269 // ---------------------------------------------------------------------------
270
TEST(operation,SingleOperation_different_order)271 TEST(operation, SingleOperation_different_order) {
272
273 auto sop1 = Transformation::create(
274 PropertyMap().set(IdentifiedObject::NAME_KEY, "ignored1"),
275 GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4807, nullptr,
276 PropertyMap(),
277 std::vector<OperationParameterNNPtr>{
278 OperationParameter::create(
279 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName")),
280 OperationParameter::create(
281 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"))},
282 std::vector<ParameterValueNNPtr>{
283 ParameterValue::createFilename("foo.bin"),
284 ParameterValue::createFilename("foo2.bin")},
285 {});
286
287 auto sop2 = Transformation::create(
288 PropertyMap().set(IdentifiedObject::NAME_KEY, "ignored2"),
289 GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4807, nullptr,
290 PropertyMap(),
291 std::vector<OperationParameterNNPtr>{
292 OperationParameter::create(
293 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2")),
294 OperationParameter::create(
295 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
296 std::vector<ParameterValueNNPtr>{
297 ParameterValue::createFilename("foo2.bin"),
298 ParameterValue::createFilename("foo.bin")},
299 {});
300
301 auto sop3 = Transformation::create(
302 PropertyMap().set(IdentifiedObject::NAME_KEY, "ignored3"),
303 GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4807, nullptr,
304 PropertyMap(),
305 std::vector<OperationParameterNNPtr>{
306 OperationParameter::create(
307 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName")),
308 OperationParameter::create(
309 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName2"))},
310 std::vector<ParameterValueNNPtr>{
311 ParameterValue::createFilename("foo2.bin"),
312 ParameterValue::createFilename("foo.bin")},
313 {});
314
315 EXPECT_FALSE(sop1->isEquivalentTo(sop2.get()));
316 EXPECT_TRUE(
317 sop1->isEquivalentTo(sop2.get(), IComparable::Criterion::EQUIVALENT));
318 EXPECT_FALSE(
319 sop1->isEquivalentTo(sop3.get(), IComparable::Criterion::EQUIVALENT));
320 }
321
322 // ---------------------------------------------------------------------------
323
TEST(operation,transformation_to_wkt)324 TEST(operation, transformation_to_wkt) {
325 PropertyMap propertiesTransformation;
326 propertiesTransformation
327 .set(Identifier::CODESPACE_KEY, "codeSpaceTransformation")
328 .set(Identifier::CODE_KEY, "codeTransformation")
329 .set(IdentifiedObject::NAME_KEY, "transformationName")
330 .set(IdentifiedObject::REMARKS_KEY, "my remarks");
331
332 auto transf = Transformation::create(
333 propertiesTransformation,
334 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
335 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807),
336 static_cast<CRSPtr>(GeographicCRS::EPSG_4979.as_nullable()),
337 PropertyMap()
338 .set(Identifier::CODESPACE_KEY, "codeSpaceOperationMethod")
339 .set(Identifier::CODE_KEY, "codeOperationMethod")
340 .set(IdentifiedObject::NAME_KEY, "operationMethodName"),
341 std::vector<OperationParameterNNPtr>{OperationParameter::create(
342 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
343 std::vector<ParameterValueNNPtr>{
344 ParameterValue::createFilename("foo.bin")},
345 std::vector<PositionalAccuracyNNPtr>{
346 PositionalAccuracy::create("0.1")});
347
348 std::string src_wkt;
349 {
350 auto formatter = WKTFormatter::create();
351 formatter->setOutputId(false);
352 src_wkt = GeographicCRS::EPSG_4326->exportToWKT(formatter.get());
353 }
354
355 std::string dst_wkt;
356 {
357 auto formatter = WKTFormatter::create();
358 formatter->setOutputId(false);
359 dst_wkt = GeographicCRS::EPSG_4807->exportToWKT(formatter.get());
360 }
361
362 std::string interpolation_wkt;
363 {
364 auto formatter = WKTFormatter::create();
365 formatter->setOutputId(false);
366 interpolation_wkt =
367 GeographicCRS::EPSG_4979->exportToWKT(formatter.get());
368 }
369
370 auto expected =
371 "COORDINATEOPERATION[\"transformationName\",\n"
372 " SOURCECRS[" +
373 src_wkt + "],\n"
374 " TARGETCRS[" +
375 dst_wkt +
376 "],\n"
377 " METHOD[\"operationMethodName\",\n"
378 " ID[\"codeSpaceOperationMethod\",\"codeOperationMethod\"]],\n"
379 " PARAMETERFILE[\"paramName\",\"foo.bin\"],\n"
380 " INTERPOLATIONCRS[" +
381 interpolation_wkt +
382 "],\n"
383 " OPERATIONACCURACY[0.1],\n"
384 " ID[\"codeSpaceTransformation\",\"codeTransformation\"],\n"
385 " REMARK[\"my remarks\"]]";
386
387 EXPECT_EQ(
388 replaceAll(replaceAll(transf->exportToWKT(WKTFormatter::create().get()),
389 " ", ""),
390 "\n", ""),
391 replaceAll(replaceAll(expected, " ", ""), "\n", ""));
392
393 EXPECT_THROW(
394 transf->exportToWKT(
395 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
396 FormattingException);
397
398 EXPECT_TRUE(transf->isEquivalentTo(transf.get()));
399 EXPECT_FALSE(transf->isEquivalentTo(createUnrelatedObject().get()));
400 }
401
402 // ---------------------------------------------------------------------------
403
TEST(operation,concatenated_operation)404 TEST(operation, concatenated_operation) {
405
406 PropertyMap propertiesTransformation;
407 propertiesTransformation
408 .set(Identifier::CODESPACE_KEY, "codeSpaceTransformation")
409 .set(Identifier::CODE_KEY, "codeTransformation")
410 .set(IdentifiedObject::NAME_KEY, "transformationName")
411 .set(IdentifiedObject::REMARKS_KEY, "my remarks");
412
413 auto transf_1 = Transformation::create(
414 propertiesTransformation,
415 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
416 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807), nullptr,
417 PropertyMap().set(IdentifiedObject::NAME_KEY, "operationMethodName"),
418 std::vector<OperationParameterNNPtr>{OperationParameter::create(
419 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
420 std::vector<ParameterValueNNPtr>{
421 ParameterValue::createFilename("foo.bin")},
422 std::vector<PositionalAccuracyNNPtr>());
423
424 auto transf_2 = Transformation::create(
425 propertiesTransformation,
426 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4807),
427 nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4979), nullptr,
428 PropertyMap().set(IdentifiedObject::NAME_KEY, "operationMethodName"),
429 std::vector<OperationParameterNNPtr>{OperationParameter::create(
430 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
431 std::vector<ParameterValueNNPtr>{
432 ParameterValue::createFilename("foo.bin")},
433 std::vector<PositionalAccuracyNNPtr>());
434
435 auto concat = ConcatenatedOperation::create(
436 PropertyMap()
437 .set(Identifier::CODESPACE_KEY, "codeSpace")
438 .set(Identifier::CODE_KEY, "code")
439 .set(IdentifiedObject::NAME_KEY, "name")
440 .set(IdentifiedObject::REMARKS_KEY, "my remarks"),
441 std::vector<CoordinateOperationNNPtr>{transf_1, transf_2},
442 std::vector<PositionalAccuracyNNPtr>{
443 PositionalAccuracy::create("0.1")});
444
445 std::string src_wkt;
446 {
447 auto formatter =
448 WKTFormatter::create(WKTFormatter::Convention::WKT2_2019);
449 src_wkt = GeographicCRS::EPSG_4326->exportToWKT(formatter.get());
450 }
451
452 std::string dst_wkt;
453 {
454 auto formatter =
455 WKTFormatter::create(WKTFormatter::Convention::WKT2_2019);
456 dst_wkt = GeographicCRS::EPSG_4979->exportToWKT(formatter.get());
457 }
458
459 std::string step1_wkt;
460 {
461 auto formatter =
462 WKTFormatter::create(WKTFormatter::Convention::WKT2_2019);
463 step1_wkt = transf_1->exportToWKT(formatter.get());
464 }
465
466 std::string step2_wkt;
467 {
468 auto formatter =
469 WKTFormatter::create(WKTFormatter::Convention::WKT2_2019);
470 step2_wkt = transf_2->exportToWKT(formatter.get());
471 }
472
473 auto expected = "CONCATENATEDOPERATION[\"name\",\n"
474 " SOURCECRS[" +
475 src_wkt + "],\n"
476 " TARGETCRS[" +
477 dst_wkt + "],\n"
478 " STEP[" +
479 step1_wkt + "],\n"
480 " STEP[" +
481 step2_wkt + "],\n"
482 " ID[\"codeSpace\",\"code\"],\n"
483 " REMARK[\"my remarks\"]]";
484
485 EXPECT_EQ(replaceAll(replaceAll(concat->exportToWKT(
486 WKTFormatter::create(
487 WKTFormatter::Convention::WKT2_2019)
488 .get()),
489 " ", ""),
490 "\n", ""),
491 replaceAll(replaceAll(expected, " ", ""), "\n", ""));
492
493 EXPECT_THROW(concat->exportToWKT(WKTFormatter::create().get()),
494 FormattingException);
495
496 EXPECT_THROW(ConcatenatedOperation::create(
497 PropertyMap().set(IdentifiedObject::NAME_KEY, "name"),
498 std::vector<CoordinateOperationNNPtr>{transf_1, transf_1},
499 std::vector<PositionalAccuracyNNPtr>()),
500 InvalidOperation);
501
502 auto inv = concat->inverse();
503 EXPECT_EQ(inv->nameStr(), "Inverse of name");
504 EXPECT_EQ(inv->sourceCRS()->nameStr(), concat->targetCRS()->nameStr());
505 EXPECT_EQ(inv->targetCRS()->nameStr(), concat->sourceCRS()->nameStr());
506 auto inv_as_concat = nn_dynamic_pointer_cast<ConcatenatedOperation>(inv);
507 ASSERT_TRUE(inv_as_concat != nullptr);
508
509 ASSERT_EQ(inv_as_concat->operations().size(), 2U);
510 EXPECT_EQ(inv_as_concat->operations()[0]->nameStr(),
511 "Inverse of transformationName");
512 EXPECT_EQ(inv_as_concat->operations()[1]->nameStr(),
513 "Inverse of transformationName");
514
515 EXPECT_TRUE(concat->isEquivalentTo(concat.get()));
516 EXPECT_FALSE(concat->isEquivalentTo(createUnrelatedObject().get()));
517 EXPECT_TRUE(concat->isEquivalentTo(
518 concat->CoordinateOperation::shallowClone().get()));
519 EXPECT_FALSE(
520 ConcatenatedOperation::create(PropertyMap(),
521 std::vector<CoordinateOperationNNPtr>{
522 transf_1, transf_1->inverse()},
523 std::vector<PositionalAccuracyNNPtr>())
524 ->isEquivalentTo(ConcatenatedOperation::create(
525 PropertyMap(),
526 std::vector<CoordinateOperationNNPtr>{
527 transf_1->inverse(), transf_1},
528 std::vector<PositionalAccuracyNNPtr>())
529 .get()));
530 EXPECT_FALSE(
531 ConcatenatedOperation::create(PropertyMap(),
532 std::vector<CoordinateOperationNNPtr>{
533 transf_1, transf_1->inverse()},
534 std::vector<PositionalAccuracyNNPtr>())
535 ->isEquivalentTo(ConcatenatedOperation::create(
536 PropertyMap(),
537 std::vector<CoordinateOperationNNPtr>{
538 transf_1, transf_1->inverse(), transf_1},
539 std::vector<PositionalAccuracyNNPtr>())
540 .get()));
541 }
542
543 // ---------------------------------------------------------------------------
544
TEST(operation,transformation_createGeocentricTranslations)545 TEST(operation, transformation_createGeocentricTranslations) {
546
547 auto transf = Transformation::createGeocentricTranslations(
548 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
549 2.0, 3.0, std::vector<PositionalAccuracyNNPtr>());
550 EXPECT_TRUE(transf->validateParameters().empty());
551
552 auto params = transf->getTOWGS84Parameters();
553 auto expected = std::vector<double>{1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0};
554 EXPECT_EQ(params, expected);
555
556 auto inv_transf = transf->inverse();
557 auto inv_transf_as_transf =
558 nn_dynamic_pointer_cast<Transformation>(inv_transf);
559 ASSERT_TRUE(inv_transf_as_transf != nullptr);
560
561 EXPECT_EQ(transf->sourceCRS()->nameStr(),
562 inv_transf_as_transf->targetCRS()->nameStr());
563 EXPECT_EQ(transf->targetCRS()->nameStr(),
564 inv_transf_as_transf->sourceCRS()->nameStr());
565 auto expected_inv =
566 std::vector<double>{-1.0, -2.0, -3.0, 0.0, 0.0, 0.0, 0.0};
567 EXPECT_EQ(inv_transf_as_transf->getTOWGS84Parameters(), expected_inv);
568
569 EXPECT_EQ(transf->exportToPROJString(PROJStringFormatter::create().get()),
570 "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
571 "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 "
572 "+step +proj=cart +ellps=GRS80 +step +proj=helmert +x=1 +y=2 "
573 "+z=3 +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 "
574 "+step +proj=unitconvert +xy_in=rad +xy_out=deg +step "
575 "+proj=axisswap +order=2,1");
576 }
577
578 // ---------------------------------------------------------------------------
579
createGeocentricDatumWGS84()580 static GeodeticCRSNNPtr createGeocentricDatumWGS84() {
581 PropertyMap propertiesCRS;
582 propertiesCRS.set(Identifier::CODESPACE_KEY, "EPSG")
583 .set(Identifier::CODE_KEY, 4328)
584 .set(IdentifiedObject::NAME_KEY, "WGS 84");
585 return GeodeticCRS::create(
586 propertiesCRS, GeodeticReferenceFrame::EPSG_6326,
587 CartesianCS::createGeocentric(UnitOfMeasure::METRE));
588 }
589
590 // ---------------------------------------------------------------------------
591
createGeocentricKM()592 static GeodeticCRSNNPtr createGeocentricKM() {
593 PropertyMap propertiesCRS;
594 propertiesCRS.set(IdentifiedObject::NAME_KEY, "Based on WGS 84");
595 return GeodeticCRS::create(
596 propertiesCRS, GeodeticReferenceFrame::EPSG_6326,
597 CartesianCS::createGeocentric(
598 UnitOfMeasure("kilometre", 1000.0, UnitOfMeasure::Type::LINEAR)));
599 }
600
601 // ---------------------------------------------------------------------------
602
TEST(operation,transformation_createGeocentricTranslations_between_geocentricCRS)603 TEST(operation,
604 transformation_createGeocentricTranslations_between_geocentricCRS) {
605
606 auto transf1 = Transformation::createGeocentricTranslations(
607 PropertyMap(), createGeocentricDatumWGS84(), createGeocentricKM(), 1.0,
608 2.0, 3.0, std::vector<PositionalAccuracyNNPtr>());
609
610 EXPECT_EQ(transf1->exportToPROJString(PROJStringFormatter::create().get()),
611 "+proj=pipeline +step +proj=helmert +x=1 +y=2 +z=3 +step "
612 "+proj=unitconvert +xy_in=m +z_in=m +xy_out=km +z_out=km");
613
614 auto transf2 = Transformation::createGeocentricTranslations(
615 PropertyMap(), createGeocentricKM(), createGeocentricDatumWGS84(), 1.0,
616 2.0, 3.0, std::vector<PositionalAccuracyNNPtr>());
617
618 EXPECT_EQ(transf2->exportToPROJString(PROJStringFormatter::create().get()),
619 "+proj=pipeline +step +proj=unitconvert +xy_in=km +z_in=km "
620 "+xy_out=m +z_out=m +step +proj=helmert +x=1 +y=2 +z=3");
621
622 auto transf3 = Transformation::createGeocentricTranslations(
623 PropertyMap(), createGeocentricKM(), createGeocentricKM(), 1.0, 2.0,
624 3.0, std::vector<PositionalAccuracyNNPtr>());
625
626 EXPECT_EQ(transf3->exportToPROJString(PROJStringFormatter::create().get()),
627 "+proj=pipeline +step +proj=unitconvert +xy_in=km +z_in=km "
628 "+xy_out=m +z_out=m +step +proj=helmert +x=1 +y=2 +z=3 +step "
629 "+proj=unitconvert +xy_in=m +z_in=m +xy_out=km +z_out=km");
630 }
631
632 // ---------------------------------------------------------------------------
633
TEST(operation,transformation_createGeocentricTranslations_null)634 TEST(operation, transformation_createGeocentricTranslations_null) {
635
636 auto transf = Transformation::createGeocentricTranslations(
637 PropertyMap(), createGeocentricDatumWGS84(),
638 createGeocentricDatumWGS84(), 0.0, 0.0, 0.0,
639 std::vector<PositionalAccuracyNNPtr>());
640
641 EXPECT_EQ(transf->inverse()->exportToPROJString(
642 PROJStringFormatter::create().get()),
643 "+proj=noop");
644 }
645
646 // ---------------------------------------------------------------------------
647
TEST(operation,transformation_createGeocentricTranslations_neg_zero)648 TEST(operation, transformation_createGeocentricTranslations_neg_zero) {
649
650 auto transf = Transformation::createGeocentricTranslations(
651 PropertyMap(), createGeocentricDatumWGS84(),
652 createGeocentricDatumWGS84(), 1.0, -0.0, 0.0,
653 std::vector<PositionalAccuracyNNPtr>());
654
655 EXPECT_EQ(transf->inverse()->exportToPROJString(
656 PROJStringFormatter::create().get()),
657 "+proj=helmert +x=-1 +y=0 +z=0");
658 }
659
660 // ---------------------------------------------------------------------------
661
TEST(operation,transformation_createPositionVector)662 TEST(operation, transformation_createPositionVector) {
663
664 auto transf = Transformation::createPositionVector(
665 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
666 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, std::vector<PositionalAccuracyNNPtr>{
667 PositionalAccuracy::create("100")});
668 EXPECT_TRUE(transf->validateParameters().empty());
669
670 ASSERT_EQ(transf->coordinateOperationAccuracies().size(), 1U);
671
672 auto expected = std::vector<double>{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
673 EXPECT_EQ(transf->getTOWGS84Parameters(), expected);
674
675 EXPECT_EQ(transf->exportToPROJString(PROJStringFormatter::create().get()),
676 "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
677 "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 "
678 "+step +proj=cart +ellps=GRS80 +step +proj=helmert +x=1 +y=2 "
679 "+z=3 +rx=4 +ry=5 +rz=6 +s=7 +convention=position_vector +step "
680 "+inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step "
681 "+proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap "
682 "+order=2,1");
683
684 auto inv_transf = transf->inverse();
685 ASSERT_EQ(inv_transf->coordinateOperationAccuracies().size(), 1U);
686
687 EXPECT_EQ(transf->sourceCRS()->nameStr(),
688 inv_transf->targetCRS()->nameStr());
689 EXPECT_EQ(transf->targetCRS()->nameStr(),
690 inv_transf->sourceCRS()->nameStr());
691
692 #ifdef USE_APPROXIMATE_HELMERT_INVERSE
693 auto inv_transf_as_transf =
694 nn_dynamic_pointer_cast<Transformation>(inv_transf);
695 ASSERT_TRUE(inv_transf_as_transf != nullptr);
696 #else
697 EXPECT_EQ(
698 inv_transf->exportToPROJString(PROJStringFormatter::create().get()),
699 "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
700 "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 +step "
701 "+proj=cart +ellps=WGS84 +step +inv +proj=helmert +x=1 +y=2 +z=3 +rx=4 "
702 "+ry=5 +rz=6 +s=7 +convention=position_vector +step +inv +proj=cart "
703 "+ellps=GRS80 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad "
704 "+xy_out=deg +step +proj=axisswap +order=2,1");
705
706 // In WKT, use approximate formula
707 auto wkt = inv_transf->exportToWKT(WKTFormatter::create().get());
708 EXPECT_TRUE(
709 wkt.find("Transformation from WGS 84 to NAD83 (approx. inversion)") !=
710 std::string::npos)
711 << wkt;
712 EXPECT_TRUE(wkt.find("Position Vector transformation (geog2D domain)") !=
713 std::string::npos)
714 << wkt;
715 EXPECT_TRUE(wkt.find("ID[\"EPSG\",9606]]") != std::string::npos) << wkt;
716 EXPECT_TRUE(wkt.find("\"X-axis translation\",-1") != std::string::npos)
717 << wkt;
718 EXPECT_TRUE(wkt.find("\"Y-axis translation\",-2") != std::string::npos)
719 << wkt;
720 EXPECT_TRUE(wkt.find("\"Z-axis translation\",-3") != std::string::npos)
721 << wkt;
722 EXPECT_TRUE(wkt.find("\"X-axis rotation\",-4") != std::string::npos) << wkt;
723 EXPECT_TRUE(wkt.find("\"Y-axis rotation\",-5") != std::string::npos) << wkt;
724 EXPECT_TRUE(wkt.find("\"Z-axis rotation\",-6") != std::string::npos) << wkt;
725 EXPECT_TRUE(wkt.find("\"Scale difference\",-7") != std::string::npos)
726 << wkt;
727 #endif
728 }
729
730 // ---------------------------------------------------------------------------
731
TEST(operation,transformation_createCoordinateFrameRotation)732 TEST(operation, transformation_createCoordinateFrameRotation) {
733
734 auto transf = Transformation::createCoordinateFrameRotation(
735 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
736 2.0, 3.0, -4.0, -5.0, -6.0, 7.0,
737 std::vector<PositionalAccuracyNNPtr>());
738 EXPECT_TRUE(transf->validateParameters().empty());
739
740 auto params = transf->getTOWGS84Parameters();
741 auto expected = std::vector<double>{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
742 EXPECT_EQ(params, expected);
743
744 EXPECT_EQ(transf->exportToPROJString(PROJStringFormatter::create().get()),
745 "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
746 "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 "
747 "+step +proj=cart +ellps=GRS80 +step +proj=helmert +x=1 +y=2 "
748 "+z=3 +rx=-4 +ry=-5 +rz=-6 +s=7 +convention=coordinate_frame "
749 "+step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step "
750 "+proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap "
751 "+order=2,1");
752
753 auto inv_transf = transf->inverse();
754 ASSERT_EQ(inv_transf->coordinateOperationAccuracies().size(), 0U);
755
756 EXPECT_EQ(transf->sourceCRS()->nameStr(),
757 inv_transf->targetCRS()->nameStr());
758 EXPECT_EQ(transf->targetCRS()->nameStr(),
759 inv_transf->sourceCRS()->nameStr());
760
761 #ifdef USE_APPROXIMATE_HELMERT_INVERSE
762 auto inv_transf_as_transf =
763 nn_dynamic_pointer_cast<Transformation>(inv_transf);
764 ASSERT_TRUE(inv_transf_as_transf != nullptr);
765 #else
766 EXPECT_EQ(
767 inv_transf->exportToPROJString(PROJStringFormatter::create().get()),
768 "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
769 "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 +step "
770 "+proj=cart +ellps=WGS84 +step +inv +proj=helmert +x=1 +y=2 +z=3 "
771 "+rx=-4 +ry=-5 +rz=-6 +s=7 +convention=coordinate_frame +step +inv "
772 "+proj=cart +ellps=GRS80 +step +proj=pop +v_3 +step +proj=unitconvert "
773 "+xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1");
774
775 // In WKT, use approximate formula
776 auto wkt = inv_transf->exportToWKT(WKTFormatter::create().get());
777 EXPECT_TRUE(
778 wkt.find("Transformation from WGS 84 to NAD83 (approx. inversion)") !=
779 std::string::npos)
780 << wkt;
781 EXPECT_TRUE(wkt.find("Coordinate Frame rotation (geog2D domain)") !=
782 std::string::npos)
783 << wkt;
784 EXPECT_TRUE(wkt.find("ID[\"EPSG\",9607]]") != std::string::npos) << wkt;
785 EXPECT_TRUE(wkt.find("\"X-axis translation\",-1") != std::string::npos)
786 << wkt;
787 EXPECT_TRUE(wkt.find("\"Y-axis translation\",-2") != std::string::npos)
788 << wkt;
789 EXPECT_TRUE(wkt.find("\"Z-axis translation\",-3") != std::string::npos)
790 << wkt;
791 EXPECT_TRUE(wkt.find("\"X-axis rotation\",4") != std::string::npos) << wkt;
792 EXPECT_TRUE(wkt.find("\"Y-axis rotation\",5") != std::string::npos) << wkt;
793 EXPECT_TRUE(wkt.find("\"Z-axis rotation\",6") != std::string::npos) << wkt;
794 EXPECT_TRUE(wkt.find("\"Scale difference\",-7") != std::string::npos)
795 << wkt;
796 #endif
797 }
798
799 // ---------------------------------------------------------------------------
800
TEST(operation,transformation_createTimeDependentPositionVector)801 TEST(operation, transformation_createTimeDependentPositionVector) {
802
803 auto transf = Transformation::createTimeDependentPositionVector(
804 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
805 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 2018.5,
806 std::vector<PositionalAccuracyNNPtr>());
807 EXPECT_TRUE(transf->validateParameters().empty());
808
809 auto inv_transf = transf->inverse();
810
811 EXPECT_EQ(transf->sourceCRS()->nameStr(),
812 inv_transf->targetCRS()->nameStr());
813 EXPECT_EQ(transf->targetCRS()->nameStr(),
814 inv_transf->sourceCRS()->nameStr());
815
816 auto projString =
817 inv_transf->exportToPROJString(PROJStringFormatter::create().get());
818 EXPECT_TRUE(projString.find("+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 "
819 "+rz=6 +s=7 +dx=0.1 +dy=0.2 +dz=0.3 +drx=0.4 "
820 "+dry=0.5 +drz=0.6 +ds=0.7 +t_epoch=2018.5 "
821 "+convention=position_vector") !=
822 std::string::npos)
823 << projString;
824
825 // In WKT, use approximate formula
826 auto wkt = inv_transf->exportToWKT(WKTFormatter::create().get());
827 EXPECT_TRUE(
828 wkt.find("Transformation from WGS 84 to NAD83 (approx. inversion)") !=
829 std::string::npos)
830 << wkt;
831 EXPECT_TRUE(wkt.find("Time-dependent Position Vector tfm (geog2D)") !=
832 std::string::npos)
833 << wkt;
834 EXPECT_TRUE(wkt.find("ID[\"EPSG\",1054]]") != std::string::npos) << wkt;
835 EXPECT_TRUE(wkt.find("\"X-axis translation\",-1") != std::string::npos)
836 << wkt;
837 EXPECT_TRUE(wkt.find("\"Y-axis translation\",-2") != std::string::npos)
838 << wkt;
839 EXPECT_TRUE(wkt.find("\"Z-axis translation\",-3") != std::string::npos)
840 << wkt;
841 EXPECT_TRUE(wkt.find("\"X-axis rotation\",-4") != std::string::npos) << wkt;
842 EXPECT_TRUE(wkt.find("\"Y-axis rotation\",-5") != std::string::npos) << wkt;
843 EXPECT_TRUE(wkt.find("\"Z-axis rotation\",-6") != std::string::npos) << wkt;
844 EXPECT_TRUE(wkt.find("\"Scale difference\",-7") != std::string::npos)
845 << wkt;
846 EXPECT_TRUE(wkt.find("\"Rate of change of X-axis translation\",-0.1") !=
847 std::string::npos)
848 << wkt;
849 EXPECT_TRUE(wkt.find("\"Rate of change of Y-axis translation\",-0.2") !=
850 std::string::npos)
851 << wkt;
852 EXPECT_TRUE(wkt.find("\"Rate of change of Z-axis translation\",-0.3") !=
853 std::string::npos)
854 << wkt;
855 EXPECT_TRUE(wkt.find("\"Rate of change of X-axis rotation\",-0.4") !=
856 std::string::npos)
857 << wkt;
858 EXPECT_TRUE(wkt.find("\"Rate of change of Y-axis rotation\",-0.5") !=
859 std::string::npos)
860 << wkt;
861 EXPECT_TRUE(wkt.find("\"Rate of change of Z-axis rotation\",-0.6") !=
862 std::string::npos)
863 << wkt;
864 EXPECT_TRUE(wkt.find("\"Rate of change of Scale difference\",-0.7") !=
865 std::string::npos)
866 << wkt;
867 EXPECT_TRUE(wkt.find("\"Parameter reference epoch\",2018.5") !=
868 std::string::npos)
869 << wkt;
870 }
871
872 // ---------------------------------------------------------------------------
873
TEST(operation,transformation_createTimeDependentCoordinateFrameRotation)874 TEST(operation, transformation_createTimeDependentCoordinateFrameRotation) {
875
876 auto transf = Transformation::createTimeDependentCoordinateFrameRotation(
877 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
878 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 2018.5,
879 std::vector<PositionalAccuracyNNPtr>());
880 EXPECT_TRUE(transf->validateParameters().empty());
881
882 auto inv_transf = transf->inverse();
883
884 EXPECT_EQ(transf->sourceCRS()->nameStr(),
885 inv_transf->targetCRS()->nameStr());
886 EXPECT_EQ(transf->targetCRS()->nameStr(),
887 inv_transf->sourceCRS()->nameStr());
888
889 auto projString =
890 inv_transf->exportToPROJString(PROJStringFormatter::create().get());
891 EXPECT_TRUE(projString.find("+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 "
892 "+rz=6 +s=7 +dx=0.1 +dy=0.2 +dz=0.3 +drx=0.4 "
893 "+dry=0.5 +drz=0.6 +ds=0.7 +t_epoch=2018.5 "
894 "+convention=coordinate_frame") !=
895 std::string::npos)
896 << projString;
897
898 // In WKT, use approximate formula
899 auto wkt = inv_transf->exportToWKT(WKTFormatter::create().get());
900 EXPECT_TRUE(
901 wkt.find("Transformation from WGS 84 to NAD83 (approx. inversion)") !=
902 std::string::npos)
903 << wkt;
904 EXPECT_TRUE(wkt.find("Time-dependent Coordinate Frame rotation (geog2D)") !=
905 std::string::npos)
906 << wkt;
907 EXPECT_TRUE(wkt.find("ID[\"EPSG\",1057]]") != std::string::npos) << wkt;
908 EXPECT_TRUE(wkt.find("\"X-axis translation\",-1") != std::string::npos)
909 << wkt;
910 EXPECT_TRUE(wkt.find("\"Y-axis translation\",-2") != std::string::npos)
911 << wkt;
912 EXPECT_TRUE(wkt.find("\"Z-axis translation\",-3") != std::string::npos)
913 << wkt;
914 EXPECT_TRUE(wkt.find("\"X-axis rotation\",-4") != std::string::npos) << wkt;
915 EXPECT_TRUE(wkt.find("\"Y-axis rotation\",-5") != std::string::npos) << wkt;
916 EXPECT_TRUE(wkt.find("\"Z-axis rotation\",-6") != std::string::npos) << wkt;
917 EXPECT_TRUE(wkt.find("\"Scale difference\",-7") != std::string::npos)
918 << wkt;
919 EXPECT_TRUE(wkt.find("\"Rate of change of X-axis translation\",-0.1") !=
920 std::string::npos)
921 << wkt;
922 EXPECT_TRUE(wkt.find("\"Rate of change of Y-axis translation\",-0.2") !=
923 std::string::npos)
924 << wkt;
925 EXPECT_TRUE(wkt.find("\"Rate of change of Z-axis translation\",-0.3") !=
926 std::string::npos)
927 << wkt;
928 EXPECT_TRUE(wkt.find("\"Rate of change of X-axis rotation\",-0.4") !=
929 std::string::npos)
930 << wkt;
931 EXPECT_TRUE(wkt.find("\"Rate of change of Y-axis rotation\",-0.5") !=
932 std::string::npos)
933 << wkt;
934 EXPECT_TRUE(wkt.find("\"Rate of change of Z-axis rotation\",-0.6") !=
935 std::string::npos)
936 << wkt;
937 EXPECT_TRUE(wkt.find("\"Rate of change of Scale difference\",-0.7") !=
938 std::string::npos)
939 << wkt;
940 EXPECT_TRUE(wkt.find("\"Parameter reference epoch\",2018.5") !=
941 std::string::npos)
942 << wkt;
943 }
944
945 // ---------------------------------------------------------------------------
946
TEST(operation,transformation_successive_helmert_noop)947 TEST(operation, transformation_successive_helmert_noop) {
948
949 auto transf_1 = Transformation::createPositionVector(
950 PropertyMap(), GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4269, 1.0,
951 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, std::vector<PositionalAccuracyNNPtr>());
952 auto transf_2 = Transformation::createPositionVector(
953 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, -1.0,
954 -2.0, -3.0, -4.0, -5.0, -6.0, -7.0,
955 std::vector<PositionalAccuracyNNPtr>());
956
957 auto concat = ConcatenatedOperation::create(
958 PropertyMap(),
959 std::vector<CoordinateOperationNNPtr>{transf_1, transf_2},
960 std::vector<PositionalAccuracyNNPtr>{});
961
962 EXPECT_EQ(concat->exportToPROJString(PROJStringFormatter::create().get()),
963 "+proj=noop");
964 }
965
966 // ---------------------------------------------------------------------------
967
TEST(operation,transformation_successive_helmert_non_trivial_1)968 TEST(operation, transformation_successive_helmert_non_trivial_1) {
969
970 auto transf_1 = Transformation::createPositionVector(
971 PropertyMap(), GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4269, 1.0,
972 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, std::vector<PositionalAccuracyNNPtr>());
973 auto transf_2 = Transformation::createPositionVector(
974 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, -1.0,
975 -2.0, -3.0, -4.0, -5.0, -6.0, 7.0,
976 std::vector<PositionalAccuracyNNPtr>());
977
978 auto concat = ConcatenatedOperation::create(
979 PropertyMap(),
980 std::vector<CoordinateOperationNNPtr>{transf_1, transf_2},
981 std::vector<PositionalAccuracyNNPtr>{});
982
983 EXPECT_NE(concat->exportToPROJString(PROJStringFormatter::create().get()),
984 "");
985 }
986
987 // ---------------------------------------------------------------------------
988
TEST(operation,transformation_successive_helmert_non_trivial_2)989 TEST(operation, transformation_successive_helmert_non_trivial_2) {
990
991 auto transf_1 = Transformation::createPositionVector(
992 PropertyMap(), GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4269, 1.0,
993 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, std::vector<PositionalAccuracyNNPtr>());
994 auto transf_2 = Transformation::createCoordinateFrameRotation(
995 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, -1.0,
996 -2.0, -3.0, -4.0, -5.0, -6.0, -7.0,
997 std::vector<PositionalAccuracyNNPtr>());
998
999 auto concat = ConcatenatedOperation::create(
1000 PropertyMap(),
1001 std::vector<CoordinateOperationNNPtr>{transf_1, transf_2},
1002 std::vector<PositionalAccuracyNNPtr>{});
1003
1004 EXPECT_NE(concat->exportToPROJString(PROJStringFormatter::create().get()),
1005 "");
1006 }
1007
1008 // ---------------------------------------------------------------------------
1009
TEST(operation,transformation_createMolodensky)1010 TEST(operation, transformation_createMolodensky) {
1011
1012 auto transf = Transformation::createMolodensky(
1013 PropertyMap(), GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4269, 1.0,
1014 2.0, 3.0, 4.0, 5.0, std::vector<PositionalAccuracyNNPtr>());
1015 EXPECT_TRUE(transf->validateParameters().empty());
1016
1017 auto wkt = transf->exportToWKT(WKTFormatter::create().get());
1018 EXPECT_TRUE(replaceAll(replaceAll(wkt, " ", ""), "\n", "")
1019 .find("METHOD[\"Molodensky\",ID[\"EPSG\",9604]]") !=
1020 std::string::npos)
1021 << wkt;
1022
1023 auto inv_transf = transf->inverse();
1024 auto inv_transf_as_transf =
1025 nn_dynamic_pointer_cast<Transformation>(inv_transf);
1026 ASSERT_TRUE(inv_transf_as_transf != nullptr);
1027
1028 EXPECT_EQ(transf->sourceCRS()->nameStr(),
1029 inv_transf_as_transf->targetCRS()->nameStr());
1030 EXPECT_EQ(transf->targetCRS()->nameStr(),
1031 inv_transf_as_transf->sourceCRS()->nameStr());
1032
1033 auto projString = inv_transf_as_transf->exportToPROJString(
1034 PROJStringFormatter::create().get());
1035 EXPECT_EQ(projString, "+proj=pipeline +step +proj=axisswap +order=2,1 "
1036 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
1037 "+step +proj=molodensky +ellps=GRS80 +dx=-1 +dy=-2 "
1038 "+dz=-3 +da=-4 +df=-5 +step +proj=unitconvert "
1039 "+xy_in=rad +xy_out=deg +step +proj=axisswap "
1040 "+order=2,1");
1041 }
1042
1043 // ---------------------------------------------------------------------------
1044
TEST(operation,transformation_createAbridgedMolodensky)1045 TEST(operation, transformation_createAbridgedMolodensky) {
1046
1047 auto transf = Transformation::createAbridgedMolodensky(
1048 PropertyMap(), GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4269, 1.0,
1049 2.0, 3.0, 4.0, 5.0, std::vector<PositionalAccuracyNNPtr>());
1050
1051 auto wkt = transf->exportToWKT(WKTFormatter::create().get());
1052 EXPECT_TRUE(replaceAll(replaceAll(wkt, " ", ""), "\n", "")
1053 .find(replaceAll(
1054 "METHOD[\"Abridged Molodensky\",ID[\"EPSG\",9605]]",
1055 " ", "")) != std::string::npos)
1056 << wkt;
1057
1058 auto inv_transf = transf->inverse();
1059 auto inv_transf_as_transf =
1060 nn_dynamic_pointer_cast<Transformation>(inv_transf);
1061 ASSERT_TRUE(inv_transf_as_transf != nullptr);
1062
1063 EXPECT_EQ(transf->sourceCRS()->nameStr(),
1064 inv_transf_as_transf->targetCRS()->nameStr());
1065 EXPECT_EQ(transf->targetCRS()->nameStr(),
1066 inv_transf_as_transf->sourceCRS()->nameStr());
1067
1068 auto projString = inv_transf_as_transf->exportToPROJString(
1069 PROJStringFormatter::create().get());
1070 EXPECT_EQ(projString, "+proj=pipeline +step +proj=axisswap +order=2,1 "
1071 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
1072 "+step +proj=molodensky +ellps=GRS80 +dx=-1 +dy=-2 "
1073 "+dz=-3 +da=-4 +df=-5 +abridged +step "
1074 "+proj=unitconvert +xy_in=rad +xy_out=deg +step "
1075 "+proj=axisswap +order=2,1");
1076 }
1077
1078 // ---------------------------------------------------------------------------
1079
TEST(operation,transformation_inverse)1080 TEST(operation, transformation_inverse) {
1081
1082 auto transf = Transformation::create(
1083 PropertyMap()
1084 .set(IdentifiedObject::NAME_KEY, "my transformation")
1085 .set(Identifier::CODESPACE_KEY, "my codeSpace")
1086 .set(Identifier::CODE_KEY, "my code"),
1087 GeographicCRS::EPSG_4326, GeographicCRS::EPSG_4269, nullptr,
1088 PropertyMap()
1089 .set(IdentifiedObject::NAME_KEY, "my operation")
1090 .set(Identifier::CODESPACE_KEY, "my codeSpace")
1091 .set(Identifier::CODE_KEY, "my code"),
1092 std::vector<OperationParameterNNPtr>{OperationParameter::create(
1093 PropertyMap().set(IdentifiedObject::NAME_KEY, "paramName"))},
1094 std::vector<ParameterValueNNPtr>{
1095 ParameterValue::createFilename("foo.bin")},
1096 std::vector<PositionalAccuracyNNPtr>{
1097 PositionalAccuracy::create("0.1")});
1098 auto inv = transf->inverse();
1099 EXPECT_EQ(inv->inverse(), transf);
1100 EXPECT_EQ(
1101 inv->exportToWKT(WKTFormatter::create().get()),
1102 "COORDINATEOPERATION[\"Inverse of my transformation\",\n"
1103 " SOURCECRS[\n"
1104 " GEODCRS[\"NAD83\",\n"
1105 " DATUM[\"North American Datum 1983\",\n"
1106 " ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n"
1107 " LENGTHUNIT[\"metre\",1]]],\n"
1108 " PRIMEM[\"Greenwich\",0,\n"
1109 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1110 " CS[ellipsoidal,2],\n"
1111 " AXIS[\"latitude\",north,\n"
1112 " ORDER[1],\n"
1113 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1114 " AXIS[\"longitude\",east,\n"
1115 " ORDER[2],\n"
1116 " ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n"
1117 " TARGETCRS[\n"
1118 " GEODCRS[\"WGS 84\",\n"
1119 " DATUM[\"World Geodetic System 1984\",\n"
1120 " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
1121 " LENGTHUNIT[\"metre\",1]]],\n"
1122 " PRIMEM[\"Greenwich\",0,\n"
1123 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1124 " CS[ellipsoidal,2],\n"
1125 " AXIS[\"latitude\",north,\n"
1126 " ORDER[1],\n"
1127 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1128 " AXIS[\"longitude\",east,\n"
1129 " ORDER[2],\n"
1130 " ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n"
1131 " METHOD[\"Inverse of my operation\",\n"
1132 " ID[\"INVERSE(my codeSpace)\",\"my code\"]],\n"
1133 " PARAMETERFILE[\"paramName\",\"foo.bin\"],\n"
1134 " OPERATIONACCURACY[0.1],\n"
1135 " ID[\"INVERSE(my codeSpace)\",\"my code\"]]");
1136
1137 EXPECT_THROW(inv->exportToPROJString(PROJStringFormatter::create().get()),
1138 FormattingException);
1139 }
1140
1141 // ---------------------------------------------------------------------------
1142
createVerticalCRS()1143 static VerticalCRSNNPtr createVerticalCRS() {
1144 PropertyMap propertiesVDatum;
1145 propertiesVDatum.set(Identifier::CODESPACE_KEY, "EPSG")
1146 .set(Identifier::CODE_KEY, 5101)
1147 .set(IdentifiedObject::NAME_KEY, "Ordnance Datum Newlyn");
1148 auto vdatum = VerticalReferenceFrame::create(propertiesVDatum);
1149 PropertyMap propertiesCRS;
1150 propertiesCRS.set(Identifier::CODESPACE_KEY, "EPSG")
1151 .set(Identifier::CODE_KEY, 5701)
1152 .set(IdentifiedObject::NAME_KEY, "ODN height");
1153 return VerticalCRS::create(
1154 propertiesCRS, vdatum,
1155 VerticalCS::createGravityRelatedHeight(UnitOfMeasure::METRE));
1156 }
1157
1158 // ---------------------------------------------------------------------------
1159
TEST(operation,transformation_createTOWGS84)1160 TEST(operation, transformation_createTOWGS84) {
1161
1162 EXPECT_THROW(Transformation::createTOWGS84(GeographicCRS::EPSG_4326,
1163 std::vector<double>()),
1164 InvalidOperation);
1165
1166 EXPECT_THROW(Transformation::createTOWGS84(createVerticalCRS(),
1167 std::vector<double>(7, 0)),
1168 InvalidOperation);
1169 }
1170
1171 // ---------------------------------------------------------------------------
1172
TEST(operation,createAxisOrderReversal)1173 TEST(operation, createAxisOrderReversal) {
1174
1175 {
1176 auto conv = Conversion::createAxisOrderReversal(false);
1177 EXPECT_TRUE(conv->validateParameters().empty());
1178 }
1179 {
1180 auto conv = Conversion::createAxisOrderReversal(true);
1181 EXPECT_TRUE(conv->validateParameters().empty());
1182 }
1183
1184 auto latLongDeg = GeographicCRS::create(
1185 PropertyMap(), GeodeticReferenceFrame::EPSG_6326,
1186 EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE));
1187 auto longLatDeg = GeographicCRS::create(
1188 PropertyMap(), GeodeticReferenceFrame::EPSG_6326,
1189 EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::DEGREE));
1190 {
1191 auto op = CoordinateOperationFactory::create()->createOperation(
1192 latLongDeg, longLatDeg);
1193 ASSERT_TRUE(op != nullptr);
1194 EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
1195 "+proj=axisswap +order=2,1");
1196 }
1197 {
1198 auto longLatRad = GeographicCRS::create(
1199 PropertyMap(), GeodeticReferenceFrame::EPSG_6326,
1200 EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::RADIAN));
1201 auto op = CoordinateOperationFactory::create()->createOperation(
1202 longLatRad, latLongDeg);
1203 ASSERT_TRUE(op != nullptr);
1204 EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
1205 "+proj=pipeline +step +proj=axisswap +order=2,1 "
1206 "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
1207 }
1208 }
1209
1210 // ---------------------------------------------------------------------------
1211
TEST(operation,utm_export)1212 TEST(operation, utm_export) {
1213 auto conv = Conversion::createUTM(PropertyMap(), 1, false);
1214 EXPECT_TRUE(conv->validateParameters().empty());
1215 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1216 "+proj=utm +zone=1 +south");
1217
1218 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1219 "CONVERSION[\"UTM zone 1S\",\n"
1220 " METHOD[\"Transverse Mercator\",\n"
1221 " ID[\"EPSG\",9807]],\n"
1222 " PARAMETER[\"Latitude of natural origin\",0,\n"
1223 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1224 " ID[\"EPSG\",8801]],\n"
1225 " PARAMETER[\"Longitude of natural origin\",-177,\n"
1226 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1227 " ID[\"EPSG\",8802]],\n"
1228 " PARAMETER[\"Scale factor at natural origin\",0.9996,\n"
1229 " SCALEUNIT[\"unity\",1],\n"
1230 " ID[\"EPSG\",8805]],\n"
1231 " PARAMETER[\"False easting\",500000,\n"
1232 " LENGTHUNIT[\"metre\",1],\n"
1233 " ID[\"EPSG\",8806]],\n"
1234 " PARAMETER[\"False northing\",10000000,\n"
1235 " LENGTHUNIT[\"metre\",1],\n"
1236 " ID[\"EPSG\",8807]],\n"
1237 " ID[\"EPSG\",17001]]");
1238
1239 EXPECT_EQ(
1240 conv->exportToWKT(
1241 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1242 "PROJECTION[\"Transverse_Mercator\"],\n"
1243 "PARAMETER[\"latitude_of_origin\",0],\n"
1244 "PARAMETER[\"central_meridian\",-177],\n"
1245 "PARAMETER[\"scale_factor\",0.9996],\n"
1246 "PARAMETER[\"false_easting\",500000],\n"
1247 "PARAMETER[\"false_northing\",10000000]");
1248 }
1249
1250 // ---------------------------------------------------------------------------
1251
TEST(operation,tmerc_export)1252 TEST(operation, tmerc_export) {
1253 auto conv = Conversion::createTransverseMercator(
1254 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
1255 EXPECT_TRUE(conv->validateParameters().empty());
1256 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1257 "+proj=tmerc +lat_0=1 +lon_0=2 +k=3 +x_0=4 +y_0=5");
1258
1259 {
1260 auto formatter = PROJStringFormatter::create();
1261 formatter->setUseApproxTMerc(true);
1262 EXPECT_EQ(conv->exportToPROJString(formatter.get()),
1263 "+proj=tmerc +approx +lat_0=1 +lon_0=2 +k=3 +x_0=4 +y_0=5");
1264 }
1265
1266 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1267 "CONVERSION[\"Transverse Mercator\",\n"
1268 " METHOD[\"Transverse Mercator\",\n"
1269 " ID[\"EPSG\",9807]],\n"
1270 " PARAMETER[\"Latitude of natural origin\",1,\n"
1271 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1272 " ID[\"EPSG\",8801]],\n"
1273 " PARAMETER[\"Longitude of natural origin\",2,\n"
1274 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1275 " ID[\"EPSG\",8802]],\n"
1276 " PARAMETER[\"Scale factor at natural origin\",3,\n"
1277 " SCALEUNIT[\"unity\",1],\n"
1278 " ID[\"EPSG\",8805]],\n"
1279 " PARAMETER[\"False easting\",4,\n"
1280 " LENGTHUNIT[\"metre\",1],\n"
1281 " ID[\"EPSG\",8806]],\n"
1282 " PARAMETER[\"False northing\",5,\n"
1283 " LENGTHUNIT[\"metre\",1],\n"
1284 " ID[\"EPSG\",8807]]]");
1285
1286 EXPECT_EQ(
1287 conv->exportToWKT(
1288 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1289 "PROJECTION[\"Transverse_Mercator\"],\n"
1290 "PARAMETER[\"latitude_of_origin\",1],\n"
1291 "PARAMETER[\"central_meridian\",2],\n"
1292 "PARAMETER[\"scale_factor\",3],\n"
1293 "PARAMETER[\"false_easting\",4],\n"
1294 "PARAMETER[\"false_northing\",5]");
1295 }
1296
1297 // ---------------------------------------------------------------------------
1298
TEST(operation,gstmerc_export)1299 TEST(operation, gstmerc_export) {
1300 auto conv = Conversion::createGaussSchreiberTransverseMercator(
1301 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
1302 EXPECT_TRUE(conv->validateParameters().empty());
1303 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1304 "+proj=gstmerc +lat_0=1 +lon_0=2 +k_0=3 +x_0=4 +y_0=5");
1305
1306 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1307 "CONVERSION[\"Gauss Schreiber Transverse Mercator\",\n"
1308 " METHOD[\"Gauss Schreiber Transverse Mercator\"],\n"
1309 " PARAMETER[\"Latitude of natural origin\",1,\n"
1310 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1311 " ID[\"EPSG\",8801]],\n"
1312 " PARAMETER[\"Longitude of natural origin\",2,\n"
1313 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1314 " ID[\"EPSG\",8802]],\n"
1315 " PARAMETER[\"Scale factor at natural origin\",3,\n"
1316 " SCALEUNIT[\"unity\",1],\n"
1317 " ID[\"EPSG\",8805]],\n"
1318 " PARAMETER[\"False easting\",4,\n"
1319 " LENGTHUNIT[\"metre\",1],\n"
1320 " ID[\"EPSG\",8806]],\n"
1321 " PARAMETER[\"False northing\",5,\n"
1322 " LENGTHUNIT[\"metre\",1],\n"
1323 " ID[\"EPSG\",8807]]]");
1324
1325 EXPECT_EQ(
1326 conv->exportToWKT(
1327 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1328 "PROJECTION[\"Gauss_Schreiber_Transverse_Mercator\"],\n"
1329 "PARAMETER[\"latitude_of_origin\",1],\n"
1330 "PARAMETER[\"central_meridian\",2],\n"
1331 "PARAMETER[\"scale_factor\",3],\n"
1332 "PARAMETER[\"false_easting\",4],\n"
1333 "PARAMETER[\"false_northing\",5]");
1334 }
1335
1336 // ---------------------------------------------------------------------------
1337
TEST(operation,tmerc_south_oriented_export)1338 TEST(operation, tmerc_south_oriented_export) {
1339 auto conv = Conversion::createTransverseMercatorSouthOriented(
1340 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
1341 EXPECT_TRUE(conv->validateParameters().empty());
1342
1343 // False easting/northing != 0 not supported
1344 EXPECT_THROW(conv->exportToPROJString(PROJStringFormatter::create().get()),
1345 FormattingException);
1346
1347 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1348 "CONVERSION[\"Transverse Mercator (South Orientated)\",\n"
1349 " METHOD[\"Transverse Mercator (South Orientated)\",\n"
1350 " ID[\"EPSG\",9808]],\n"
1351 " PARAMETER[\"Latitude of natural origin\",1,\n"
1352 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1353 " ID[\"EPSG\",8801]],\n"
1354 " PARAMETER[\"Longitude of natural origin\",2,\n"
1355 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1356 " ID[\"EPSG\",8802]],\n"
1357 " PARAMETER[\"Scale factor at natural origin\",3,\n"
1358 " SCALEUNIT[\"unity\",1],\n"
1359 " ID[\"EPSG\",8805]],\n"
1360 " PARAMETER[\"False easting\",4,\n"
1361 " LENGTHUNIT[\"metre\",1],\n"
1362 " ID[\"EPSG\",8806]],\n"
1363 " PARAMETER[\"False northing\",5,\n"
1364 " LENGTHUNIT[\"metre\",1],\n"
1365 " ID[\"EPSG\",8807]]]");
1366
1367 EXPECT_EQ(
1368 conv->exportToWKT(
1369 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1370 "PROJECTION[\"Transverse_Mercator_South_Orientated\"],\n"
1371 "PARAMETER[\"latitude_of_origin\",1],\n"
1372 "PARAMETER[\"central_meridian\",2],\n"
1373 "PARAMETER[\"scale_factor\",3],\n"
1374 "PARAMETER[\"false_easting\",4],\n"
1375 "PARAMETER[\"false_northing\",5]");
1376
1377 auto wkt = "PROJCRS[\"Hartebeesthoek94 / Lo29\","
1378 " BASEGEODCRS[\"Hartebeesthoek94\","
1379 " DATUM[\"Hartebeesthoek94\","
1380 " ELLIPSOID[\"WGS "
1381 "84\",6378137,298.257223563,LENGTHUNIT[\"metre\",1.0]]]],"
1382 " CONVERSION[\"South African Survey Grid zone 29\","
1383 " METHOD[\"Transverse Mercator (South "
1384 "Orientated)\",ID[\"EPSG\",9808]],"
1385 " PARAMETER[\"Latitude of natural "
1386 "origin\",0,ANGLEUNIT[\"degree\",0.01745329252]],"
1387 " PARAMETER[\"Longitude of natural "
1388 "origin\",29,ANGLEUNIT[\"degree\",0.01745329252]],"
1389 " PARAMETER[\"Scale factor at natural "
1390 "origin\",1,SCALEUNIT[\"unity\",1.0]],"
1391 " PARAMETER[\"False easting\",0,LENGTHUNIT[\"metre\",1.0]],"
1392 " PARAMETER[\"False northing\",0,LENGTHUNIT[\"metre\",1.0]]],"
1393 " CS[cartesian,2],"
1394 " AXIS[\"westing (Y)\",west,ORDER[1]],"
1395 " AXIS[\"southing (X)\",south,ORDER[2]],"
1396 " LENGTHUNIT[\"metre\",1.0],"
1397 " ID[\"EPSG\",2053]]";
1398 auto obj = WKTParser().createFromWKT(wkt);
1399 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
1400 ASSERT_TRUE(crs != nullptr);
1401 EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
1402 "+proj=tmerc +axis=wsu +lat_0=0 +lon_0=29 +k=1 +x_0=0 +y_0=0 "
1403 "+ellps=WGS84 +units=m +no_defs +type=crs");
1404 }
1405
1406 // ---------------------------------------------------------------------------
1407
TEST(operation,tped_export)1408 TEST(operation, tped_export) {
1409 auto conv = Conversion::createTwoPointEquidistant(
1410 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Length(5),
1411 Length(6));
1412 EXPECT_TRUE(conv->validateParameters().empty());
1413
1414 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1415 "+proj=tpeqd +lat_1=1 +lon_1=2 +lat_2=3 +lon_2=4 +x_0=5 +y_0=6");
1416
1417 auto formatter = WKTFormatter::create();
1418 formatter->simulCurNodeHasId();
1419 EXPECT_EQ(conv->exportToWKT(formatter.get()),
1420 "CONVERSION[\"Two Point Equidistant\",\n"
1421 " METHOD[\"Two Point Equidistant\"],\n"
1422 " PARAMETER[\"Latitude of 1st point\",1,\n"
1423 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1424 " PARAMETER[\"Longitude of 1st point\",2,\n"
1425 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1426 " PARAMETER[\"Latitude of 2nd point\",3,\n"
1427 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1428 " PARAMETER[\"Longitude of 2nd point\",4,\n"
1429 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
1430 " PARAMETER[\"False easting\",5,\n"
1431 " LENGTHUNIT[\"metre\",1],\n"
1432 " ID[\"EPSG\",8806]],\n"
1433 " PARAMETER[\"False northing\",6,\n"
1434 " LENGTHUNIT[\"metre\",1],\n"
1435 " ID[\"EPSG\",8807]]]");
1436
1437 EXPECT_EQ(
1438 conv->exportToWKT(
1439 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1440 "PROJECTION[\"Two_Point_Equidistant\"],\n"
1441 "PARAMETER[\"Latitude_Of_1st_Point\",1],\n"
1442 "PARAMETER[\"Longitude_Of_1st_Point\",2],\n"
1443 "PARAMETER[\"Latitude_Of_2nd_Point\",3],\n"
1444 "PARAMETER[\"Longitude_Of_2nd_Point\",4],\n"
1445 "PARAMETER[\"false_easting\",5],\n"
1446 "PARAMETER[\"false_northing\",6]");
1447 }
1448
1449 // ---------------------------------------------------------------------------
1450
TEST(operation,tmg_export)1451 TEST(operation, tmg_export) {
1452 auto conv = Conversion::createTunisiaMappingGrid(
1453 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
1454 EXPECT_TRUE(conv->validateParameters().empty());
1455
1456 EXPECT_THROW(conv->exportToPROJString(PROJStringFormatter::create().get()),
1457 FormattingException);
1458
1459 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1460 "CONVERSION[\"Tunisia Mapping Grid\",\n"
1461 " METHOD[\"Tunisia Mapping Grid\",\n"
1462 " ID[\"EPSG\",9816]],\n"
1463 " PARAMETER[\"Latitude of false origin\",1,\n"
1464 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1465 " ID[\"EPSG\",8821]],\n"
1466 " PARAMETER[\"Longitude of false origin\",2,\n"
1467 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1468 " ID[\"EPSG\",8822]],\n"
1469 " PARAMETER[\"Easting at false origin\",3,\n"
1470 " LENGTHUNIT[\"metre\",1],\n"
1471 " ID[\"EPSG\",8826]],\n"
1472 " PARAMETER[\"Northing at false origin\",4,\n"
1473 " LENGTHUNIT[\"metre\",1],\n"
1474 " ID[\"EPSG\",8827]]]");
1475
1476 EXPECT_EQ(
1477 conv->exportToWKT(
1478 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1479 "PROJECTION[\"Tunisia_Mapping_Grid\"],\n"
1480 "PARAMETER[\"latitude_of_origin\",1],\n"
1481 "PARAMETER[\"central_meridian\",2],\n"
1482 "PARAMETER[\"false_easting\",3],\n"
1483 "PARAMETER[\"false_northing\",4]");
1484 }
1485
1486 // ---------------------------------------------------------------------------
1487
TEST(operation,aea_export)1488 TEST(operation, aea_export) {
1489 auto conv = Conversion::createAlbersEqualArea(PropertyMap(), Angle(1),
1490 Angle(2), Angle(3), Angle(4),
1491 Length(5), Length(6));
1492 EXPECT_TRUE(conv->validateParameters().empty());
1493
1494 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1495 "+proj=aea +lat_0=1 +lon_0=2 +lat_1=3 +lat_2=4 +x_0=5 +y_0=6");
1496
1497 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1498 "CONVERSION[\"Albers Equal Area\",\n"
1499 " METHOD[\"Albers Equal Area\",\n"
1500 " ID[\"EPSG\",9822]],\n"
1501 " PARAMETER[\"Latitude of false origin\",1,\n"
1502 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1503 " ID[\"EPSG\",8821]],\n"
1504 " PARAMETER[\"Longitude of false origin\",2,\n"
1505 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1506 " ID[\"EPSG\",8822]],\n"
1507 " PARAMETER[\"Latitude of 1st standard parallel\",3,\n"
1508 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1509 " ID[\"EPSG\",8823]],\n"
1510 " PARAMETER[\"Latitude of 2nd standard parallel\",4,\n"
1511 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1512 " ID[\"EPSG\",8824]],\n"
1513 " PARAMETER[\"Easting at false origin\",5,\n"
1514 " LENGTHUNIT[\"metre\",1],\n"
1515 " ID[\"EPSG\",8826]],\n"
1516 " PARAMETER[\"Northing at false origin\",6,\n"
1517 " LENGTHUNIT[\"metre\",1],\n"
1518 " ID[\"EPSG\",8827]]]");
1519
1520 EXPECT_EQ(
1521 conv->exportToWKT(
1522 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1523 "PROJECTION[\"Albers_Conic_Equal_Area\"],\n"
1524 "PARAMETER[\"latitude_of_center\",1],\n"
1525 "PARAMETER[\"longitude_of_center\",2],\n"
1526 "PARAMETER[\"standard_parallel_1\",3],\n"
1527 "PARAMETER[\"standard_parallel_2\",4],\n"
1528 "PARAMETER[\"false_easting\",5],\n"
1529 "PARAMETER[\"false_northing\",6]");
1530 }
1531
1532 // ---------------------------------------------------------------------------
1533
TEST(operation,azimuthal_equidistant_export)1534 TEST(operation, azimuthal_equidistant_export) {
1535 auto conv = Conversion::createAzimuthalEquidistant(
1536 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
1537 EXPECT_TRUE(conv->validateParameters().empty());
1538
1539 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1540 "+proj=aeqd +lat_0=1 +lon_0=2 +x_0=3 +y_0=4");
1541
1542 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1543 "CONVERSION[\"Modified Azimuthal Equidistant\",\n"
1544 " METHOD[\"Modified Azimuthal Equidistant\",\n"
1545 " ID[\"EPSG\",9832]],\n"
1546 " PARAMETER[\"Latitude of natural origin\",1,\n"
1547 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1548 " ID[\"EPSG\",8801]],\n"
1549 " PARAMETER[\"Longitude of natural origin\",2,\n"
1550 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1551 " ID[\"EPSG\",8802]],\n"
1552 " PARAMETER[\"False easting\",3,\n"
1553 " LENGTHUNIT[\"metre\",1],\n"
1554 " ID[\"EPSG\",8806]],\n"
1555 " PARAMETER[\"False northing\",4,\n"
1556 " LENGTHUNIT[\"metre\",1],\n"
1557 " ID[\"EPSG\",8807]]]");
1558
1559 EXPECT_EQ(
1560 conv->exportToWKT(
1561 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1562 "PROJECTION[\"Azimuthal_Equidistant\"],\n"
1563 "PARAMETER[\"latitude_of_center\",1],\n"
1564 "PARAMETER[\"longitude_of_center\",2],\n"
1565 "PARAMETER[\"false_easting\",3],\n"
1566 "PARAMETER[\"false_northing\",4]");
1567 }
1568
1569 // ---------------------------------------------------------------------------
1570
TEST(operation,guam_projection_export)1571 TEST(operation, guam_projection_export) {
1572 auto conv = Conversion::createGuamProjection(
1573 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
1574 EXPECT_TRUE(conv->validateParameters().empty());
1575
1576 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1577 "+proj=aeqd +guam +lat_0=1 +lon_0=2 +x_0=3 +y_0=4");
1578
1579 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1580 "CONVERSION[\"Guam Projection\",\n"
1581 " METHOD[\"Guam Projection\",\n"
1582 " ID[\"EPSG\",9831]],\n"
1583 " PARAMETER[\"Latitude of natural origin\",1,\n"
1584 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1585 " ID[\"EPSG\",8801]],\n"
1586 " PARAMETER[\"Longitude of natural origin\",2,\n"
1587 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1588 " ID[\"EPSG\",8802]],\n"
1589 " PARAMETER[\"False easting\",3,\n"
1590 " LENGTHUNIT[\"metre\",1],\n"
1591 " ID[\"EPSG\",8806]],\n"
1592 " PARAMETER[\"False northing\",4,\n"
1593 " LENGTHUNIT[\"metre\",1],\n"
1594 " ID[\"EPSG\",8807]]]");
1595
1596 EXPECT_THROW(
1597 conv->exportToWKT(
1598 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1599 FormattingException);
1600 }
1601
1602 // ---------------------------------------------------------------------------
1603
TEST(operation,bonne_export)1604 TEST(operation, bonne_export) {
1605 auto conv = Conversion::createBonne(PropertyMap(), Angle(1), Angle(2),
1606 Length(3), Length(4));
1607 EXPECT_TRUE(conv->validateParameters().empty());
1608
1609 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1610 "+proj=bonne +lat_1=1 +lon_0=2 +x_0=3 +y_0=4");
1611
1612 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1613 "CONVERSION[\"Bonne\",\n"
1614 " METHOD[\"Bonne\",\n"
1615 " ID[\"EPSG\",9827]],\n"
1616 " PARAMETER[\"Latitude of natural origin\",1,\n"
1617 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1618 " ID[\"EPSG\",8801]],\n"
1619 " PARAMETER[\"Longitude of natural origin\",2,\n"
1620 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1621 " ID[\"EPSG\",8802]],\n"
1622 " PARAMETER[\"False easting\",3,\n"
1623 " LENGTHUNIT[\"metre\",1],\n"
1624 " ID[\"EPSG\",8806]],\n"
1625 " PARAMETER[\"False northing\",4,\n"
1626 " LENGTHUNIT[\"metre\",1],\n"
1627 " ID[\"EPSG\",8807]]]");
1628
1629 EXPECT_EQ(
1630 conv->exportToWKT(
1631 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1632 "PROJECTION[\"Bonne\"],\n"
1633 "PARAMETER[\"standard_parallel_1\",1],\n"
1634 "PARAMETER[\"central_meridian\",2],\n"
1635 "PARAMETER[\"false_easting\",3],\n"
1636 "PARAMETER[\"false_northing\",4]");
1637
1638 auto obj = WKTParser().createFromWKT(
1639 "PROJCS[\"unnamed\","
1640 "GEOGCS[\"unnamed ellipse\","
1641 " DATUM[\"unknown\","
1642 " SPHEROID[\"unnamed\",6378137,298.257223563]],"
1643 " PRIMEM[\"Greenwich\",0],"
1644 " UNIT[\"degree\",0.0174532925199433]],"
1645 "PROJECTION[\"Bonne\"],"
1646 "PARAMETER[\"standard_parallel_1\",1],"
1647 "PARAMETER[\"central_meridian\",2],"
1648 "PARAMETER[\"false_easting\",3],"
1649 "PARAMETER[\"false_northing\",4],"
1650 "UNIT[\"metre\",1]]");
1651 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
1652 ASSERT_TRUE(crs != nullptr);
1653 EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
1654 "+proj=bonne +lat_1=1 +lon_0=2 +x_0=3 +y_0=4 +ellps=WGS84 "
1655 "+units=m +no_defs +type=crs");
1656 }
1657
1658 // ---------------------------------------------------------------------------
1659
TEST(operation,lambert_cylindrical_equal_area_spherical_export)1660 TEST(operation, lambert_cylindrical_equal_area_spherical_export) {
1661 auto conv = Conversion::createLambertCylindricalEqualAreaSpherical(
1662 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
1663 EXPECT_TRUE(conv->validateParameters().empty());
1664
1665 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1666 "+proj=cea +lat_ts=1 +lon_0=2 +x_0=3 +y_0=4");
1667
1668 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1669 "CONVERSION[\"Lambert Cylindrical Equal Area (Spherical)\",\n"
1670 " METHOD[\"Lambert Cylindrical Equal Area (Spherical)\",\n"
1671 " ID[\"EPSG\",9834]],\n"
1672 " PARAMETER[\"Latitude of 1st standard parallel\",1,\n"
1673 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1674 " ID[\"EPSG\",8823]],\n"
1675 " PARAMETER[\"Longitude of natural origin\",2,\n"
1676 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1677 " ID[\"EPSG\",8802]],\n"
1678 " PARAMETER[\"False easting\",3,\n"
1679 " LENGTHUNIT[\"metre\",1],\n"
1680 " ID[\"EPSG\",8806]],\n"
1681 " PARAMETER[\"False northing\",4,\n"
1682 " LENGTHUNIT[\"metre\",1],\n"
1683 " ID[\"EPSG\",8807]]]");
1684
1685 EXPECT_EQ(
1686 conv->exportToWKT(
1687 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1688 "PROJECTION[\"Cylindrical_Equal_Area\"],\n"
1689 "PARAMETER[\"standard_parallel_1\",1],\n"
1690 "PARAMETER[\"central_meridian\",2],\n"
1691 "PARAMETER[\"false_easting\",3],\n"
1692 "PARAMETER[\"false_northing\",4]");
1693 }
1694
1695 // ---------------------------------------------------------------------------
1696
TEST(operation,lambert_cylindrical_equal_area_export)1697 TEST(operation, lambert_cylindrical_equal_area_export) {
1698 auto conv = Conversion::createLambertCylindricalEqualArea(
1699 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
1700 EXPECT_TRUE(conv->validateParameters().empty());
1701
1702 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1703 "+proj=cea +lat_ts=1 +lon_0=2 +x_0=3 +y_0=4");
1704
1705 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1706 "CONVERSION[\"Lambert Cylindrical Equal Area\",\n"
1707 " METHOD[\"Lambert Cylindrical Equal Area\",\n"
1708 " ID[\"EPSG\",9835]],\n"
1709 " PARAMETER[\"Latitude of 1st standard parallel\",1,\n"
1710 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1711 " ID[\"EPSG\",8823]],\n"
1712 " PARAMETER[\"Longitude of natural origin\",2,\n"
1713 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1714 " ID[\"EPSG\",8802]],\n"
1715 " PARAMETER[\"False easting\",3,\n"
1716 " LENGTHUNIT[\"metre\",1],\n"
1717 " ID[\"EPSG\",8806]],\n"
1718 " PARAMETER[\"False northing\",4,\n"
1719 " LENGTHUNIT[\"metre\",1],\n"
1720 " ID[\"EPSG\",8807]]]");
1721
1722 EXPECT_EQ(
1723 conv->exportToWKT(
1724 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1725 "PROJECTION[\"Cylindrical_Equal_Area\"],\n"
1726 "PARAMETER[\"standard_parallel_1\",1],\n"
1727 "PARAMETER[\"central_meridian\",2],\n"
1728 "PARAMETER[\"false_easting\",3],\n"
1729 "PARAMETER[\"false_northing\",4]");
1730 }
1731
1732 // ---------------------------------------------------------------------------
1733
TEST(operation,lcc1sp_export)1734 TEST(operation, lcc1sp_export) {
1735 auto conv = Conversion::createLambertConicConformal_1SP(
1736 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
1737 EXPECT_TRUE(conv->validateParameters().empty());
1738
1739 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1740 "+proj=lcc +lat_1=1 +lat_0=1 +lon_0=2 +k_0=3 +x_0=4 +y_0=5");
1741
1742 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1743 "CONVERSION[\"Lambert Conic Conformal (1SP)\",\n"
1744 " METHOD[\"Lambert Conic Conformal (1SP)\",\n"
1745 " ID[\"EPSG\",9801]],\n"
1746 " PARAMETER[\"Latitude of natural origin\",1,\n"
1747 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1748 " ID[\"EPSG\",8801]],\n"
1749 " PARAMETER[\"Longitude of natural origin\",2,\n"
1750 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1751 " ID[\"EPSG\",8802]],\n"
1752 " PARAMETER[\"Scale factor at natural origin\",3,\n"
1753 " SCALEUNIT[\"unity\",1],\n"
1754 " ID[\"EPSG\",8805]],\n"
1755 " PARAMETER[\"False easting\",4,\n"
1756 " LENGTHUNIT[\"metre\",1],\n"
1757 " ID[\"EPSG\",8806]],\n"
1758 " PARAMETER[\"False northing\",5,\n"
1759 " LENGTHUNIT[\"metre\",1],\n"
1760 " ID[\"EPSG\",8807]]]");
1761
1762 EXPECT_EQ(
1763 conv->exportToWKT(
1764 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1765 "PROJECTION[\"Lambert_Conformal_Conic_1SP\"],\n"
1766 "PARAMETER[\"latitude_of_origin\",1],\n"
1767 "PARAMETER[\"central_meridian\",2],\n"
1768 "PARAMETER[\"scale_factor\",3],\n"
1769 "PARAMETER[\"false_easting\",4],\n"
1770 "PARAMETER[\"false_northing\",5]");
1771 }
1772
1773 // ---------------------------------------------------------------------------
1774
TEST(operation,lcc2sp_export)1775 TEST(operation, lcc2sp_export) {
1776 auto conv = Conversion::createLambertConicConformal_2SP(
1777 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Length(5),
1778 Length(6));
1779 EXPECT_TRUE(conv->validateParameters().empty());
1780
1781 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1782 "+proj=lcc +lat_0=1 +lon_0=2 +lat_1=3 +lat_2=4 +x_0=5 +y_0=6");
1783
1784 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1785 "CONVERSION[\"Lambert Conic Conformal (2SP)\",\n"
1786 " METHOD[\"Lambert Conic Conformal (2SP)\",\n"
1787 " ID[\"EPSG\",9802]],\n"
1788 " PARAMETER[\"Latitude of false origin\",1,\n"
1789 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1790 " ID[\"EPSG\",8821]],\n"
1791 " PARAMETER[\"Longitude of false origin\",2,\n"
1792 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1793 " ID[\"EPSG\",8822]],\n"
1794 " PARAMETER[\"Latitude of 1st standard parallel\",3,\n"
1795 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1796 " ID[\"EPSG\",8823]],\n"
1797 " PARAMETER[\"Latitude of 2nd standard parallel\",4,\n"
1798 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1799 " ID[\"EPSG\",8824]],\n"
1800 " PARAMETER[\"Easting at false origin\",5,\n"
1801 " LENGTHUNIT[\"metre\",1],\n"
1802 " ID[\"EPSG\",8826]],\n"
1803 " PARAMETER[\"Northing at false origin\",6,\n"
1804 " LENGTHUNIT[\"metre\",1],\n"
1805 " ID[\"EPSG\",8827]]]");
1806
1807 EXPECT_EQ(
1808 conv->exportToWKT(
1809 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1810 "PROJECTION[\"Lambert_Conformal_Conic_2SP\"],\n"
1811 "PARAMETER[\"latitude_of_origin\",1],\n"
1812 "PARAMETER[\"central_meridian\",2],\n"
1813 "PARAMETER[\"standard_parallel_1\",3],\n"
1814 "PARAMETER[\"standard_parallel_2\",4],\n"
1815 "PARAMETER[\"false_easting\",5],\n"
1816 "PARAMETER[\"false_northing\",6]");
1817 }
1818
1819 // ---------------------------------------------------------------------------
1820
TEST(operation,lcc2sp_isEquivalentTo_parallels_switched)1821 TEST(operation, lcc2sp_isEquivalentTo_parallels_switched) {
1822 auto conv1 = Conversion::createLambertConicConformal_2SP(
1823 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Length(5),
1824 Length(6));
1825 auto conv2 = Conversion::createLambertConicConformal_2SP(
1826 PropertyMap(), Angle(1), Angle(2), Angle(4), Angle(3), Length(5),
1827 Length(6));
1828
1829 EXPECT_TRUE(
1830 conv1->isEquivalentTo(conv2.get(), IComparable::Criterion::EQUIVALENT));
1831
1832 auto conv3 = Conversion::createLambertConicConformal_2SP(
1833 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(3), Length(5),
1834 Length(6));
1835
1836 EXPECT_FALSE(
1837 conv1->isEquivalentTo(conv3.get(), IComparable::Criterion::EQUIVALENT));
1838 }
1839
1840 // ---------------------------------------------------------------------------
1841
TEST(operation,lcc2sp_michigan_export)1842 TEST(operation, lcc2sp_michigan_export) {
1843 auto conv = Conversion::createLambertConicConformal_2SP_Michigan(
1844 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Length(5),
1845 Length(6), Scale(7));
1846 EXPECT_TRUE(conv->validateParameters().empty());
1847
1848 EXPECT_EQ(
1849 conv->exportToPROJString(PROJStringFormatter::create().get()),
1850 "+proj=lcc +lat_0=1 +lon_0=2 +lat_1=3 +lat_2=4 +x_0=5 +y_0=6 +k_0=7");
1851
1852 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1853 "CONVERSION[\"Lambert Conic Conformal (2SP Michigan)\",\n"
1854 " METHOD[\"Lambert Conic Conformal (2SP Michigan)\",\n"
1855 " ID[\"EPSG\",1051]],\n"
1856 " PARAMETER[\"Latitude of false origin\",1,\n"
1857 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1858 " ID[\"EPSG\",8821]],\n"
1859 " PARAMETER[\"Longitude of false origin\",2,\n"
1860 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1861 " ID[\"EPSG\",8822]],\n"
1862 " PARAMETER[\"Latitude of 1st standard parallel\",3,\n"
1863 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1864 " ID[\"EPSG\",8823]],\n"
1865 " PARAMETER[\"Latitude of 2nd standard parallel\",4,\n"
1866 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1867 " ID[\"EPSG\",8824]],\n"
1868 " PARAMETER[\"Easting at false origin\",5,\n"
1869 " LENGTHUNIT[\"metre\",1],\n"
1870 " ID[\"EPSG\",8826]],\n"
1871 " PARAMETER[\"Northing at false origin\",6,\n"
1872 " LENGTHUNIT[\"metre\",1],\n"
1873 " ID[\"EPSG\",8827]],\n"
1874 " PARAMETER[\"Ellipsoid scaling factor\",7,\n"
1875 " SCALEUNIT[\"unity\",1],\n"
1876 " ID[\"EPSG\",1038]]]");
1877
1878 EXPECT_THROW(
1879 conv->exportToWKT(
1880 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1881 FormattingException);
1882 }
1883
1884 // ---------------------------------------------------------------------------
1885
TEST(operation,lcc2sp_belgium_export)1886 TEST(operation, lcc2sp_belgium_export) {
1887 auto conv = Conversion::createLambertConicConformal_2SP_Belgium(
1888 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Length(5),
1889 Length(6));
1890 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1891 "+proj=lcc +lat_0=1 +lon_0=2 +lat_1=3 +lat_2=4 +x_0=5 +y_0=6");
1892
1893 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1894 "CONVERSION[\"Lambert Conic Conformal (2SP Belgium)\",\n"
1895 " METHOD[\"Lambert Conic Conformal (2SP Belgium)\",\n"
1896 " ID[\"EPSG\",9803]],\n"
1897 " PARAMETER[\"Latitude of false origin\",1,\n"
1898 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1899 " ID[\"EPSG\",8821]],\n"
1900 " PARAMETER[\"Longitude of false origin\",2,\n"
1901 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1902 " ID[\"EPSG\",8822]],\n"
1903 " PARAMETER[\"Latitude of 1st standard parallel\",3,\n"
1904 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1905 " ID[\"EPSG\",8823]],\n"
1906 " PARAMETER[\"Latitude of 2nd standard parallel\",4,\n"
1907 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1908 " ID[\"EPSG\",8824]],\n"
1909 " PARAMETER[\"Easting at false origin\",5,\n"
1910 " LENGTHUNIT[\"metre\",1],\n"
1911 " ID[\"EPSG\",8826]],\n"
1912 " PARAMETER[\"Northing at false origin\",6,\n"
1913 " LENGTHUNIT[\"metre\",1],\n"
1914 " ID[\"EPSG\",8827]]]");
1915
1916 EXPECT_EQ(
1917 conv->exportToWKT(
1918 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1919 "PROJECTION[\"Lambert_Conformal_Conic_2SP_Belgium\"],\n"
1920 "PARAMETER[\"latitude_of_origin\",1],\n"
1921 "PARAMETER[\"central_meridian\",2],\n"
1922 "PARAMETER[\"standard_parallel_1\",3],\n"
1923 "PARAMETER[\"standard_parallel_2\",4],\n"
1924 "PARAMETER[\"false_easting\",5],\n"
1925 "PARAMETER[\"false_northing\",6]");
1926 }
1927
1928 // ---------------------------------------------------------------------------
1929
TEST(operation,cassini_soldner_export)1930 TEST(operation, cassini_soldner_export) {
1931 auto conv = Conversion::createCassiniSoldner(
1932 PropertyMap(), Angle(1), Angle(2), Length(4), Length(5));
1933 EXPECT_TRUE(conv->validateParameters().empty());
1934
1935 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1936 "+proj=cass +lat_0=1 +lon_0=2 +x_0=4 +y_0=5");
1937
1938 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1939 "CONVERSION[\"Cassini-Soldner\",\n"
1940 " METHOD[\"Cassini-Soldner\",\n"
1941 " ID[\"EPSG\",9806]],\n"
1942 " PARAMETER[\"Latitude of natural origin\",1,\n"
1943 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1944 " ID[\"EPSG\",8801]],\n"
1945 " PARAMETER[\"Longitude of natural origin\",2,\n"
1946 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1947 " ID[\"EPSG\",8802]],\n"
1948 " PARAMETER[\"False easting\",4,\n"
1949 " LENGTHUNIT[\"metre\",1],\n"
1950 " ID[\"EPSG\",8806]],\n"
1951 " PARAMETER[\"False northing\",5,\n"
1952 " LENGTHUNIT[\"metre\",1],\n"
1953 " ID[\"EPSG\",8807]]]");
1954
1955 EXPECT_EQ(
1956 conv->exportToWKT(
1957 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
1958 "PROJECTION[\"Cassini_Soldner\"],\n"
1959 "PARAMETER[\"latitude_of_origin\",1],\n"
1960 "PARAMETER[\"central_meridian\",2],\n"
1961 "PARAMETER[\"false_easting\",4],\n"
1962 "PARAMETER[\"false_northing\",5]");
1963 }
1964
1965 // ---------------------------------------------------------------------------
1966
TEST(operation,equidistant_conic_export)1967 TEST(operation, equidistant_conic_export) {
1968 auto conv = Conversion::createEquidistantConic(PropertyMap(), Angle(1),
1969 Angle(2), Angle(3), Angle(4),
1970 Length(5), Length(6));
1971 EXPECT_TRUE(conv->validateParameters().empty());
1972
1973 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
1974 "+proj=eqdc +lat_0=1 +lon_0=2 +lat_1=3 +lat_2=4 +x_0=5 +y_0=6");
1975
1976 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
1977 "CONVERSION[\"Equidistant Conic\",\n"
1978 " METHOD[\"Equidistant Conic\"],\n"
1979 " PARAMETER[\"Latitude of natural origin\",1,\n"
1980 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1981 " ID[\"EPSG\",8801]],\n"
1982 " PARAMETER[\"Longitude of natural origin\",2,\n"
1983 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1984 " ID[\"EPSG\",8802]],\n"
1985 " PARAMETER[\"Latitude of 1st standard parallel\",3,\n"
1986 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1987 " ID[\"EPSG\",8823]],\n"
1988 " PARAMETER[\"Latitude of 2nd standard parallel\",4,\n"
1989 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
1990 " ID[\"EPSG\",8824]],\n"
1991 " PARAMETER[\"False easting\",5,\n"
1992 " LENGTHUNIT[\"metre\",1],\n"
1993 " ID[\"EPSG\",8806]],\n"
1994 " PARAMETER[\"False northing\",6,\n"
1995 " LENGTHUNIT[\"metre\",1],\n"
1996 " ID[\"EPSG\",8807]]]");
1997
1998 EXPECT_EQ(
1999 conv->exportToWKT(
2000 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2001 "PROJECTION[\"Equidistant_Conic\"],\n"
2002 "PARAMETER[\"latitude_of_center\",1],\n"
2003 "PARAMETER[\"longitude_of_center\",2],\n"
2004 "PARAMETER[\"standard_parallel_1\",3],\n"
2005 "PARAMETER[\"standard_parallel_2\",4],\n"
2006 "PARAMETER[\"false_easting\",5],\n"
2007 "PARAMETER[\"false_northing\",6]");
2008 }
2009
2010 // ---------------------------------------------------------------------------
2011
TEST(operation,eckert_export)2012 TEST(operation, eckert_export) {
2013
2014 std::vector<std::string> numbers{"", "1", "2", "3", "4", "5", "6"};
2015 std::vector<std::string> latinNumbers{"", "I", "II", "III",
2016 "IV", "V", "VI"};
2017
2018 for (int i = 1; i <= 6; i++) {
2019 auto conv =
2020 (i == 1)
2021 ? Conversion::createEckertI(PropertyMap(), Angle(1), Length(2),
2022 Length(3))
2023 : (i == 2)
2024 ? Conversion::createEckertII(PropertyMap(), Angle(1),
2025 Length(2), Length(3))
2026 : (i == 3)
2027 ? Conversion::createEckertIII(
2028 PropertyMap(), Angle(1), Length(2), Length(3))
2029 : (i == 4) ? Conversion::createEckertIV(
2030 PropertyMap(), Angle(1), Length(2),
2031 Length(3))
2032 : (i == 5) ? Conversion::createEckertV(
2033 PropertyMap(), Angle(1),
2034 Length(2), Length(3))
2035 :
2036
2037 Conversion::createEckertVI(
2038 PropertyMap(), Angle(1),
2039 Length(2), Length(3));
2040
2041 EXPECT_TRUE(conv->validateParameters().empty());
2042
2043 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2044 "+proj=eck" + numbers[i] + " +lon_0=1 +x_0=2 +y_0=3");
2045
2046 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2047 "CONVERSION[\"Eckert " + latinNumbers[i] +
2048 "\",\n"
2049 " METHOD[\"Eckert " +
2050 latinNumbers[i] +
2051 "\"],\n"
2052 " PARAMETER[\"Longitude of natural origin\",1,\n"
2053 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2054 " ID[\"EPSG\",8802]],\n"
2055 " PARAMETER[\"False easting\",2,\n"
2056 " LENGTHUNIT[\"metre\",1],\n"
2057 " ID[\"EPSG\",8806]],\n"
2058 " PARAMETER[\"False northing\",3,\n"
2059 " LENGTHUNIT[\"metre\",1],\n"
2060 " ID[\"EPSG\",8807]]]");
2061
2062 EXPECT_EQ(conv->exportToWKT(
2063 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL)
2064 .get()),
2065 "PROJECTION[\"Eckert_" + latinNumbers[i] +
2066 "\"],\n"
2067 "PARAMETER[\"central_meridian\",1],\n"
2068 "PARAMETER[\"false_easting\",2],\n"
2069 "PARAMETER[\"false_northing\",3]");
2070 }
2071 }
2072
2073 // ---------------------------------------------------------------------------
2074
TEST(operation,createEquidistantCylindrical)2075 TEST(operation, createEquidistantCylindrical) {
2076 auto conv = Conversion::createEquidistantCylindrical(
2077 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
2078 EXPECT_TRUE(conv->validateParameters().empty());
2079
2080 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2081 "+proj=eqc +lat_ts=1 +lat_0=0 +lon_0=2 +x_0=3 +y_0=4");
2082
2083 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2084 "CONVERSION[\"Equidistant Cylindrical\",\n"
2085 " METHOD[\"Equidistant Cylindrical\",\n"
2086 " ID[\"EPSG\",1028]],\n"
2087 " PARAMETER[\"Latitude of 1st standard parallel\",1,\n"
2088 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2089 " ID[\"EPSG\",8823]],\n"
2090 " PARAMETER[\"Longitude of natural origin\",2,\n"
2091 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2092 " ID[\"EPSG\",8802]],\n"
2093 " PARAMETER[\"False easting\",3,\n"
2094 " LENGTHUNIT[\"metre\",1],\n"
2095 " ID[\"EPSG\",8806]],\n"
2096 " PARAMETER[\"False northing\",4,\n"
2097 " LENGTHUNIT[\"metre\",1],\n"
2098 " ID[\"EPSG\",8807]]]");
2099
2100 EXPECT_EQ(
2101 conv->exportToWKT(
2102 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2103 "PROJECTION[\"Equirectangular\"],\n"
2104 "PARAMETER[\"standard_parallel_1\",1],\n"
2105 "PARAMETER[\"central_meridian\",2],\n"
2106 "PARAMETER[\"false_easting\",3],\n"
2107 "PARAMETER[\"false_northing\",4]");
2108
2109 EXPECT_TRUE(conv->validateParameters().empty());
2110 }
2111
2112 // ---------------------------------------------------------------------------
2113
TEST(operation,createEquidistantCylindricalSpherical)2114 TEST(operation, createEquidistantCylindricalSpherical) {
2115 auto conv = Conversion::createEquidistantCylindricalSpherical(
2116 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
2117 EXPECT_TRUE(conv->validateParameters().empty());
2118
2119 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2120 "+proj=eqc +lat_ts=1 +lat_0=0 +lon_0=2 +x_0=3 +y_0=4");
2121
2122 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2123 "CONVERSION[\"Equidistant Cylindrical (Spherical)\",\n"
2124 " METHOD[\"Equidistant Cylindrical (Spherical)\",\n"
2125 " ID[\"EPSG\",1029]],\n"
2126 " PARAMETER[\"Latitude of 1st standard parallel\",1,\n"
2127 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2128 " ID[\"EPSG\",8823]],\n"
2129 " PARAMETER[\"Longitude of natural origin\",2,\n"
2130 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2131 " ID[\"EPSG\",8802]],\n"
2132 " PARAMETER[\"False easting\",3,\n"
2133 " LENGTHUNIT[\"metre\",1],\n"
2134 " ID[\"EPSG\",8806]],\n"
2135 " PARAMETER[\"False northing\",4,\n"
2136 " LENGTHUNIT[\"metre\",1],\n"
2137 " ID[\"EPSG\",8807]]]");
2138
2139 EXPECT_EQ(
2140 conv->exportToWKT(
2141 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2142 "PROJECTION[\"Equirectangular\"],\n"
2143 "PARAMETER[\"standard_parallel_1\",1],\n"
2144 "PARAMETER[\"central_meridian\",2],\n"
2145 "PARAMETER[\"false_easting\",3],\n"
2146 "PARAMETER[\"false_northing\",4]");
2147
2148 EXPECT_TRUE(conv->validateParameters().empty());
2149 }
2150
2151 // ---------------------------------------------------------------------------
2152
TEST(operation,equidistant_cylindrical_lat_0)2153 TEST(operation, equidistant_cylindrical_lat_0) {
2154
2155 auto obj = PROJStringParser().createFromPROJString(
2156 "+proj=eqc +ellps=sphere +lat_0=-2 +lat_ts=1 +lon_0=-10 +type=crs");
2157 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
2158 ASSERT_TRUE(crs != nullptr);
2159
2160 auto wkt = crs->exportToWKT(WKTFormatter::create().get());
2161 EXPECT_TRUE(wkt.find("PARAMETER[\"Latitude of natural origin\",-2") !=
2162 std::string::npos)
2163 << wkt;
2164
2165 auto projString = crs->exportToPROJString(
2166 PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
2167 .get());
2168 EXPECT_EQ(projString,
2169 "+proj=eqc +lat_ts=1 +lat_0=-2 +lon_0=-10 +x_0=0 +y_0=0 "
2170 "+ellps=sphere +units=m +no_defs +type=crs");
2171 }
2172
2173 // ---------------------------------------------------------------------------
2174
TEST(operation,gall_export)2175 TEST(operation, gall_export) {
2176
2177 auto conv =
2178 Conversion::createGall(PropertyMap(), Angle(1), Length(2), Length(3));
2179 EXPECT_TRUE(conv->validateParameters().empty());
2180
2181 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2182 "+proj=gall +lon_0=1 +x_0=2 +y_0=3");
2183
2184 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2185 "CONVERSION[\"Gall Stereographic\",\n"
2186 " METHOD[\"Gall Stereographic\"],\n"
2187 " PARAMETER[\"Longitude of natural origin\",1,\n"
2188 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2189 " ID[\"EPSG\",8802]],\n"
2190 " PARAMETER[\"False easting\",2,\n"
2191 " LENGTHUNIT[\"metre\",1],\n"
2192 " ID[\"EPSG\",8806]],\n"
2193 " PARAMETER[\"False northing\",3,\n"
2194 " LENGTHUNIT[\"metre\",1],\n"
2195 " ID[\"EPSG\",8807]]]");
2196
2197 EXPECT_EQ(
2198 conv->exportToWKT(
2199 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2200 "PROJECTION[\"Gall_Stereographic\"],\n"
2201 "PARAMETER[\"central_meridian\",1],\n"
2202 "PARAMETER[\"false_easting\",2],\n"
2203 "PARAMETER[\"false_northing\",3]");
2204 }
2205
2206 // ---------------------------------------------------------------------------
2207
TEST(operation,goode_homolosine_export)2208 TEST(operation, goode_homolosine_export) {
2209
2210 auto conv = Conversion::createGoodeHomolosine(PropertyMap(), Angle(1),
2211 Length(2), Length(3));
2212 EXPECT_TRUE(conv->validateParameters().empty());
2213
2214 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2215 "+proj=goode +lon_0=1 +x_0=2 +y_0=3");
2216
2217 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2218 "CONVERSION[\"Goode Homolosine\",\n"
2219 " METHOD[\"Goode Homolosine\"],\n"
2220 " PARAMETER[\"Longitude of natural origin\",1,\n"
2221 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2222 " ID[\"EPSG\",8802]],\n"
2223 " PARAMETER[\"False easting\",2,\n"
2224 " LENGTHUNIT[\"metre\",1],\n"
2225 " ID[\"EPSG\",8806]],\n"
2226 " PARAMETER[\"False northing\",3,\n"
2227 " LENGTHUNIT[\"metre\",1],\n"
2228 " ID[\"EPSG\",8807]]]");
2229
2230 EXPECT_EQ(
2231 conv->exportToWKT(
2232 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2233 "PROJECTION[\"Goode_Homolosine\"],\n"
2234 "PARAMETER[\"central_meridian\",1],\n"
2235 "PARAMETER[\"false_easting\",2],\n"
2236 "PARAMETER[\"false_northing\",3]");
2237 }
2238
2239 // ---------------------------------------------------------------------------
2240
TEST(operation,interrupted_goode_homolosine_export)2241 TEST(operation, interrupted_goode_homolosine_export) {
2242
2243 auto conv = Conversion::createInterruptedGoodeHomolosine(
2244 PropertyMap(), Angle(1), Length(2), Length(3));
2245 EXPECT_TRUE(conv->validateParameters().empty());
2246
2247 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2248 "+proj=igh +lon_0=1 +x_0=2 +y_0=3");
2249
2250 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2251 "CONVERSION[\"Interrupted Goode Homolosine\",\n"
2252 " METHOD[\"Interrupted Goode Homolosine\"],\n"
2253 " PARAMETER[\"Longitude of natural origin\",1,\n"
2254 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2255 " ID[\"EPSG\",8802]],\n"
2256 " PARAMETER[\"False easting\",2,\n"
2257 " LENGTHUNIT[\"metre\",1],\n"
2258 " ID[\"EPSG\",8806]],\n"
2259 " PARAMETER[\"False northing\",3,\n"
2260 " LENGTHUNIT[\"metre\",1],\n"
2261 " ID[\"EPSG\",8807]]]");
2262
2263 EXPECT_EQ(
2264 conv->exportToWKT(
2265 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2266 "PROJECTION[\"Interrupted_Goode_Homolosine\"],\n"
2267 "PARAMETER[\"central_meridian\",1],\n"
2268 "PARAMETER[\"false_easting\",2],\n"
2269 "PARAMETER[\"false_northing\",3]");
2270 }
2271
2272 // ---------------------------------------------------------------------------
2273
TEST(operation,geostationary_satellite_sweep_x_export)2274 TEST(operation, geostationary_satellite_sweep_x_export) {
2275
2276 auto conv = Conversion::createGeostationarySatelliteSweepX(
2277 PropertyMap(), Angle(1), Length(2), Length(3), Length(4));
2278 EXPECT_TRUE(conv->validateParameters().empty());
2279
2280 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2281 "+proj=geos +sweep=x +lon_0=1 +h=2 +x_0=3 +y_0=4");
2282
2283 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2284 "CONVERSION[\"Geostationary Satellite (Sweep X)\",\n"
2285 " METHOD[\"Geostationary Satellite (Sweep X)\"],\n"
2286 " PARAMETER[\"Longitude of natural origin\",1,\n"
2287 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2288 " ID[\"EPSG\",8802]],\n"
2289 " PARAMETER[\"Satellite Height\",2,\n"
2290 " LENGTHUNIT[\"metre\",1,\n"
2291 " ID[\"EPSG\",9001]]],\n"
2292 " PARAMETER[\"False easting\",3,\n"
2293 " LENGTHUNIT[\"metre\",1],\n"
2294 " ID[\"EPSG\",8806]],\n"
2295 " PARAMETER[\"False northing\",4,\n"
2296 " LENGTHUNIT[\"metre\",1],\n"
2297 " ID[\"EPSG\",8807]]]");
2298
2299 auto crs = ProjectedCRS::create(
2300 PropertyMap(), GeographicCRS::EPSG_4326, conv,
2301 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
2302 auto wkt1 = crs->exportToWKT(
2303 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get());
2304 EXPECT_TRUE(wkt1.find("PROJECTION[\"Geostationary_Satellite\"]") !=
2305 std::string::npos)
2306 << wkt1;
2307 EXPECT_TRUE(wkt1.find("EXTENSION[\"PROJ4\",\"+proj=geos +sweep=x +lon_0=1 "
2308 "+h=2 +x_0=3 +y_0=4 +datum=WGS84 +units=m "
2309 "+no_defs\"]]") != std::string::npos)
2310 << wkt1;
2311 }
2312
2313 // ---------------------------------------------------------------------------
2314
TEST(operation,geostationary_satellite_sweep_y_export)2315 TEST(operation, geostationary_satellite_sweep_y_export) {
2316
2317 auto conv = Conversion::createGeostationarySatelliteSweepY(
2318 PropertyMap(), Angle(1), Length(2), Length(3), Length(4));
2319 EXPECT_TRUE(conv->validateParameters().empty());
2320
2321 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2322 "+proj=geos +lon_0=1 +h=2 +x_0=3 +y_0=4");
2323
2324 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2325 "CONVERSION[\"Geostationary Satellite (Sweep Y)\",\n"
2326 " METHOD[\"Geostationary Satellite (Sweep Y)\"],\n"
2327 " PARAMETER[\"Longitude of natural origin\",1,\n"
2328 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2329 " ID[\"EPSG\",8802]],\n"
2330 " PARAMETER[\"Satellite Height\",2,\n"
2331 " LENGTHUNIT[\"metre\",1,\n"
2332 " ID[\"EPSG\",9001]]],\n"
2333 " PARAMETER[\"False easting\",3,\n"
2334 " LENGTHUNIT[\"metre\",1],\n"
2335 " ID[\"EPSG\",8806]],\n"
2336 " PARAMETER[\"False northing\",4,\n"
2337 " LENGTHUNIT[\"metre\",1],\n"
2338 " ID[\"EPSG\",8807]]]");
2339
2340 EXPECT_EQ(
2341 conv->exportToWKT(
2342 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2343 "PROJECTION[\"Geostationary_Satellite\"],\n"
2344 "PARAMETER[\"central_meridian\",1],\n"
2345 "PARAMETER[\"satellite_height\",2],\n"
2346 "PARAMETER[\"false_easting\",3],\n"
2347 "PARAMETER[\"false_northing\",4]");
2348 }
2349
2350 // ---------------------------------------------------------------------------
2351
TEST(operation,gnomonic_export)2352 TEST(operation, gnomonic_export) {
2353 auto conv = Conversion::createGnomonic(PropertyMap(), Angle(1), Angle(2),
2354 Length(4), Length(5));
2355 EXPECT_TRUE(conv->validateParameters().empty());
2356
2357 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2358 "+proj=gnom +lat_0=1 +lon_0=2 +x_0=4 +y_0=5");
2359
2360 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2361 "CONVERSION[\"Gnomonic\",\n"
2362 " METHOD[\"Gnomonic\"],\n"
2363 " PARAMETER[\"Latitude of natural origin\",1,\n"
2364 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2365 " ID[\"EPSG\",8801]],\n"
2366 " PARAMETER[\"Longitude of natural origin\",2,\n"
2367 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2368 " ID[\"EPSG\",8802]],\n"
2369 " PARAMETER[\"False easting\",4,\n"
2370 " LENGTHUNIT[\"metre\",1],\n"
2371 " ID[\"EPSG\",8806]],\n"
2372 " PARAMETER[\"False northing\",5,\n"
2373 " LENGTHUNIT[\"metre\",1],\n"
2374 " ID[\"EPSG\",8807]]]");
2375
2376 EXPECT_EQ(
2377 conv->exportToWKT(
2378 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2379 "PROJECTION[\"Gnomonic\"],\n"
2380 "PARAMETER[\"latitude_of_origin\",1],\n"
2381 "PARAMETER[\"central_meridian\",2],\n"
2382 "PARAMETER[\"false_easting\",4],\n"
2383 "PARAMETER[\"false_northing\",5]");
2384 }
2385
2386 // ---------------------------------------------------------------------------
2387
TEST(operation,hotine_oblique_mercator_variant_A_export)2388 TEST(operation, hotine_oblique_mercator_variant_A_export) {
2389 auto conv = Conversion::createHotineObliqueMercatorVariantA(
2390 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Scale(5),
2391 Length(6), Length(7));
2392 EXPECT_TRUE(conv->validateParameters().empty());
2393
2394 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2395 "+proj=omerc +no_uoff +lat_0=1 +lonc=2 +alpha=3 +gamma=4 +k=5 "
2396 "+x_0=6 +y_0=7");
2397
2398 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2399 "CONVERSION[\"Hotine Oblique Mercator (variant A)\",\n"
2400 " METHOD[\"Hotine Oblique Mercator (variant A)\",\n"
2401 " ID[\"EPSG\",9812]],\n"
2402 " PARAMETER[\"Latitude of projection centre\",1,\n"
2403 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2404 " ID[\"EPSG\",8811]],\n"
2405 " PARAMETER[\"Longitude of projection centre\",2,\n"
2406 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2407 " ID[\"EPSG\",8812]],\n"
2408 " PARAMETER[\"Azimuth of initial line\",3,\n"
2409 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2410 " ID[\"EPSG\",8813]],\n"
2411 " PARAMETER[\"Angle from Rectified to Skew Grid\",4,\n"
2412 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2413 " ID[\"EPSG\",8814]],\n"
2414 " PARAMETER[\"Scale factor on initial line\",5,\n"
2415 " SCALEUNIT[\"unity\",1],\n"
2416 " ID[\"EPSG\",8815]],\n"
2417 " PARAMETER[\"False easting\",6,\n"
2418 " LENGTHUNIT[\"metre\",1],\n"
2419 " ID[\"EPSG\",8806]],\n"
2420 " PARAMETER[\"False northing\",7,\n"
2421 " LENGTHUNIT[\"metre\",1],\n"
2422 " ID[\"EPSG\",8807]]]");
2423
2424 EXPECT_EQ(
2425 conv->exportToWKT(
2426 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2427 "PROJECTION[\"Hotine_Oblique_Mercator\"],\n"
2428 "PARAMETER[\"latitude_of_center\",1],\n"
2429 "PARAMETER[\"longitude_of_center\",2],\n"
2430 "PARAMETER[\"azimuth\",3],\n"
2431 "PARAMETER[\"rectified_grid_angle\",4],\n"
2432 "PARAMETER[\"scale_factor\",5],\n"
2433 "PARAMETER[\"false_easting\",6],\n"
2434 "PARAMETER[\"false_northing\",7]");
2435 }
2436
2437 // ---------------------------------------------------------------------------
2438
TEST(operation,hotine_oblique_mercator_variant_A_export_swiss_mercator)2439 TEST(operation, hotine_oblique_mercator_variant_A_export_swiss_mercator) {
2440 auto conv = Conversion::createHotineObliqueMercatorVariantA(
2441 PropertyMap(), Angle(1), Angle(2), Angle(90), Angle(90), Scale(5),
2442 Length(6), Length(7));
2443 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2444 "+proj=somerc +lat_0=1 +lon_0=2 +k_0=5 "
2445 "+x_0=6 +y_0=7");
2446 }
2447
2448 // ---------------------------------------------------------------------------
2449
TEST(operation,hotine_oblique_mercator_variant_B_export)2450 TEST(operation, hotine_oblique_mercator_variant_B_export) {
2451 auto conv = Conversion::createHotineObliqueMercatorVariantB(
2452 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Scale(5),
2453 Length(6), Length(7));
2454 EXPECT_TRUE(conv->validateParameters().empty());
2455
2456 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2457 "+proj=omerc +lat_0=1 +lonc=2 +alpha=3 +gamma=4 +k=5 "
2458 "+x_0=6 +y_0=7");
2459
2460 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2461 "CONVERSION[\"Hotine Oblique Mercator (variant B)\",\n"
2462 " METHOD[\"Hotine Oblique Mercator (variant B)\",\n"
2463 " ID[\"EPSG\",9815]],\n"
2464 " PARAMETER[\"Latitude of projection centre\",1,\n"
2465 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2466 " ID[\"EPSG\",8811]],\n"
2467 " PARAMETER[\"Longitude of projection centre\",2,\n"
2468 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2469 " ID[\"EPSG\",8812]],\n"
2470 " PARAMETER[\"Azimuth of initial line\",3,\n"
2471 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2472 " ID[\"EPSG\",8813]],\n"
2473 " PARAMETER[\"Angle from Rectified to Skew Grid\",4,\n"
2474 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2475 " ID[\"EPSG\",8814]],\n"
2476 " PARAMETER[\"Scale factor on initial line\",5,\n"
2477 " SCALEUNIT[\"unity\",1],\n"
2478 " ID[\"EPSG\",8815]],\n"
2479 " PARAMETER[\"Easting at projection centre\",6,\n"
2480 " LENGTHUNIT[\"metre\",1],\n"
2481 " ID[\"EPSG\",8816]],\n"
2482 " PARAMETER[\"Northing at projection centre\",7,\n"
2483 " LENGTHUNIT[\"metre\",1],\n"
2484 " ID[\"EPSG\",8817]]]");
2485
2486 EXPECT_EQ(
2487 conv->exportToWKT(
2488 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2489 "PROJECTION[\"Hotine_Oblique_Mercator_Azimuth_Center\"],\n"
2490 "PARAMETER[\"latitude_of_center\",1],\n"
2491 "PARAMETER[\"longitude_of_center\",2],\n"
2492 "PARAMETER[\"azimuth\",3],\n"
2493 "PARAMETER[\"rectified_grid_angle\",4],\n"
2494 "PARAMETER[\"scale_factor\",5],\n"
2495 "PARAMETER[\"false_easting\",6],\n"
2496 "PARAMETER[\"false_northing\",7]");
2497 }
2498
2499 // ---------------------------------------------------------------------------
2500
TEST(operation,hotine_oblique_mercator_variant_B_export_swiss_mercator)2501 TEST(operation, hotine_oblique_mercator_variant_B_export_swiss_mercator) {
2502 auto conv = Conversion::createHotineObliqueMercatorVariantB(
2503 PropertyMap(), Angle(1), Angle(2), Angle(90), Angle(90), Scale(5),
2504 Length(6), Length(7));
2505 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2506 "+proj=somerc +lat_0=1 +lon_0=2 +k_0=5 "
2507 "+x_0=6 +y_0=7");
2508 }
2509
2510 // ---------------------------------------------------------------------------
2511
TEST(operation,hotine_oblique_mercator_two_point_natural_origin_export)2512 TEST(operation, hotine_oblique_mercator_two_point_natural_origin_export) {
2513 auto conv = Conversion::createHotineObliqueMercatorTwoPointNaturalOrigin(
2514 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Angle(5),
2515 Scale(6), Length(7), Length(8));
2516 EXPECT_TRUE(conv->validateParameters().empty());
2517
2518 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2519 "+proj=omerc +lat_0=1 +lat_1=2 +lon_1=3 +lat_2=4 +lon_2=5 +k=6 "
2520 "+x_0=7 +y_0=8");
2521
2522 auto formatter = WKTFormatter::create();
2523 formatter->simulCurNodeHasId();
2524 EXPECT_EQ(
2525 conv->exportToWKT(formatter.get()),
2526 "CONVERSION[\"Hotine Oblique Mercator Two Point Natural Origin\",\n"
2527 " METHOD[\"Hotine Oblique Mercator Two Point Natural Origin\"],\n"
2528 " PARAMETER[\"Latitude of projection centre\",1,\n"
2529 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2530 " ID[\"EPSG\",8811]],\n"
2531 " PARAMETER[\"Latitude of 1st point\",2,\n"
2532 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
2533 " PARAMETER[\"Longitude of 1st point\",3,\n"
2534 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
2535 " PARAMETER[\"Latitude of 2nd point\",4,\n"
2536 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
2537 " PARAMETER[\"Longitude of 2nd point\",5,\n"
2538 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
2539 " PARAMETER[\"Scale factor on initial line\",6,\n"
2540 " SCALEUNIT[\"unity\",1],\n"
2541 " ID[\"EPSG\",8815]],\n"
2542 " PARAMETER[\"Easting at projection centre\",7,\n"
2543 " LENGTHUNIT[\"metre\",1],\n"
2544 " ID[\"EPSG\",8816]],\n"
2545 " PARAMETER[\"Northing at projection centre\",8,\n"
2546 " LENGTHUNIT[\"metre\",1],\n"
2547 " ID[\"EPSG\",8817]]]");
2548
2549 EXPECT_EQ(
2550 conv->exportToWKT(
2551 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2552 "PROJECTION[\"Hotine_Oblique_Mercator_Two_Point_Natural_Origin\"],\n"
2553 "PARAMETER[\"latitude_of_center\",1],\n"
2554 "PARAMETER[\"latitude_of_point_1\",2],\n"
2555 "PARAMETER[\"longitude_of_point_1\",3],\n"
2556 "PARAMETER[\"latitude_of_point_2\",4],\n"
2557 "PARAMETER[\"longitude_of_point_2\",5],\n"
2558 "PARAMETER[\"scale_factor\",6],\n"
2559 "PARAMETER[\"false_easting\",7],\n"
2560 "PARAMETER[\"false_northing\",8]");
2561 }
2562
2563 // ---------------------------------------------------------------------------
2564
TEST(operation,laborde_oblique_mercator_export)2565 TEST(operation, laborde_oblique_mercator_export) {
2566 auto conv = Conversion::createLabordeObliqueMercator(
2567 PropertyMap(), Angle(1), Angle(2), Angle(3), Scale(4), Length(5),
2568 Length(6));
2569 EXPECT_TRUE(conv->validateParameters().empty());
2570
2571 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2572 "+proj=labrd +lat_0=1 +lon_0=2 +azi=3 +k=4 +x_0=5 +y_0=6");
2573
2574 auto formatter = WKTFormatter::create();
2575 formatter->simulCurNodeHasId();
2576 EXPECT_EQ(conv->exportToWKT(formatter.get()),
2577 "CONVERSION[\"Laborde Oblique Mercator\",\n"
2578 " METHOD[\"Laborde Oblique Mercator\",\n"
2579 " ID[\"EPSG\",9813]],\n"
2580 " PARAMETER[\"Latitude of projection centre\",1,\n"
2581 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2582 " ID[\"EPSG\",8811]],\n"
2583 " PARAMETER[\"Longitude of projection centre\",2,\n"
2584 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2585 " ID[\"EPSG\",8812]],\n"
2586 " PARAMETER[\"Azimuth of initial line\",3,\n"
2587 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2588 " ID[\"EPSG\",8813]],\n"
2589 " PARAMETER[\"Scale factor on initial line\",4,\n"
2590 " SCALEUNIT[\"unity\",1],\n"
2591 " ID[\"EPSG\",8815]],\n"
2592 " PARAMETER[\"False easting\",5,\n"
2593 " LENGTHUNIT[\"metre\",1],\n"
2594 " ID[\"EPSG\",8806]],\n"
2595 " PARAMETER[\"False northing\",6,\n"
2596 " LENGTHUNIT[\"metre\",1],\n"
2597 " ID[\"EPSG\",8807]]]");
2598
2599 EXPECT_EQ(
2600 conv->exportToWKT(
2601 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2602 "PROJECTION[\"Laborde_Oblique_Mercator\"],\n"
2603 "PARAMETER[\"latitude_of_center\",1],\n"
2604 "PARAMETER[\"longitude_of_center\",2],\n"
2605 "PARAMETER[\"azimuth\",3],\n"
2606 "PARAMETER[\"scale_factor\",4],\n"
2607 "PARAMETER[\"false_easting\",5],\n"
2608 "PARAMETER[\"false_northing\",6]");
2609 }
2610
2611 // ---------------------------------------------------------------------------
2612
TEST(operation,imw_polyconic_export)2613 TEST(operation, imw_polyconic_export) {
2614 auto conv = Conversion::createInternationalMapWorldPolyconic(
2615 PropertyMap(), Angle(1), Angle(3), Angle(4), Length(5), Length(6));
2616 EXPECT_TRUE(conv->validateParameters().empty());
2617
2618 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2619 "+proj=imw_p +lon_0=1 +lat_1=3 +lat_2=4 +x_0=5 +y_0=6");
2620
2621 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2622 "CONVERSION[\"International Map of the World Polyconic\",\n"
2623 " METHOD[\"International Map of the World Polyconic\"],\n"
2624 " PARAMETER[\"Longitude of natural origin\",1,\n"
2625 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2626 " ID[\"EPSG\",8802]],\n"
2627 " PARAMETER[\"Latitude of 1st point\",3,\n"
2628 " ANGLEUNIT[\"degree\",0.0174532925199433,\n"
2629 " ID[\"EPSG\",9122]]],\n"
2630 " PARAMETER[\"Latitude of 2nd point\",4,\n"
2631 " ANGLEUNIT[\"degree\",0.0174532925199433,\n"
2632 " ID[\"EPSG\",9122]]],\n"
2633 " PARAMETER[\"False easting\",5,\n"
2634 " LENGTHUNIT[\"metre\",1],\n"
2635 " ID[\"EPSG\",8806]],\n"
2636 " PARAMETER[\"False northing\",6,\n"
2637 " LENGTHUNIT[\"metre\",1],\n"
2638 " ID[\"EPSG\",8807]]]");
2639
2640 EXPECT_EQ(
2641 conv->exportToWKT(
2642 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2643 "PROJECTION[\"International_Map_of_the_World_Polyconic\"],\n"
2644 "PARAMETER[\"central_meridian\",1],\n"
2645 "PARAMETER[\"Latitude_Of_1st_Point\",3],\n"
2646 "PARAMETER[\"Latitude_Of_2nd_Point\",4],\n"
2647 "PARAMETER[\"false_easting\",5],\n"
2648 "PARAMETER[\"false_northing\",6]");
2649 }
2650
2651 // ---------------------------------------------------------------------------
2652
TEST(operation,krovak_north_oriented_export)2653 TEST(operation, krovak_north_oriented_export) {
2654 auto conv = Conversion::createKrovakNorthOriented(
2655 PropertyMap(), Angle(49.5), Angle(42.5), Angle(30.2881397527778),
2656 Angle(78.5), Scale(0.9999), Length(5), Length(6));
2657 EXPECT_TRUE(conv->validateParameters().empty());
2658
2659 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2660 "+proj=krovak +lat_0=49.5 +lon_0=42.5 +alpha=30.2881397527778 "
2661 "+k=0.9999 +x_0=5 +y_0=6");
2662
2663 EXPECT_EQ(
2664 conv->exportToWKT(WKTFormatter::create().get()),
2665 "CONVERSION[\"Krovak (North Orientated)\",\n"
2666 " METHOD[\"Krovak (North Orientated)\",\n"
2667 " ID[\"EPSG\",1041]],\n"
2668 " PARAMETER[\"Latitude of projection centre\",49.5,\n"
2669 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2670 " ID[\"EPSG\",8811]],\n"
2671 " PARAMETER[\"Longitude of origin\",42.5,\n"
2672 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2673 " ID[\"EPSG\",8833]],\n"
2674 " PARAMETER[\"Co-latitude of cone axis\",30.2881397527778,\n"
2675 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2676 " ID[\"EPSG\",1036]],\n"
2677 " PARAMETER[\"Latitude of pseudo standard parallel\",78.5,\n"
2678 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2679 " ID[\"EPSG\",8818]],\n"
2680 " PARAMETER[\"Scale factor on pseudo standard parallel\",0.9999,\n"
2681 " SCALEUNIT[\"unity\",1],\n"
2682 " ID[\"EPSG\",8819]],\n"
2683 " PARAMETER[\"False easting\",5,\n"
2684 " LENGTHUNIT[\"metre\",1],\n"
2685 " ID[\"EPSG\",8806]],\n"
2686 " PARAMETER[\"False northing\",6,\n"
2687 " LENGTHUNIT[\"metre\",1],\n"
2688 " ID[\"EPSG\",8807]]]");
2689
2690 EXPECT_EQ(
2691 conv->exportToWKT(
2692 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2693 "PROJECTION[\"Krovak\"],\n"
2694 "PARAMETER[\"latitude_of_center\",49.5],\n"
2695 "PARAMETER[\"longitude_of_center\",42.5],\n"
2696 "PARAMETER[\"azimuth\",30.2881397527778],\n"
2697 "PARAMETER[\"pseudo_standard_parallel_1\",78.5],\n"
2698 "PARAMETER[\"scale_factor\",0.9999],\n"
2699 "PARAMETER[\"false_easting\",5],\n"
2700 "PARAMETER[\"false_northing\",6]");
2701 }
2702
2703 // ---------------------------------------------------------------------------
2704
TEST(operation,krovak_export)2705 TEST(operation, krovak_export) {
2706 auto conv = Conversion::createKrovak(
2707 PropertyMap(), Angle(49.5), Angle(42.5), Angle(30.2881397527778),
2708 Angle(78.5), Scale(0.9999), Length(5), Length(6));
2709 EXPECT_TRUE(conv->validateParameters().empty());
2710
2711 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2712 "+proj=krovak +axis=swu +lat_0=49.5 +lon_0=42.5 "
2713 "+alpha=30.2881397527778 +k=0.9999 +x_0=5 "
2714 "+y_0=6");
2715
2716 EXPECT_EQ(
2717 conv->exportToWKT(WKTFormatter::create().get()),
2718 "CONVERSION[\"Krovak\",\n"
2719 " METHOD[\"Krovak\",\n"
2720 " ID[\"EPSG\",9819]],\n"
2721 " PARAMETER[\"Latitude of projection centre\",49.5,\n"
2722 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2723 " ID[\"EPSG\",8811]],\n"
2724 " PARAMETER[\"Longitude of origin\",42.5,\n"
2725 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2726 " ID[\"EPSG\",8833]],\n"
2727 " PARAMETER[\"Co-latitude of cone axis\",30.2881397527778,\n"
2728 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2729 " ID[\"EPSG\",1036]],\n"
2730 " PARAMETER[\"Latitude of pseudo standard parallel\",78.5,\n"
2731 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2732 " ID[\"EPSG\",8818]],\n"
2733 " PARAMETER[\"Scale factor on pseudo standard parallel\",0.9999,\n"
2734 " SCALEUNIT[\"unity\",1],\n"
2735 " ID[\"EPSG\",8819]],\n"
2736 " PARAMETER[\"False easting\",5,\n"
2737 " LENGTHUNIT[\"metre\",1],\n"
2738 " ID[\"EPSG\",8806]],\n"
2739 " PARAMETER[\"False northing\",6,\n"
2740 " LENGTHUNIT[\"metre\",1],\n"
2741 " ID[\"EPSG\",8807]]]");
2742
2743 EXPECT_EQ(
2744 conv->exportToWKT(
2745 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2746 "PROJECTION[\"Krovak\"],\n"
2747 "PARAMETER[\"latitude_of_center\",49.5],\n"
2748 "PARAMETER[\"longitude_of_center\",42.5],\n"
2749 "PARAMETER[\"azimuth\",30.2881397527778],\n"
2750 "PARAMETER[\"pseudo_standard_parallel_1\",78.5],\n"
2751 "PARAMETER[\"scale_factor\",0.9999],\n"
2752 "PARAMETER[\"false_easting\",5],\n"
2753 "PARAMETER[\"false_northing\",6]");
2754 }
2755
2756 // ---------------------------------------------------------------------------
2757
TEST(operation,lambert_azimuthal_equal_area_export)2758 TEST(operation, lambert_azimuthal_equal_area_export) {
2759 auto conv = Conversion::createLambertAzimuthalEqualArea(
2760 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
2761 EXPECT_TRUE(conv->validateParameters().empty());
2762
2763 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2764 "+proj=laea +lat_0=1 +lon_0=2 +x_0=3 +y_0=4");
2765
2766 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2767 "CONVERSION[\"Lambert Azimuthal Equal Area\",\n"
2768 " METHOD[\"Lambert Azimuthal Equal Area\",\n"
2769 " ID[\"EPSG\",9820]],\n"
2770 " PARAMETER[\"Latitude of natural origin\",1,\n"
2771 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2772 " ID[\"EPSG\",8801]],\n"
2773 " PARAMETER[\"Longitude of natural origin\",2,\n"
2774 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2775 " ID[\"EPSG\",8802]],\n"
2776 " PARAMETER[\"False easting\",3,\n"
2777 " LENGTHUNIT[\"metre\",1],\n"
2778 " ID[\"EPSG\",8806]],\n"
2779 " PARAMETER[\"False northing\",4,\n"
2780 " LENGTHUNIT[\"metre\",1],\n"
2781 " ID[\"EPSG\",8807]]]");
2782
2783 EXPECT_EQ(
2784 conv->exportToWKT(
2785 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2786 "PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],\n"
2787 "PARAMETER[\"latitude_of_center\",1],\n"
2788 "PARAMETER[\"longitude_of_center\",2],\n"
2789 "PARAMETER[\"false_easting\",3],\n"
2790 "PARAMETER[\"false_northing\",4]");
2791 }
2792
2793 // ---------------------------------------------------------------------------
2794
TEST(operation,miller_cylindrical_export)2795 TEST(operation, miller_cylindrical_export) {
2796 auto conv = Conversion::createMillerCylindrical(PropertyMap(), Angle(2),
2797 Length(3), Length(4));
2798 EXPECT_TRUE(conv->validateParameters().empty());
2799
2800 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2801 "+proj=mill +R_A +lon_0=2 +x_0=3 +y_0=4");
2802
2803 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2804 "CONVERSION[\"Miller Cylindrical\",\n"
2805 " METHOD[\"Miller Cylindrical\"],\n"
2806 " PARAMETER[\"Longitude of natural origin\",2,\n"
2807 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2808 " ID[\"EPSG\",8802]],\n"
2809 " PARAMETER[\"False easting\",3,\n"
2810 " LENGTHUNIT[\"metre\",1],\n"
2811 " ID[\"EPSG\",8806]],\n"
2812 " PARAMETER[\"False northing\",4,\n"
2813 " LENGTHUNIT[\"metre\",1],\n"
2814 " ID[\"EPSG\",8807]]]");
2815
2816 EXPECT_EQ(
2817 conv->exportToWKT(
2818 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2819 "PROJECTION[\"Miller_Cylindrical\"],\n"
2820 "PARAMETER[\"longitude_of_center\",2],\n"
2821 "PARAMETER[\"false_easting\",3],\n"
2822 "PARAMETER[\"false_northing\",4]");
2823 }
2824
2825 // ---------------------------------------------------------------------------
2826
TEST(operation,mercator_variant_A_export)2827 TEST(operation, mercator_variant_A_export) {
2828 auto conv = Conversion::createMercatorVariantA(
2829 PropertyMap(), Angle(0), Angle(1), Scale(2), Length(3), Length(4));
2830 EXPECT_TRUE(conv->validateParameters().empty());
2831
2832 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2833 "+proj=merc +lon_0=1 +k=2 +x_0=3 +y_0=4");
2834
2835 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2836 "CONVERSION[\"Mercator (variant A)\",\n"
2837 " METHOD[\"Mercator (variant A)\",\n"
2838 " ID[\"EPSG\",9804]],\n"
2839 " PARAMETER[\"Latitude of natural origin\",0,\n"
2840 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2841 " ID[\"EPSG\",8801]],\n"
2842 " PARAMETER[\"Longitude of natural origin\",1,\n"
2843 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2844 " ID[\"EPSG\",8802]],\n"
2845 " PARAMETER[\"Scale factor at natural origin\",2,\n"
2846 " SCALEUNIT[\"unity\",1],\n"
2847 " ID[\"EPSG\",8805]],\n"
2848 " PARAMETER[\"False easting\",3,\n"
2849 " LENGTHUNIT[\"metre\",1],\n"
2850 " ID[\"EPSG\",8806]],\n"
2851 " PARAMETER[\"False northing\",4,\n"
2852 " LENGTHUNIT[\"metre\",1],\n"
2853 " ID[\"EPSG\",8807]]]");
2854
2855 EXPECT_EQ(
2856 conv->exportToWKT(
2857 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2858 "PROJECTION[\"Mercator_1SP\"],\n"
2859 "PARAMETER[\"central_meridian\",1],\n"
2860 "PARAMETER[\"scale_factor\",2],\n"
2861 "PARAMETER[\"false_easting\",3],\n"
2862 "PARAMETER[\"false_northing\",4]");
2863 }
2864
2865 // ---------------------------------------------------------------------------
2866
TEST(operation,mercator_variant_A_export_latitude_origin_non_zero)2867 TEST(operation, mercator_variant_A_export_latitude_origin_non_zero) {
2868 auto conv = Conversion::createMercatorVariantA(
2869 PropertyMap(), Angle(10), Angle(1), Scale(2), Length(3), Length(4));
2870
2871 EXPECT_THROW(conv->exportToPROJString(PROJStringFormatter::create().get()),
2872 FormattingException);
2873 }
2874
2875 // ---------------------------------------------------------------------------
2876
TEST(operation,wkt1_import_mercator_variant_A)2877 TEST(operation, wkt1_import_mercator_variant_A) {
2878 auto wkt = "PROJCS[\"test\",\n"
2879 " GEOGCS[\"WGS 84\",\n"
2880 " DATUM[\"WGS 1984\",\n"
2881 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
2882 " PRIMEM[\"Greenwich\",0],\n"
2883 " UNIT[\"degree\",0.0174532925199433]],\n"
2884 " PROJECTION[\"Mercator_1SP\"],\n"
2885 " PARAMETER[\"central_meridian\",1],\n"
2886 " PARAMETER[\"scale_factor\",2],\n"
2887 " PARAMETER[\"false_easting\",3],\n"
2888 " PARAMETER[\"false_northing\",4],\n"
2889 " UNIT[\"metre\",1]]";
2890 auto obj = WKTParser().createFromWKT(wkt);
2891 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
2892 ASSERT_TRUE(crs != nullptr);
2893
2894 auto conversion = crs->derivingConversion();
2895 auto convRef = Conversion::createMercatorVariantA(
2896 PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"), Angle(0),
2897 Angle(1), Scale(2), Length(3), Length(4));
2898
2899 EXPECT_EQ(conversion->exportToWKT(WKTFormatter::create().get()),
2900 convRef->exportToWKT(WKTFormatter::create().get()));
2901 }
2902
2903 // ---------------------------------------------------------------------------
2904
TEST(operation,wkt1_import_mercator_variant_A_that_is_variant_B)2905 TEST(operation, wkt1_import_mercator_variant_A_that_is_variant_B) {
2906 // Addresses https://trac.osgeo.org/gdal/ticket/3026
2907 auto wkt = "PROJCS[\"test\",\n"
2908 " GEOGCS[\"WGS 84\",\n"
2909 " DATUM[\"WGS 1984\",\n"
2910 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
2911 " PRIMEM[\"Greenwich\",0],\n"
2912 " UNIT[\"degree\",0.0174532925199433]],\n"
2913 " PROJECTION[\"Mercator_1SP\"],\n"
2914 " PARAMETER[\"latitude_of_origin\",-1],\n"
2915 " PARAMETER[\"central_meridian\",2],\n"
2916 " PARAMETER[\"scale_factor\",1],\n"
2917 " PARAMETER[\"false_easting\",3],\n"
2918 " PARAMETER[\"false_northing\",4],\n"
2919 " UNIT[\"metre\",1]]";
2920 auto obj = WKTParser().createFromWKT(wkt);
2921 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
2922 ASSERT_TRUE(crs != nullptr);
2923
2924 auto conversion = crs->derivingConversion();
2925 auto convRef = Conversion::createMercatorVariantB(
2926 PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"), Angle(-1),
2927 Angle(2), Length(3), Length(4));
2928
2929 EXPECT_TRUE(conversion->isEquivalentTo(convRef.get(),
2930 IComparable::Criterion::EQUIVALENT));
2931 }
2932
2933 // ---------------------------------------------------------------------------
2934
TEST(operation,mercator_variant_B_export)2935 TEST(operation, mercator_variant_B_export) {
2936 auto conv = Conversion::createMercatorVariantB(
2937 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
2938 EXPECT_TRUE(conv->validateParameters().empty());
2939
2940 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
2941 "+proj=merc +lat_ts=1 +lon_0=2 +x_0=3 +y_0=4");
2942
2943 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
2944 "CONVERSION[\"Mercator (variant B)\",\n"
2945 " METHOD[\"Mercator (variant B)\",\n"
2946 " ID[\"EPSG\",9805]],\n"
2947 " PARAMETER[\"Latitude of 1st standard parallel\",1,\n"
2948 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2949 " ID[\"EPSG\",8823]],\n"
2950 " PARAMETER[\"Longitude of natural origin\",2,\n"
2951 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
2952 " ID[\"EPSG\",8802]],\n"
2953 " PARAMETER[\"False easting\",3,\n"
2954 " LENGTHUNIT[\"metre\",1],\n"
2955 " ID[\"EPSG\",8806]],\n"
2956 " PARAMETER[\"False northing\",4,\n"
2957 " LENGTHUNIT[\"metre\",1],\n"
2958 " ID[\"EPSG\",8807]]]");
2959
2960 EXPECT_EQ(
2961 conv->exportToWKT(
2962 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
2963 "PROJECTION[\"Mercator_2SP\"],\n"
2964 "PARAMETER[\"standard_parallel_1\",1],\n"
2965 "PARAMETER[\"central_meridian\",2],\n"
2966 "PARAMETER[\"false_easting\",3],\n"
2967 "PARAMETER[\"false_northing\",4]");
2968 }
2969
2970 // ---------------------------------------------------------------------------
2971
TEST(operation,odd_mercator_1sp_with_non_null_latitude)2972 TEST(operation, odd_mercator_1sp_with_non_null_latitude) {
2973 auto obj = WKTParser().createFromWKT(
2974 "PROJCS[\"unnamed\",\n"
2975 " GEOGCS[\"WGS 84\",\n"
2976 " DATUM[\"WGS_1984\",\n"
2977 " SPHEROID[\"WGS 84\",6378137,298.257223563,\n"
2978 " AUTHORITY[\"EPSG\",\"7030\"]],\n"
2979 " AUTHORITY[\"EPSG\",\"6326\"]],\n"
2980 " PRIMEM[\"Greenwich\",0,\n"
2981 " AUTHORITY[\"EPSG\",\"8901\"]],\n"
2982 " UNIT[\"degree\",0.0174532925199433,\n"
2983 " AUTHORITY[\"EPSG\",\"9122\"]],\n"
2984 " AUTHORITY[\"EPSG\",\"4326\"]],\n"
2985 " PROJECTION[\"Mercator_1SP\"],\n"
2986 " PARAMETER[\"latitude_of_origin\",30],\n"
2987 " PARAMETER[\"central_meridian\",0],\n"
2988 " PARAMETER[\"scale_factor\",0.99],\n"
2989 " PARAMETER[\"false_easting\",0],\n"
2990 " PARAMETER[\"false_northing\",0],\n"
2991 " UNIT[\"metre\",1],\n"
2992 " AXIS[\"Easting\",EAST],\n"
2993 " AXIS[\"Northing\",NORTH]]");
2994
2995 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
2996 ASSERT_TRUE(crs != nullptr);
2997
2998 EXPECT_THROW(crs->exportToPROJString(PROJStringFormatter::create().get()),
2999 FormattingException);
3000 }
3001
3002 // ---------------------------------------------------------------------------
3003
TEST(operation,odd_mercator_2sp_with_latitude_of_origin)3004 TEST(operation, odd_mercator_2sp_with_latitude_of_origin) {
3005 auto obj = WKTParser().createFromWKT(
3006 "PROJCS[\"unnamed\",\n"
3007 " GEOGCS[\"WGS 84\",\n"
3008 " DATUM[\"WGS_1984\",\n"
3009 " SPHEROID[\"WGS 84\",6378137,298.257223563,\n"
3010 " AUTHORITY[\"EPSG\",\"7030\"]],\n"
3011 " AUTHORITY[\"EPSG\",\"6326\"]],\n"
3012 " PRIMEM[\"Greenwich\",0,\n"
3013 " AUTHORITY[\"EPSG\",\"8901\"]],\n"
3014 " UNIT[\"degree\",0.0174532925199433,\n"
3015 " AUTHORITY[\"EPSG\",\"9122\"]],\n"
3016 " AUTHORITY[\"EPSG\",\"4326\"]],\n"
3017 " PROJECTION[\"Mercator_2SP\"],\n"
3018 " PARAMETER[\"standard_parallel_1\",30],\n"
3019 " PARAMETER[\"latitude_of_origin\",40],\n"
3020 " PARAMETER[\"central_meridian\",0],\n"
3021 " PARAMETER[\"false_easting\",0],\n"
3022 " PARAMETER[\"false_northing\",0],\n"
3023 " UNIT[\"metre\",1],\n"
3024 " AXIS[\"Easting\",EAST],\n"
3025 " AXIS[\"Northing\",NORTH]]");
3026
3027 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3028 ASSERT_TRUE(crs != nullptr);
3029
3030 EXPECT_THROW(crs->exportToPROJString(PROJStringFormatter::create().get()),
3031 FormattingException);
3032 }
3033
3034 // ---------------------------------------------------------------------------
3035
TEST(operation,webmerc_export)3036 TEST(operation, webmerc_export) {
3037 auto conv = Conversion::createPopularVisualisationPseudoMercator(
3038 PropertyMap(), Angle(0), Angle(2), Length(3), Length(4));
3039 EXPECT_TRUE(conv->validateParameters().empty());
3040
3041 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3042 "+proj=webmerc +lat_0=0 +lon_0=2 +x_0=3 +y_0=4");
3043
3044 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3045 "CONVERSION[\"Popular Visualisation Pseudo Mercator\",\n"
3046 " METHOD[\"Popular Visualisation Pseudo Mercator\",\n"
3047 " ID[\"EPSG\",1024]],\n"
3048 " PARAMETER[\"Latitude of natural origin\",0,\n"
3049 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3050 " ID[\"EPSG\",8801]],\n"
3051 " PARAMETER[\"Longitude of natural origin\",2,\n"
3052 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3053 " ID[\"EPSG\",8802]],\n"
3054 " PARAMETER[\"False easting\",3,\n"
3055 " LENGTHUNIT[\"metre\",1],\n"
3056 " ID[\"EPSG\",8806]],\n"
3057 " PARAMETER[\"False northing\",4,\n"
3058 " LENGTHUNIT[\"metre\",1],\n"
3059 " ID[\"EPSG\",8807]]]");
3060
3061 auto projCRS = ProjectedCRS::create(
3062 PropertyMap().set(IdentifiedObject::NAME_KEY, "Pseudo-Mercator"),
3063 GeographicCRS::EPSG_4326, conv,
3064 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
3065
3066 EXPECT_EQ(
3067 projCRS->exportToWKT(
3068 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3069 "PROJCS[\"Pseudo-Mercator\",\n"
3070 " GEOGCS[\"WGS 84\",\n"
3071 " DATUM[\"WGS_1984\",\n"
3072 " SPHEROID[\"WGS 84\",6378137,298.257223563,\n"
3073 " AUTHORITY[\"EPSG\",\"7030\"]],\n"
3074 " AUTHORITY[\"EPSG\",\"6326\"]],\n"
3075 " PRIMEM[\"Greenwich\",0,\n"
3076 " AUTHORITY[\"EPSG\",\"8901\"]],\n"
3077 " UNIT[\"degree\",0.0174532925199433,\n"
3078 " AUTHORITY[\"EPSG\",\"9122\"]],\n"
3079 " AUTHORITY[\"EPSG\",\"4326\"]],\n"
3080 " PROJECTION[\"Mercator_1SP\"],\n"
3081 " PARAMETER[\"central_meridian\",2],\n"
3082 " PARAMETER[\"scale_factor\",1],\n"
3083 " PARAMETER[\"false_easting\",3],\n"
3084 " PARAMETER[\"false_northing\",4],\n"
3085 " UNIT[\"metre\",1,\n"
3086 " AUTHORITY[\"EPSG\",\"9001\"]],\n"
3087 " AXIS[\"Easting\",EAST],\n"
3088 " AXIS[\"Northing\",NORTH],\n"
3089 " EXTENSION[\"PROJ4\",\"+proj=merc "
3090 "+a=6378137 +b=6378137 +lat_ts=0 +lon_0=2 "
3091 "+x_0=3 +y_0=4 +k=1 +units=m "
3092 "+nadgrids=@null +wktext +no_defs\"]]");
3093
3094 auto op = CoordinateOperationFactory::create()->createOperation(
3095 GeographicCRS::EPSG_4326, projCRS);
3096 ASSERT_TRUE(op != nullptr);
3097 EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
3098 "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
3099 "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=webmerc "
3100 "+lat_0=0 +lon_0=2 +x_0=3 +y_0=4 +ellps=WGS84");
3101
3102 EXPECT_EQ(
3103 projCRS->exportToPROJString(PROJStringFormatter::create().get()),
3104 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=2 +x_0=3 "
3105 "+y_0=4 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs");
3106 }
3107
3108 // ---------------------------------------------------------------------------
3109
TEST(operation,webmerc_import_from_GDAL_wkt1)3110 TEST(operation, webmerc_import_from_GDAL_wkt1) {
3111
3112 auto projCRS = ProjectedCRS::create(
3113 PropertyMap().set(IdentifiedObject::NAME_KEY, "Pseudo-Mercator"),
3114 GeographicCRS::EPSG_4326,
3115 Conversion::createPopularVisualisationPseudoMercator(
3116 PropertyMap(), Angle(0), Angle(0), Length(0), Length(0)),
3117 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
3118
3119 auto wkt1 = projCRS->exportToWKT(
3120 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get());
3121 auto obj = WKTParser().createFromWKT(wkt1);
3122 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3123 ASSERT_TRUE(crs != nullptr);
3124
3125 auto convGot = crs->derivingConversion();
3126
3127 EXPECT_EQ(convGot->exportToWKT(WKTFormatter::create().get()),
3128 "CONVERSION[\"unnamed\",\n"
3129 " METHOD[\"Popular Visualisation Pseudo Mercator\",\n"
3130 " ID[\"EPSG\",1024]],\n"
3131 " PARAMETER[\"Latitude of natural origin\",0,\n"
3132 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3133 " ID[\"EPSG\",8801]],\n"
3134 " PARAMETER[\"Longitude of natural origin\",0,\n"
3135 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3136 " ID[\"EPSG\",8802]],\n"
3137 " PARAMETER[\"False easting\",0,\n"
3138 " LENGTHUNIT[\"metre\",1],\n"
3139 " ID[\"EPSG\",8806]],\n"
3140 " PARAMETER[\"False northing\",0,\n"
3141 " LENGTHUNIT[\"metre\",1],\n"
3142 " ID[\"EPSG\",8807]]]");
3143 }
3144
3145 // ---------------------------------------------------------------------------
3146
TEST(operation,webmerc_import_from_GDAL_wkt1_with_EPSG_code)3147 TEST(operation, webmerc_import_from_GDAL_wkt1_with_EPSG_code) {
3148
3149 auto projCRS = ProjectedCRS::create(
3150 PropertyMap()
3151 .set(IdentifiedObject::NAME_KEY, "Pseudo-Mercator")
3152 .set(Identifier::CODESPACE_KEY, "EPSG")
3153 .set(Identifier::CODE_KEY, "3857"),
3154 GeographicCRS::EPSG_4326,
3155 Conversion::createPopularVisualisationPseudoMercator(
3156 PropertyMap(), Angle(0), Angle(0), Length(0), Length(0)),
3157 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
3158
3159 auto wkt1 = projCRS->exportToWKT(
3160 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get());
3161 EXPECT_TRUE(wkt1.find("3857") != std::string::npos) << wkt1;
3162 auto obj = WKTParser().createFromWKT(wkt1);
3163 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3164 ASSERT_TRUE(crs != nullptr);
3165 EXPECT_EQ(crs->identifiers().size(), 1U);
3166 }
3167
3168 // ---------------------------------------------------------------------------
3169
TEST(operation,webmerc_import_from_GDAL_wkt1_EPSG_3785_deprecated)3170 TEST(operation, webmerc_import_from_GDAL_wkt1_EPSG_3785_deprecated) {
3171
3172 auto wkt1 =
3173 "PROJCS[\"Popular Visualisation CRS / Mercator (deprecated)\","
3174 " GEOGCS[\"Popular Visualisation CRS\","
3175 " DATUM[\"Popular_Visualisation_Datum\","
3176 " SPHEROID[\"Popular Visualisation Sphere\",6378137,0,"
3177 " AUTHORITY[\"EPSG\",\"7059\"]],"
3178 " TOWGS84[0,0,0,0,0,0,0],"
3179 " AUTHORITY[\"EPSG\",\"6055\"]],"
3180 " PRIMEM[\"Greenwich\",0,"
3181 " AUTHORITY[\"EPSG\",\"8901\"]],"
3182 " UNIT[\"degree\",0.0174532925199433,"
3183 " AUTHORITY[\"EPSG\",\"9122\"]],"
3184 " AUTHORITY[\"EPSG\",\"4055\"]],"
3185 " PROJECTION[\"Mercator_1SP\"],"
3186 " PARAMETER[\"central_meridian\",0],"
3187 " PARAMETER[\"scale_factor\",1],"
3188 " PARAMETER[\"false_easting\",0],"
3189 " PARAMETER[\"false_northing\",0],"
3190 " UNIT[\"metre\",1,"
3191 " AUTHORITY[\"EPSG\",\"9001\"]],"
3192 " AXIS[\"X\",EAST],"
3193 " AXIS[\"Y\",NORTH],"
3194 " EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 "
3195 "+lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m "
3196 "+nadgrids=@null +wktext +no_defs\"]]";
3197
3198 auto obj = WKTParser().createFromWKT(wkt1);
3199 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3200 ASSERT_TRUE(crs != nullptr);
3201
3202 EXPECT_EQ(
3203 crs->exportToPROJString(PROJStringFormatter::create().get()),
3204 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "
3205 "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs");
3206
3207 auto convGot = crs->derivingConversion();
3208
3209 EXPECT_EQ(convGot->exportToWKT(WKTFormatter::create().get()),
3210 "CONVERSION[\"unnamed\",\n"
3211 " METHOD[\"Popular Visualisation Pseudo Mercator\",\n"
3212 " ID[\"EPSG\",1024]],\n"
3213 " PARAMETER[\"Latitude of natural origin\",0,\n"
3214 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3215 " ID[\"EPSG\",8801]],\n"
3216 " PARAMETER[\"Longitude of natural origin\",0,\n"
3217 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3218 " ID[\"EPSG\",8802]],\n"
3219 " PARAMETER[\"False easting\",0,\n"
3220 " LENGTHUNIT[\"metre\",1],\n"
3221 " ID[\"EPSG\",8806]],\n"
3222 " PARAMETER[\"False northing\",0,\n"
3223 " LENGTHUNIT[\"metre\",1],\n"
3224 " ID[\"EPSG\",8807]]]");
3225 }
3226
3227 // ---------------------------------------------------------------------------
3228
TEST(operation,webmerc_import_from_WKT2_EPSG_3785_deprecated)3229 TEST(operation, webmerc_import_from_WKT2_EPSG_3785_deprecated) {
3230 auto wkt2 =
3231 "PROJCRS[\"Popular Visualisation CRS / Mercator\",\n"
3232 " BASEGEODCRS[\"Popular Visualisation CRS\",\n"
3233 " DATUM[\"Popular Visualisation Datum\",\n"
3234 " ELLIPSOID[\"Popular Visualisation Sphere\",6378137,0,\n"
3235 " LENGTHUNIT[\"metre\",1]]],\n"
3236 " PRIMEM[\"Greenwich\",0,\n"
3237 " ANGLEUNIT[\"degree\",0.0174532925199433]]],\n"
3238 " CONVERSION[\"Popular Visualisation Mercator\",\n"
3239 " METHOD[\"Mercator (1SP) (Spherical)\",\n"
3240 " ID[\"EPSG\",9841]],\n"
3241 " PARAMETER[\"Latitude of natural origin\",0,\n"
3242 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3243 " ID[\"EPSG\",8801]],\n"
3244 " PARAMETER[\"Longitude of natural origin\",0,\n"
3245 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3246 " ID[\"EPSG\",8802]],\n"
3247 " PARAMETER[\"Scale factor at natural origin\",1,\n"
3248 " SCALEUNIT[\"unity\",1],\n"
3249 " ID[\"EPSG\",8805]],\n"
3250 " PARAMETER[\"False easting\",0,\n"
3251 " LENGTHUNIT[\"metre\",1],\n"
3252 " ID[\"EPSG\",8806]],\n"
3253 " PARAMETER[\"False northing\",0,\n"
3254 " LENGTHUNIT[\"metre\",1],\n"
3255 " ID[\"EPSG\",8807]]],\n"
3256 " CS[Cartesian,2],\n"
3257 " AXIS[\"easting (X)\",east,\n"
3258 " ORDER[1],\n"
3259 " LENGTHUNIT[\"metre\",1]],\n"
3260 " AXIS[\"northing (Y)\",north,\n"
3261 " ORDER[2],\n"
3262 " LENGTHUNIT[\"metre\",1]]]";
3263
3264 auto obj = WKTParser().createFromWKT(wkt2);
3265 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3266 ASSERT_TRUE(crs != nullptr);
3267
3268 EXPECT_EQ(
3269 crs->exportToPROJString(PROJStringFormatter::create().get()),
3270 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "
3271 "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs");
3272
3273 EXPECT_EQ(
3274 crs->exportToWKT(
3275 WKTFormatter::create(WKTFormatter::Convention::WKT2_2015).get()),
3276 wkt2);
3277
3278 EXPECT_EQ(
3279 crs->exportToWKT(
3280 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL,
3281 DatabaseContext::create())
3282 .get()),
3283 "PROJCS[\"Popular Visualisation CRS / Mercator\",\n"
3284 " GEOGCS[\"Popular Visualisation CRS\",\n"
3285 " DATUM[\"Popular_Visualisation_Datum\",\n"
3286 " SPHEROID[\"Popular Visualisation Sphere\",6378137,0],\n"
3287 " TOWGS84[0,0,0,0,0,0,0]],\n"
3288 " PRIMEM[\"Greenwich\",0],\n"
3289 " UNIT[\"degree\",0.0174532925199433]],\n"
3290 " PROJECTION[\"Mercator_1SP\"],\n"
3291 " PARAMETER[\"central_meridian\",0],\n"
3292 " PARAMETER[\"scale_factor\",1],\n"
3293 " PARAMETER[\"false_easting\",0],\n"
3294 " PARAMETER[\"false_northing\",0],\n"
3295 " UNIT[\"metre\",1],\n"
3296 " AXIS[\"Easting\",EAST],\n"
3297 " AXIS[\"Northing\",NORTH],\n"
3298 " EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0 "
3299 "+lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext "
3300 "+no_defs\"]]");
3301 }
3302
3303 // ---------------------------------------------------------------------------
3304
TEST(operation,webmerc_import_from_broken_esri_WGS_84_Pseudo_Mercator)3305 TEST(operation, webmerc_import_from_broken_esri_WGS_84_Pseudo_Mercator) {
3306
3307 // Likely the result of a broken export of GDAL morphToESRI()
3308 auto wkt1 = "PROJCS[\"WGS_84_Pseudo_Mercator\",GEOGCS[\"GCS_WGS_1984\","
3309 "DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\","
3310 "6378137,298.257223563]],PRIMEM[\"Greenwich\",0],"
3311 "UNIT[\"Degree\",0.017453292519943295]],"
3312 "PROJECTION[\"Mercator\"],PARAMETER[\"central_meridian\",0],"
3313 "PARAMETER[\"false_easting\",0],"
3314 "PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1],"
3315 "PARAMETER[\"standard_parallel_1\",0.0]]";
3316
3317 auto obj = WKTParser().setStrict(false).createFromWKT(wkt1);
3318 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3319 ASSERT_TRUE(crs != nullptr);
3320
3321 auto convGot = crs->derivingConversion();
3322
3323 EXPECT_EQ(convGot->exportToWKT(WKTFormatter::create().get()),
3324 "CONVERSION[\"unnamed\",\n"
3325 " METHOD[\"Popular Visualisation Pseudo Mercator\",\n"
3326 " ID[\"EPSG\",1024]],\n"
3327 " PARAMETER[\"Latitude of natural origin\",0,\n"
3328 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3329 " ID[\"EPSG\",8801]],\n"
3330 " PARAMETER[\"Longitude of natural origin\",0,\n"
3331 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3332 " ID[\"EPSG\",8802]],\n"
3333 " PARAMETER[\"False easting\",0,\n"
3334 " LENGTHUNIT[\"metre\",1],\n"
3335 " ID[\"EPSG\",8806]],\n"
3336 " PARAMETER[\"False northing\",0,\n"
3337 " LENGTHUNIT[\"metre\",1],\n"
3338 " ID[\"EPSG\",8807]]]");
3339 }
3340
3341 // ---------------------------------------------------------------------------
3342
TEST(operation,mollweide_export)3343 TEST(operation, mollweide_export) {
3344
3345 auto conv = Conversion::createMollweide(PropertyMap(), Angle(1), Length(2),
3346 Length(3));
3347 EXPECT_TRUE(conv->validateParameters().empty());
3348
3349 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3350 "+proj=moll +lon_0=1 +x_0=2 +y_0=3");
3351
3352 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3353 "CONVERSION[\"Mollweide\",\n"
3354 " METHOD[\"Mollweide\"],\n"
3355 " PARAMETER[\"Longitude of natural origin\",1,\n"
3356 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3357 " ID[\"EPSG\",8802]],\n"
3358 " PARAMETER[\"False easting\",2,\n"
3359 " LENGTHUNIT[\"metre\",1],\n"
3360 " ID[\"EPSG\",8806]],\n"
3361 " PARAMETER[\"False northing\",3,\n"
3362 " LENGTHUNIT[\"metre\",1],\n"
3363 " ID[\"EPSG\",8807]]]");
3364
3365 EXPECT_EQ(
3366 conv->exportToWKT(
3367 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3368 "PROJECTION[\"Mollweide\"],\n"
3369 "PARAMETER[\"central_meridian\",1],\n"
3370 "PARAMETER[\"false_easting\",2],\n"
3371 "PARAMETER[\"false_northing\",3]");
3372 }
3373 // ---------------------------------------------------------------------------
3374
TEST(operation,nzmg_export)3375 TEST(operation, nzmg_export) {
3376 auto conv = Conversion::createNewZealandMappingGrid(
3377 PropertyMap(), Angle(1), Angle(2), Length(4), Length(5));
3378 EXPECT_TRUE(conv->validateParameters().empty());
3379
3380 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3381 "+proj=nzmg +lat_0=1 +lon_0=2 +x_0=4 +y_0=5");
3382
3383 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3384 "CONVERSION[\"New Zealand Map Grid\",\n"
3385 " METHOD[\"New Zealand Map Grid\",\n"
3386 " ID[\"EPSG\",9811]],\n"
3387 " PARAMETER[\"Latitude of natural origin\",1,\n"
3388 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3389 " ID[\"EPSG\",8801]],\n"
3390 " PARAMETER[\"Longitude of natural origin\",2,\n"
3391 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3392 " ID[\"EPSG\",8802]],\n"
3393 " PARAMETER[\"False easting\",4,\n"
3394 " LENGTHUNIT[\"metre\",1],\n"
3395 " ID[\"EPSG\",8806]],\n"
3396 " PARAMETER[\"False northing\",5,\n"
3397 " LENGTHUNIT[\"metre\",1],\n"
3398 " ID[\"EPSG\",8807]]]");
3399
3400 EXPECT_EQ(
3401 conv->exportToWKT(
3402 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3403 "PROJECTION[\"New_Zealand_Map_Grid\"],\n"
3404 "PARAMETER[\"latitude_of_origin\",1],\n"
3405 "PARAMETER[\"central_meridian\",2],\n"
3406 "PARAMETER[\"false_easting\",4],\n"
3407 "PARAMETER[\"false_northing\",5]");
3408 }
3409
3410 // ---------------------------------------------------------------------------
3411
TEST(operation,oblique_stereographic_export)3412 TEST(operation, oblique_stereographic_export) {
3413 auto conv = Conversion::createObliqueStereographic(
3414 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
3415 EXPECT_TRUE(conv->validateParameters().empty());
3416
3417 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3418 "+proj=sterea +lat_0=1 +lon_0=2 +k=3 +x_0=4 +y_0=5");
3419
3420 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3421 "CONVERSION[\"Oblique Stereographic\",\n"
3422 " METHOD[\"Oblique Stereographic\",\n"
3423 " ID[\"EPSG\",9809]],\n"
3424 " PARAMETER[\"Latitude of natural origin\",1,\n"
3425 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3426 " ID[\"EPSG\",8801]],\n"
3427 " PARAMETER[\"Longitude of natural origin\",2,\n"
3428 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3429 " ID[\"EPSG\",8802]],\n"
3430 " PARAMETER[\"Scale factor at natural origin\",3,\n"
3431 " SCALEUNIT[\"unity\",1],\n"
3432 " ID[\"EPSG\",8805]],\n"
3433 " PARAMETER[\"False easting\",4,\n"
3434 " LENGTHUNIT[\"metre\",1],\n"
3435 " ID[\"EPSG\",8806]],\n"
3436 " PARAMETER[\"False northing\",5,\n"
3437 " LENGTHUNIT[\"metre\",1],\n"
3438 " ID[\"EPSG\",8807]]]");
3439
3440 EXPECT_EQ(
3441 conv->exportToWKT(
3442 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3443 "PROJECTION[\"Oblique_Stereographic\"],\n"
3444 "PARAMETER[\"latitude_of_origin\",1],\n"
3445 "PARAMETER[\"central_meridian\",2],\n"
3446 "PARAMETER[\"scale_factor\",3],\n"
3447 "PARAMETER[\"false_easting\",4],\n"
3448 "PARAMETER[\"false_northing\",5]");
3449 }
3450
3451 // ---------------------------------------------------------------------------
3452
TEST(operation,orthographic_export)3453 TEST(operation, orthographic_export) {
3454 auto conv = Conversion::createOrthographic(PropertyMap(), Angle(1),
3455 Angle(2), Length(4), Length(5));
3456 EXPECT_TRUE(conv->validateParameters().empty());
3457
3458 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3459 "+proj=ortho +lat_0=1 +lon_0=2 +x_0=4 +y_0=5");
3460
3461 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3462 "CONVERSION[\"Orthographic\",\n"
3463 " METHOD[\"Orthographic\",\n"
3464 " ID[\"EPSG\",9840]],\n"
3465 " PARAMETER[\"Latitude of natural origin\",1,\n"
3466 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3467 " ID[\"EPSG\",8801]],\n"
3468 " PARAMETER[\"Longitude of natural origin\",2,\n"
3469 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3470 " ID[\"EPSG\",8802]],\n"
3471 " PARAMETER[\"False easting\",4,\n"
3472 " LENGTHUNIT[\"metre\",1],\n"
3473 " ID[\"EPSG\",8806]],\n"
3474 " PARAMETER[\"False northing\",5,\n"
3475 " LENGTHUNIT[\"metre\",1],\n"
3476 " ID[\"EPSG\",8807]]]");
3477
3478 EXPECT_EQ(
3479 conv->exportToWKT(
3480 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3481 "PROJECTION[\"Orthographic\"],\n"
3482 "PARAMETER[\"latitude_of_origin\",1],\n"
3483 "PARAMETER[\"central_meridian\",2],\n"
3484 "PARAMETER[\"false_easting\",4],\n"
3485 "PARAMETER[\"false_northing\",5]");
3486 }
3487
3488 // ---------------------------------------------------------------------------
3489
TEST(operation,american_polyconic_export)3490 TEST(operation, american_polyconic_export) {
3491 auto conv = Conversion::createAmericanPolyconic(
3492 PropertyMap(), Angle(1), Angle(2), Length(4), Length(5));
3493 EXPECT_TRUE(conv->validateParameters().empty());
3494
3495 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3496 "+proj=poly +lat_0=1 +lon_0=2 +x_0=4 +y_0=5");
3497
3498 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3499 "CONVERSION[\"American Polyconic\",\n"
3500 " METHOD[\"American Polyconic\",\n"
3501 " ID[\"EPSG\",9818]],\n"
3502 " PARAMETER[\"Latitude of natural origin\",1,\n"
3503 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3504 " ID[\"EPSG\",8801]],\n"
3505 " PARAMETER[\"Longitude of natural origin\",2,\n"
3506 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3507 " ID[\"EPSG\",8802]],\n"
3508 " PARAMETER[\"False easting\",4,\n"
3509 " LENGTHUNIT[\"metre\",1],\n"
3510 " ID[\"EPSG\",8806]],\n"
3511 " PARAMETER[\"False northing\",5,\n"
3512 " LENGTHUNIT[\"metre\",1],\n"
3513 " ID[\"EPSG\",8807]]]");
3514
3515 EXPECT_EQ(
3516 conv->exportToWKT(
3517 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3518 "PROJECTION[\"Polyconic\"],\n"
3519 "PARAMETER[\"latitude_of_origin\",1],\n"
3520 "PARAMETER[\"central_meridian\",2],\n"
3521 "PARAMETER[\"false_easting\",4],\n"
3522 "PARAMETER[\"false_northing\",5]");
3523 }
3524
3525 // ---------------------------------------------------------------------------
3526
TEST(operation,polar_stereographic_variant_A_export)3527 TEST(operation, polar_stereographic_variant_A_export) {
3528 auto conv = Conversion::createPolarStereographicVariantA(
3529 PropertyMap(), Angle(90), Angle(2), Scale(3), Length(4), Length(5));
3530 EXPECT_TRUE(conv->validateParameters().empty());
3531
3532 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3533 "+proj=stere +lat_0=90 +lon_0=2 +k=3 +x_0=4 +y_0=5");
3534
3535 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3536 "CONVERSION[\"Polar Stereographic (variant A)\",\n"
3537 " METHOD[\"Polar Stereographic (variant A)\",\n"
3538 " ID[\"EPSG\",9810]],\n"
3539 " PARAMETER[\"Latitude of natural origin\",90,\n"
3540 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3541 " ID[\"EPSG\",8801]],\n"
3542 " PARAMETER[\"Longitude of natural origin\",2,\n"
3543 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3544 " ID[\"EPSG\",8802]],\n"
3545 " PARAMETER[\"Scale factor at natural origin\",3,\n"
3546 " SCALEUNIT[\"unity\",1],\n"
3547 " ID[\"EPSG\",8805]],\n"
3548 " PARAMETER[\"False easting\",4,\n"
3549 " LENGTHUNIT[\"metre\",1],\n"
3550 " ID[\"EPSG\",8806]],\n"
3551 " PARAMETER[\"False northing\",5,\n"
3552 " LENGTHUNIT[\"metre\",1],\n"
3553 " ID[\"EPSG\",8807]]]");
3554
3555 EXPECT_EQ(
3556 conv->exportToWKT(
3557 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3558 "PROJECTION[\"Polar_Stereographic\"],\n"
3559 "PARAMETER[\"latitude_of_origin\",90],\n"
3560 "PARAMETER[\"central_meridian\",2],\n"
3561 "PARAMETER[\"scale_factor\",3],\n"
3562 "PARAMETER[\"false_easting\",4],\n"
3563 "PARAMETER[\"false_northing\",5]");
3564 }
3565
3566 // ---------------------------------------------------------------------------
3567
TEST(operation,polar_stereographic_variant_B_export_positive_lat)3568 TEST(operation, polar_stereographic_variant_B_export_positive_lat) {
3569 auto conv = Conversion::createPolarStereographicVariantB(
3570 PropertyMap(), Angle(70), Angle(2), Length(4), Length(5));
3571 EXPECT_TRUE(conv->validateParameters().empty());
3572
3573 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3574 "+proj=stere +lat_0=90 +lat_ts=70 +lon_0=2 +x_0=4 +y_0=5");
3575
3576 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3577 "CONVERSION[\"Polar Stereographic (variant B)\",\n"
3578 " METHOD[\"Polar Stereographic (variant B)\",\n"
3579 " ID[\"EPSG\",9829]],\n"
3580 " PARAMETER[\"Latitude of standard parallel\",70,\n"
3581 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3582 " ID[\"EPSG\",8832]],\n"
3583 " PARAMETER[\"Longitude of origin\",2,\n"
3584 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3585 " ID[\"EPSG\",8833]],\n"
3586 " PARAMETER[\"False easting\",4,\n"
3587 " LENGTHUNIT[\"metre\",1],\n"
3588 " ID[\"EPSG\",8806]],\n"
3589 " PARAMETER[\"False northing\",5,\n"
3590 " LENGTHUNIT[\"metre\",1],\n"
3591 " ID[\"EPSG\",8807]]]");
3592
3593 EXPECT_EQ(
3594 conv->exportToWKT(
3595 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3596 "PROJECTION[\"Polar_Stereographic\"],\n"
3597 "PARAMETER[\"latitude_of_origin\",70],\n"
3598 "PARAMETER[\"central_meridian\",2],\n"
3599 "PARAMETER[\"false_easting\",4],\n"
3600 "PARAMETER[\"false_northing\",5]");
3601 }
3602
3603 // ---------------------------------------------------------------------------
3604
TEST(operation,polar_stereographic_variant_B_export_negative_lat)3605 TEST(operation, polar_stereographic_variant_B_export_negative_lat) {
3606 auto conv = Conversion::createPolarStereographicVariantB(
3607 PropertyMap(), Angle(-70), Angle(2), Length(4), Length(5));
3608
3609 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3610 "+proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=2 +x_0=4 +y_0=5");
3611 }
3612
3613 // ---------------------------------------------------------------------------
3614
TEST(operation,wkt1_import_polar_stereographic_variantA)3615 TEST(operation, wkt1_import_polar_stereographic_variantA) {
3616 auto wkt = "PROJCS[\"test\",\n"
3617 " GEOGCS[\"WGS 84\",\n"
3618 " DATUM[\"WGS 1984\",\n"
3619 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
3620 " PRIMEM[\"Greenwich\",0],\n"
3621 " UNIT[\"degree\",0.0174532925199433]],\n"
3622 " PROJECTION[\"Polar_Stereographic\"],\n"
3623 " PARAMETER[\"latitude_of_origin\",-90],\n"
3624 " PARAMETER[\"central_meridian\",2],\n"
3625 " PARAMETER[\"scale_factor\",3],\n"
3626 " PARAMETER[\"false_easting\",4],\n"
3627 " PARAMETER[\"false_northing\",5],\n"
3628 " UNIT[\"metre\",1]]";
3629 auto obj = WKTParser().createFromWKT(wkt);
3630 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3631 ASSERT_TRUE(crs != nullptr);
3632
3633 auto conversion = crs->derivingConversion();
3634 auto convRef = Conversion::createPolarStereographicVariantA(
3635 PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"), Angle(-90),
3636 Angle(2), Scale(3), Length(4), Length(5));
3637
3638 EXPECT_EQ(conversion->exportToWKT(WKTFormatter::create().get()),
3639 convRef->exportToWKT(WKTFormatter::create().get()));
3640 }
3641
3642 // ---------------------------------------------------------------------------
3643
TEST(operation,wkt1_import_polar_stereographic_variantB)3644 TEST(operation, wkt1_import_polar_stereographic_variantB) {
3645 auto wkt = "PROJCS[\"test\",\n"
3646 " GEOGCS[\"WGS 84\",\n"
3647 " DATUM[\"WGS 1984\",\n"
3648 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
3649 " PRIMEM[\"Greenwich\",0],\n"
3650 " UNIT[\"degree\",0.0174532925199433]],\n"
3651 " PROJECTION[\"Polar_Stereographic\"],\n"
3652 " PARAMETER[\"latitude_of_origin\",-70],\n"
3653 " PARAMETER[\"central_meridian\",2],\n"
3654 " PARAMETER[\"scale_factor\",1],\n"
3655 " PARAMETER[\"false_easting\",4],\n"
3656 " PARAMETER[\"false_northing\",5],\n"
3657 " UNIT[\"metre\",1]]";
3658 auto obj = WKTParser().createFromWKT(wkt);
3659 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3660 ASSERT_TRUE(crs != nullptr);
3661
3662 auto conversion = crs->derivingConversion();
3663 auto convRef = Conversion::createPolarStereographicVariantB(
3664 PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"), Angle(-70),
3665 Angle(2), Length(4), Length(5));
3666
3667 EXPECT_EQ(conversion->exportToWKT(WKTFormatter::create().get()),
3668 convRef->exportToWKT(WKTFormatter::create().get()));
3669 }
3670
3671 // ---------------------------------------------------------------------------
3672
TEST(operation,wkt1_import_polar_stereographic_ambiguous)3673 TEST(operation, wkt1_import_polar_stereographic_ambiguous) {
3674 auto wkt = "PROJCS[\"test\",\n"
3675 " GEOGCS[\"WGS 84\",\n"
3676 " DATUM[\"WGS 1984\",\n"
3677 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
3678 " PRIMEM[\"Greenwich\",0],\n"
3679 " UNIT[\"degree\",0.0174532925199433]],\n"
3680 " PROJECTION[\"Polar_Stereographic\"],\n"
3681 " PARAMETER[\"latitude_of_origin\",-70],\n"
3682 " PARAMETER[\"central_meridian\",2],\n"
3683 " PARAMETER[\"scale_factor\",3],\n"
3684 " PARAMETER[\"false_easting\",4],\n"
3685 " PARAMETER[\"false_northing\",5],\n"
3686 " UNIT[\"metre\",1]]";
3687 auto obj = WKTParser().createFromWKT(wkt);
3688 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3689 ASSERT_TRUE(crs != nullptr);
3690
3691 auto conversion = crs->derivingConversion();
3692 EXPECT_EQ(conversion->method()->nameStr(), "Polar_Stereographic");
3693 }
3694
3695 // ---------------------------------------------------------------------------
3696
TEST(operation,wkt1_import_equivalent_parameters)3697 TEST(operation, wkt1_import_equivalent_parameters) {
3698 auto wkt = "PROJCS[\"test\",\n"
3699 " GEOGCS[\"WGS 84\",\n"
3700 " DATUM[\"WGS 1984\",\n"
3701 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
3702 " PRIMEM[\"Greenwich\",0],\n"
3703 " UNIT[\"degree\",0.0174532925199433]],\n"
3704 " PROJECTION[\"Hotine Oblique Mercator Two Point Natural "
3705 "Origin\"],\n"
3706 " PARAMETER[\"latitude_of_origin\",1],\n"
3707 " PARAMETER[\"Latitude_Of_1st_Point\",2],\n"
3708 " PARAMETER[\"Longitude_Of_1st_Point\",3],\n"
3709 " PARAMETER[\"Latitude_Of_2nd_Point\",4],\n"
3710 " PARAMETER[\"Longitude_Of 2nd_Point\",5],\n"
3711 " PARAMETER[\"scale_factor\",6],\n"
3712 " PARAMETER[\"false_easting\",7],\n"
3713 " PARAMETER[\"false_northing\",8],\n"
3714 " UNIT[\"metre\",1]]";
3715 auto obj = WKTParser().createFromWKT(wkt);
3716 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
3717 ASSERT_TRUE(crs != nullptr);
3718
3719 auto conversion = crs->derivingConversion();
3720 auto convRef = Conversion::createHotineObliqueMercatorTwoPointNaturalOrigin(
3721 PropertyMap(), Angle(1), Angle(2), Angle(3), Angle(4), Angle(5),
3722 Scale(6), Length(7), Length(8));
3723
3724 EXPECT_EQ(
3725 conversion->exportToWKT(
3726 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3727 convRef->exportToWKT(
3728 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()));
3729 }
3730
3731 // ---------------------------------------------------------------------------
3732
TEST(operation,robinson_export)3733 TEST(operation, robinson_export) {
3734
3735 auto conv = Conversion::createRobinson(PropertyMap(), Angle(1), Length(2),
3736 Length(3));
3737 EXPECT_TRUE(conv->validateParameters().empty());
3738
3739 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3740 "+proj=robin +lon_0=1 +x_0=2 +y_0=3");
3741
3742 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3743 "CONVERSION[\"Robinson\",\n"
3744 " METHOD[\"Robinson\"],\n"
3745 " PARAMETER[\"Longitude of natural origin\",1,\n"
3746 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3747 " ID[\"EPSG\",8802]],\n"
3748 " PARAMETER[\"False easting\",2,\n"
3749 " LENGTHUNIT[\"metre\",1],\n"
3750 " ID[\"EPSG\",8806]],\n"
3751 " PARAMETER[\"False northing\",3,\n"
3752 " LENGTHUNIT[\"metre\",1],\n"
3753 " ID[\"EPSG\",8807]]]");
3754
3755 EXPECT_EQ(
3756 conv->exportToWKT(
3757 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3758 "PROJECTION[\"Robinson\"],\n"
3759 "PARAMETER[\"longitude_of_center\",1],\n"
3760 "PARAMETER[\"false_easting\",2],\n"
3761 "PARAMETER[\"false_northing\",3]");
3762 }
3763
3764 // ---------------------------------------------------------------------------
3765
TEST(operation,sinusoidal_export)3766 TEST(operation, sinusoidal_export) {
3767
3768 auto conv = Conversion::createSinusoidal(PropertyMap(), Angle(1), Length(2),
3769 Length(3));
3770 EXPECT_TRUE(conv->validateParameters().empty());
3771
3772 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3773 "+proj=sinu +lon_0=1 +x_0=2 +y_0=3");
3774
3775 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3776 "CONVERSION[\"Sinusoidal\",\n"
3777 " METHOD[\"Sinusoidal\"],\n"
3778 " PARAMETER[\"Longitude of natural origin\",1,\n"
3779 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3780 " ID[\"EPSG\",8802]],\n"
3781 " PARAMETER[\"False easting\",2,\n"
3782 " LENGTHUNIT[\"metre\",1],\n"
3783 " ID[\"EPSG\",8806]],\n"
3784 " PARAMETER[\"False northing\",3,\n"
3785 " LENGTHUNIT[\"metre\",1],\n"
3786 " ID[\"EPSG\",8807]]]");
3787
3788 EXPECT_EQ(
3789 conv->exportToWKT(
3790 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3791 "PROJECTION[\"Sinusoidal\"],\n"
3792 "PARAMETER[\"longitude_of_center\",1],\n"
3793 "PARAMETER[\"false_easting\",2],\n"
3794 "PARAMETER[\"false_northing\",3]");
3795 }
3796
3797 // ---------------------------------------------------------------------------
3798
TEST(operation,stereographic_export)3799 TEST(operation, stereographic_export) {
3800 auto conv = Conversion::createStereographic(
3801 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
3802 EXPECT_TRUE(conv->validateParameters().empty());
3803
3804 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3805 "+proj=stere +lat_0=1 +lon_0=2 +k=3 +x_0=4 +y_0=5");
3806
3807 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3808 "CONVERSION[\"Stereographic\",\n"
3809 " METHOD[\"Stereographic\"],\n"
3810 " PARAMETER[\"Latitude of natural origin\",1,\n"
3811 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3812 " ID[\"EPSG\",8801]],\n"
3813 " PARAMETER[\"Longitude of natural origin\",2,\n"
3814 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3815 " ID[\"EPSG\",8802]],\n"
3816 " PARAMETER[\"Scale factor at natural origin\",3,\n"
3817 " SCALEUNIT[\"unity\",1],\n"
3818 " ID[\"EPSG\",8805]],\n"
3819 " PARAMETER[\"False easting\",4,\n"
3820 " LENGTHUNIT[\"metre\",1],\n"
3821 " ID[\"EPSG\",8806]],\n"
3822 " PARAMETER[\"False northing\",5,\n"
3823 " LENGTHUNIT[\"metre\",1],\n"
3824 " ID[\"EPSG\",8807]]]");
3825
3826 EXPECT_EQ(
3827 conv->exportToWKT(
3828 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3829 "PROJECTION[\"Stereographic\"],\n"
3830 "PARAMETER[\"latitude_of_origin\",1],\n"
3831 "PARAMETER[\"central_meridian\",2],\n"
3832 "PARAMETER[\"scale_factor\",3],\n"
3833 "PARAMETER[\"false_easting\",4],\n"
3834 "PARAMETER[\"false_northing\",5]");
3835 }
3836
3837 // ---------------------------------------------------------------------------
3838
TEST(operation,vandergrinten_export)3839 TEST(operation, vandergrinten_export) {
3840
3841 auto conv = Conversion::createVanDerGrinten(PropertyMap(), Angle(1),
3842 Length(2), Length(3));
3843 EXPECT_TRUE(conv->validateParameters().empty());
3844
3845 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3846 "+proj=vandg +R_A +lon_0=1 +x_0=2 +y_0=3");
3847
3848 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3849 "CONVERSION[\"Van Der Grinten\",\n"
3850 " METHOD[\"Van Der Grinten\"],\n"
3851 " PARAMETER[\"Longitude of natural origin\",1,\n"
3852 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3853 " ID[\"EPSG\",8802]],\n"
3854 " PARAMETER[\"False easting\",2,\n"
3855 " LENGTHUNIT[\"metre\",1],\n"
3856 " ID[\"EPSG\",8806]],\n"
3857 " PARAMETER[\"False northing\",3,\n"
3858 " LENGTHUNIT[\"metre\",1],\n"
3859 " ID[\"EPSG\",8807]]]");
3860
3861 EXPECT_EQ(
3862 conv->exportToWKT(
3863 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3864 "PROJECTION[\"VanDerGrinten\"],\n"
3865 "PARAMETER[\"central_meridian\",1],\n"
3866 "PARAMETER[\"false_easting\",2],\n"
3867 "PARAMETER[\"false_northing\",3]");
3868 }
3869
3870 // ---------------------------------------------------------------------------
3871
TEST(operation,wagner_export)3872 TEST(operation, wagner_export) {
3873
3874 std::vector<std::string> numbers{"", "1", "2", "3", "4", "5", "6", "7"};
3875 std::vector<std::string> latinNumbers{"", "I", "II", "III",
3876 "IV", "V", "VI", "VII"};
3877
3878 for (int i = 1; i <= 7; i++) {
3879 if (i == 3)
3880 continue;
3881 auto conv =
3882 (i == 1)
3883 ? Conversion::createWagnerI(PropertyMap(), Angle(1), Length(2),
3884 Length(3))
3885 : (i == 2)
3886 ? Conversion::createWagnerII(PropertyMap(), Angle(1),
3887 Length(2), Length(3))
3888 : (i == 4)
3889 ? Conversion::createWagnerIV(
3890 PropertyMap(), Angle(1), Length(2), Length(3))
3891 : (i == 5) ? Conversion::createWagnerV(
3892 PropertyMap(), Angle(1), Length(2),
3893 Length(3))
3894 : (i == 6) ?
3895
3896 Conversion::createWagnerVI(
3897 PropertyMap(), Angle(1),
3898 Length(2), Length(3))
3899 :
3900
3901 Conversion::createWagnerVII(
3902 PropertyMap(), Angle(1),
3903 Length(2), Length(3));
3904 EXPECT_TRUE(conv->validateParameters().empty());
3905
3906 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3907 "+proj=wag" + numbers[i] + " +lon_0=1 +x_0=2 +y_0=3");
3908
3909 auto formatter = WKTFormatter::create();
3910 formatter->simulCurNodeHasId();
3911 EXPECT_EQ(conv->exportToWKT(formatter.get()),
3912 "CONVERSION[\"Wagner " + latinNumbers[i] +
3913 "\",\n"
3914 " METHOD[\"Wagner " +
3915 latinNumbers[i] +
3916 "\"],\n"
3917 " PARAMETER[\"Longitude of natural origin\",1,\n"
3918 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3919 " ID[\"EPSG\",8802]],\n"
3920 " PARAMETER[\"False easting\",2,\n"
3921 " LENGTHUNIT[\"metre\",1],\n"
3922 " ID[\"EPSG\",8806]],\n"
3923 " PARAMETER[\"False northing\",3,\n"
3924 " LENGTHUNIT[\"metre\",1],\n"
3925 " ID[\"EPSG\",8807]]]");
3926
3927 EXPECT_EQ(conv->exportToWKT(
3928 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL)
3929 .get()),
3930 "PROJECTION[\"Wagner_" + latinNumbers[i] +
3931 "\"],\n"
3932 "PARAMETER[\"central_meridian\",1],\n"
3933 "PARAMETER[\"false_easting\",2],\n"
3934 "PARAMETER[\"false_northing\",3]");
3935 }
3936 }
3937
3938 // ---------------------------------------------------------------------------
3939
TEST(operation,wagnerIII_export)3940 TEST(operation, wagnerIII_export) {
3941
3942 auto conv = Conversion::createWagnerIII(PropertyMap(), Angle(1), Angle(2),
3943 Length(3), Length(4));
3944
3945 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3946 "+proj=wag3 +lat_ts=1 +lon_0=2 +x_0=3 +y_0=4");
3947
3948 auto formatter = WKTFormatter::create();
3949 formatter->simulCurNodeHasId();
3950 EXPECT_EQ(conv->exportToWKT(formatter.get()),
3951 "CONVERSION[\"Wagner III\",\n"
3952 " METHOD[\"Wagner III\"],\n"
3953 " PARAMETER[\"Latitude of true scale\",1,\n"
3954 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
3955 " PARAMETER[\"Longitude of natural origin\",2,\n"
3956 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3957 " ID[\"EPSG\",8802]],\n"
3958 " PARAMETER[\"False easting\",3,\n"
3959 " LENGTHUNIT[\"metre\",1],\n"
3960 " ID[\"EPSG\",8806]],\n"
3961 " PARAMETER[\"False northing\",4,\n"
3962 " LENGTHUNIT[\"metre\",1],\n"
3963 " ID[\"EPSG\",8807]]]");
3964
3965 EXPECT_EQ(
3966 conv->exportToWKT(
3967 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
3968 "PROJECTION[\"Wagner_III\"],\n"
3969 "PARAMETER[\"latitude_of_origin\",1],\n"
3970 "PARAMETER[\"central_meridian\",2],\n"
3971 "PARAMETER[\"false_easting\",3],\n"
3972 "PARAMETER[\"false_northing\",4]");
3973 }
3974
3975 // ---------------------------------------------------------------------------
3976
TEST(operation,qsc_export)3977 TEST(operation, qsc_export) {
3978
3979 auto conv = Conversion::createQuadrilateralizedSphericalCube(
3980 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4));
3981 EXPECT_TRUE(conv->validateParameters().empty());
3982
3983 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
3984 "+proj=qsc +lat_0=1 +lon_0=2 +x_0=3 +y_0=4");
3985
3986 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
3987 "CONVERSION[\"Quadrilateralized Spherical Cube\",\n"
3988 " METHOD[\"Quadrilateralized Spherical Cube\"],\n"
3989 " PARAMETER[\"Latitude of natural origin\",1,\n"
3990 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3991 " ID[\"EPSG\",8801]],\n"
3992 " PARAMETER[\"Longitude of natural origin\",2,\n"
3993 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
3994 " ID[\"EPSG\",8802]],\n"
3995 " PARAMETER[\"False easting\",3,\n"
3996 " LENGTHUNIT[\"metre\",1],\n"
3997 " ID[\"EPSG\",8806]],\n"
3998 " PARAMETER[\"False northing\",4,\n"
3999 " LENGTHUNIT[\"metre\",1],\n"
4000 " ID[\"EPSG\",8807]]]");
4001
4002 EXPECT_EQ(
4003 conv->exportToWKT(
4004 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
4005 "PROJECTION[\"Quadrilateralized_Spherical_Cube\"],\n"
4006 "PARAMETER[\"latitude_of_origin\",1],\n"
4007 "PARAMETER[\"central_meridian\",2],\n"
4008 "PARAMETER[\"false_easting\",3],\n"
4009 "PARAMETER[\"false_northing\",4]");
4010 }
4011
4012 // ---------------------------------------------------------------------------
4013
TEST(operation,sch_export)4014 TEST(operation, sch_export) {
4015
4016 auto conv = Conversion::createSphericalCrossTrackHeight(
4017 PropertyMap(), Angle(1), Angle(2), Angle(3), Length(4));
4018 EXPECT_TRUE(conv->validateParameters().empty());
4019
4020 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4021 "+proj=sch +plat_0=1 +plon_0=2 +phdg_0=3 +h_0=4");
4022
4023 auto formatter = WKTFormatter::create();
4024 formatter->simulCurNodeHasId();
4025 EXPECT_EQ(conv->exportToWKT(formatter.get()),
4026 "CONVERSION[\"Spherical Cross-Track Height\",\n"
4027 " METHOD[\"Spherical Cross-Track Height\"],\n"
4028 " PARAMETER[\"Peg point latitude\",1,\n"
4029 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
4030 " PARAMETER[\"Peg point longitude\",2,\n"
4031 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
4032 " PARAMETER[\"Peg point heading\",3,\n"
4033 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
4034 " PARAMETER[\"Peg point height\",4,\n"
4035 " LENGTHUNIT[\"metre\",1]]]");
4036
4037 EXPECT_EQ(
4038 conv->exportToWKT(
4039 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
4040 "PROJECTION[\"Spherical_Cross_Track_Height\"],\n"
4041 "PARAMETER[\"peg_point_latitude\",1],\n"
4042 "PARAMETER[\"peg_point_longitude\",2],\n"
4043 "PARAMETER[\"peg_point_heading\",3],\n"
4044 "PARAMETER[\"peg_point_height\",4]");
4045 }
4046
4047 // ---------------------------------------------------------------------------
4048
TEST(operation,conversion_inverse)4049 TEST(operation, conversion_inverse) {
4050 auto conv = Conversion::createTransverseMercator(
4051 PropertyMap(), Angle(1), Angle(2), Scale(3), Length(4), Length(5));
4052 auto inv = conv->inverse();
4053 EXPECT_EQ(inv->inverse(), conv);
4054 EXPECT_EQ(inv->exportToWKT(WKTFormatter::create().get()),
4055 "CONVERSION[\"Inverse of Transverse Mercator\",\n"
4056 " METHOD[\"Inverse of Transverse Mercator\",\n"
4057 " ID[\"INVERSE(EPSG)\",9807]],\n"
4058 " PARAMETER[\"Latitude of natural origin\",1,\n"
4059 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4060 " ID[\"EPSG\",8801]],\n"
4061 " PARAMETER[\"Longitude of natural origin\",2,\n"
4062 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4063 " ID[\"EPSG\",8802]],\n"
4064 " PARAMETER[\"Scale factor at natural origin\",3,\n"
4065 " SCALEUNIT[\"unity\",1],\n"
4066 " ID[\"EPSG\",8805]],\n"
4067 " PARAMETER[\"False easting\",4,\n"
4068 " LENGTHUNIT[\"metre\",1],\n"
4069 " ID[\"EPSG\",8806]],\n"
4070 " PARAMETER[\"False northing\",5,\n"
4071 " LENGTHUNIT[\"metre\",1],\n"
4072 " ID[\"EPSG\",8807]]]");
4073
4074 EXPECT_EQ(inv->exportToPROJString(PROJStringFormatter::create().get()),
4075 "+proj=pipeline +step +inv +proj=tmerc +lat_0=1 +lon_0=2 +k=3 "
4076 "+x_0=4 +y_0=5");
4077
4078 EXPECT_TRUE(inv->isEquivalentTo(inv.get()));
4079 EXPECT_FALSE(inv->isEquivalentTo(createUnrelatedObject().get()));
4080
4081 EXPECT_TRUE(
4082 conv->isEquivalentTo(conv->CoordinateOperation::shallowClone().get()));
4083 EXPECT_TRUE(
4084 inv->isEquivalentTo(inv->CoordinateOperation::shallowClone().get()));
4085 }
4086
4087 // ---------------------------------------------------------------------------
4088
TEST(operation,eqearth_export)4089 TEST(operation, eqearth_export) {
4090
4091 auto conv = Conversion::createEqualEarth(PropertyMap(), Angle(1), Length(2),
4092 Length(3));
4093
4094 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4095 "+proj=eqearth +lon_0=1 +x_0=2 +y_0=3");
4096
4097 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
4098 "CONVERSION[\"Equal Earth\",\n"
4099 " METHOD[\"Equal Earth\",\n"
4100 " ID[\"EPSG\",1078]],\n"
4101 " PARAMETER[\"Longitude of natural origin\",1,\n"
4102 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4103 " ID[\"EPSG\",8802]],\n"
4104 " PARAMETER[\"False easting\",2,\n"
4105 " LENGTHUNIT[\"metre\",1],\n"
4106 " ID[\"EPSG\",8806]],\n"
4107 " PARAMETER[\"False northing\",3,\n"
4108 " LENGTHUNIT[\"metre\",1],\n"
4109 " ID[\"EPSG\",8807]]]");
4110 }
4111
4112 // ---------------------------------------------------------------------------
4113
TEST(operation,vertical_perspective_export)4114 TEST(operation, vertical_perspective_export) {
4115
4116 auto conv = Conversion::createVerticalPerspective(
4117 PropertyMap(), Angle(1), Angle(2), Length(3), Length(4), Length(5),
4118 Length(6));
4119
4120 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4121 "+proj=nsper +lat_0=1 +lon_0=2 +h=4 +x_0=5 +y_0=6");
4122
4123 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
4124 "CONVERSION[\"Vertical Perspective\",\n"
4125 " METHOD[\"Vertical Perspective\",\n"
4126 " ID[\"EPSG\",9838]],\n"
4127 " PARAMETER[\"Latitude of topocentric origin\",1,\n"
4128 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4129 " ID[\"EPSG\",8834]],\n"
4130 " PARAMETER[\"Longitude of topocentric origin\",2,\n"
4131 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4132 " ID[\"EPSG\",8835]],\n"
4133 " PARAMETER[\"Ellipsoidal height of topocentric origin\",3,\n"
4134 " LENGTHUNIT[\"metre\",1],\n"
4135 " ID[\"EPSG\",8836]],\n"
4136 " PARAMETER[\"Viewpoint height\",4,\n"
4137 " LENGTHUNIT[\"metre\",1],\n"
4138 " ID[\"EPSG\",8840]],\n"
4139 " PARAMETER[\"False easting\",5,\n"
4140 " LENGTHUNIT[\"metre\",1],\n"
4141 " ID[\"EPSG\",8806]],\n"
4142 " PARAMETER[\"False northing\",6,\n"
4143 " LENGTHUNIT[\"metre\",1],\n"
4144 " ID[\"EPSG\",8807]]]");
4145 }
4146
4147 // ---------------------------------------------------------------------------
4148
TEST(operation,vertical_perspective_export_no_topocentric_height_and_false_easting_northing)4149 TEST(
4150 operation,
4151 vertical_perspective_export_no_topocentric_height_and_false_easting_northing) {
4152
4153 auto conv = Conversion::createVerticalPerspective(
4154 PropertyMap(), Angle(1), Angle(2), Length(0), Length(4), Length(0),
4155 Length(0));
4156
4157 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4158 "+proj=nsper +lat_0=1 +lon_0=2 +h=4 +x_0=0 +y_0=0");
4159
4160 // Check that False esting and False northing are not exported, when they
4161 // are 0.
4162 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
4163 "CONVERSION[\"Vertical Perspective\",\n"
4164 " METHOD[\"Vertical Perspective\",\n"
4165 " ID[\"EPSG\",9838]],\n"
4166 " PARAMETER[\"Latitude of topocentric origin\",1,\n"
4167 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4168 " ID[\"EPSG\",8834]],\n"
4169 " PARAMETER[\"Longitude of topocentric origin\",2,\n"
4170 " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
4171 " ID[\"EPSG\",8835]],\n"
4172 " PARAMETER[\"Ellipsoidal height of topocentric origin\",0,\n"
4173 " LENGTHUNIT[\"metre\",1],\n"
4174 " ID[\"EPSG\",8836]],\n"
4175 " PARAMETER[\"Viewpoint height\",4,\n"
4176 " LENGTHUNIT[\"metre\",1],\n"
4177 " ID[\"EPSG\",8840]]]");
4178 }
4179
4180 // ---------------------------------------------------------------------------
4181
TEST(operation,laborde_oblique_mercator)4182 TEST(operation, laborde_oblique_mercator) {
4183
4184 // Content of EPSG:29701 "Tananarive (Paris) / Laborde Grid"
4185 auto projString = "+proj=labrd +lat_0=-18.9 +lon_0=44.1 +azi=18.9 "
4186 "+k=0.9995 +x_0=400000 +y_0=800000 +ellps=intl +pm=paris "
4187 "+units=m +no_defs +type=crs";
4188 auto obj = PROJStringParser().createFromPROJString(projString);
4189 auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
4190 ASSERT_TRUE(crs != nullptr);
4191 EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
4192 projString);
4193 }
4194
4195 // ---------------------------------------------------------------------------
4196
TEST(operation,adams_ws2_export)4197 TEST(operation, adams_ws2_export) {
4198 auto dbContext = DatabaseContext::create();
4199 // ESRI:54098 WGS_1984_Adams_Square_II
4200 auto crs = AuthorityFactory::create(dbContext, "ESRI")
4201 ->createProjectedCRS("54098");
4202 EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
4203 "+proj=adams_ws2 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m "
4204 "+no_defs +type=crs");
4205 }
4206
4207 // ---------------------------------------------------------------------------
4208
TEST(operation,adams_ws2_export_failure)4209 TEST(operation, adams_ws2_export_failure) {
4210 auto dbContext = DatabaseContext::create();
4211 // ESRI:54099 WGS_1984_Spilhaus_Ocean_Map_in_Square
4212 auto crs = AuthorityFactory::create(dbContext, "ESRI")
4213 ->createProjectedCRS("54099");
4214 EXPECT_THROW(crs->exportToPROJString(PROJStringFormatter::create().get()),
4215 FormattingException);
4216 }
4217
4218 // ---------------------------------------------------------------------------
4219
TEST(operation,PROJ_based)4220 TEST(operation, PROJ_based) {
4221 auto conv = SingleOperation::createPROJBased(PropertyMap(), "+proj=merc",
4222 nullptr, nullptr);
4223
4224 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4225 "+proj=merc");
4226
4227 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
4228 "CONVERSION[\"PROJ-based coordinate operation\",\n"
4229 " METHOD[\"PROJ-based operation method: +proj=merc\"]]");
4230
4231 EXPECT_EQ(conv->inverse()->exportToPROJString(
4232 PROJStringFormatter::create().get()),
4233 "+proj=pipeline +step +inv +proj=merc");
4234
4235 auto str = "+proj=pipeline +step +proj=unitconvert +xy_in=grad +xy_out=rad "
4236 "+step +proj=axisswap +order=2,1 +step +proj=longlat "
4237 "+ellps=clrk80ign +pm=paris +step +proj=axisswap +order=2,1";
4238 EXPECT_EQ(
4239 SingleOperation::createPROJBased(PropertyMap(), str, nullptr, nullptr)
4240 ->exportToPROJString(PROJStringFormatter::create().get()),
4241 str);
4242
4243 EXPECT_THROW(SingleOperation::createPROJBased(
4244 PropertyMap(), "+proj=pipeline +step +proj=pipeline",
4245 nullptr, nullptr)
4246 ->exportToPROJString(PROJStringFormatter::create().get()),
4247 FormattingException);
4248 }
4249
4250 // ---------------------------------------------------------------------------
4251
TEST(operation,PROJ_based_empty)4252 TEST(operation, PROJ_based_empty) {
4253 auto conv =
4254 SingleOperation::createPROJBased(PropertyMap(), "", nullptr, nullptr);
4255
4256 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4257 "+proj=noop");
4258
4259 EXPECT_EQ(conv->exportToWKT(WKTFormatter::create().get()),
4260 "CONVERSION[\"PROJ-based coordinate operation\",\n"
4261 " METHOD[\"PROJ-based operation method: \"]]");
4262
4263 EXPECT_THROW(
4264 conv->exportToWKT(
4265 WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
4266 FormattingException);
4267
4268 EXPECT_EQ(conv->inverse()->exportToPROJString(
4269 PROJStringFormatter::create().get()),
4270 "+proj=noop");
4271 }
4272
4273 // ---------------------------------------------------------------------------
4274
TEST(operation,PROJ_based_with_global_parameters)4275 TEST(operation, PROJ_based_with_global_parameters) {
4276 auto conv = SingleOperation::createPROJBased(
4277 PropertyMap(), "+proj=pipeline +ellps=WGS84 +step +proj=longlat",
4278 nullptr, nullptr);
4279
4280 EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),
4281 "+proj=pipeline +ellps=WGS84 +step +proj=longlat");
4282 }
4283
4284 // ---------------------------------------------------------------------------
4285
TEST(operation,mercator_variant_A_to_variant_B)4286 TEST(operation, mercator_variant_A_to_variant_B) {
4287 auto projCRS = ProjectedCRS::create(
4288 PropertyMap(), GeographicCRS::EPSG_4326,
4289 Conversion::createMercatorVariantA(PropertyMap(), Angle(0), Angle(1),
4290 Scale(0.9), Length(3), Length(4)),
4291 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4292
4293 auto conv = projCRS->derivingConversion();
4294 auto sameConv =
4295 conv->convertToOtherMethod(EPSG_CODE_METHOD_MERCATOR_VARIANT_A);
4296 ASSERT_TRUE(sameConv);
4297 EXPECT_TRUE(sameConv->isEquivalentTo(conv.get()));
4298
4299 auto targetConv =
4300 conv->convertToOtherMethod(EPSG_CODE_METHOD_MERCATOR_VARIANT_B);
4301 ASSERT_TRUE(targetConv);
4302
4303 auto lat_1 = targetConv->parameterValueNumeric(
4304 EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, UnitOfMeasure::DEGREE);
4305 EXPECT_EQ(lat_1, 25.917499691810534) << lat_1;
4306
4307 EXPECT_EQ(targetConv->parameterValueNumeric(
4308 EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN,
4309 UnitOfMeasure::DEGREE),
4310 1);
4311
4312 EXPECT_EQ(targetConv->parameterValueNumeric(
4313 EPSG_CODE_PARAMETER_FALSE_EASTING, UnitOfMeasure::METRE),
4314 3);
4315
4316 EXPECT_EQ(targetConv->parameterValueNumeric(
4317 EPSG_CODE_PARAMETER_FALSE_NORTHING, UnitOfMeasure::METRE),
4318 4);
4319
4320 EXPECT_FALSE(
4321 conv->isEquivalentTo(targetConv.get(), IComparable::Criterion::STRICT));
4322 EXPECT_TRUE(conv->isEquivalentTo(targetConv.get(),
4323 IComparable::Criterion::EQUIVALENT));
4324 EXPECT_TRUE(targetConv->isEquivalentTo(conv.get(),
4325 IComparable::Criterion::EQUIVALENT));
4326 }
4327
4328 // ---------------------------------------------------------------------------
4329
TEST(operation,mercator_variant_A_to_variant_B_scale_1)4330 TEST(operation, mercator_variant_A_to_variant_B_scale_1) {
4331 auto projCRS = ProjectedCRS::create(
4332 PropertyMap(), GeographicCRS::EPSG_4326,
4333 Conversion::createMercatorVariantA(PropertyMap(), Angle(0), Angle(1),
4334 Scale(1.0), Length(3), Length(4)),
4335 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4336
4337 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4338 EPSG_CODE_METHOD_MERCATOR_VARIANT_B);
4339 ASSERT_TRUE(targetConv);
4340
4341 auto lat_1 = targetConv->parameterValueNumeric(
4342 EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, UnitOfMeasure::DEGREE);
4343 EXPECT_EQ(lat_1, 0.0) << lat_1;
4344 }
4345
4346 // ---------------------------------------------------------------------------
4347
TEST(operation,mercator_variant_A_to_variant_B_no_crs)4348 TEST(operation, mercator_variant_A_to_variant_B_no_crs) {
4349 auto targetConv =
4350 Conversion::createMercatorVariantA(PropertyMap(), Angle(0), Angle(1),
4351 Scale(1.0), Length(3), Length(4))
4352 ->convertToOtherMethod(EPSG_CODE_METHOD_MERCATOR_VARIANT_B);
4353 EXPECT_FALSE(targetConv != nullptr);
4354 }
4355
4356 // ---------------------------------------------------------------------------
4357
TEST(operation,mercator_variant_A_to_variant_B_invalid_scale)4358 TEST(operation, mercator_variant_A_to_variant_B_invalid_scale) {
4359 auto projCRS = ProjectedCRS::create(
4360 PropertyMap(), GeographicCRS::EPSG_4326,
4361 Conversion::createMercatorVariantA(PropertyMap(), Angle(0), Angle(1),
4362 Scale(0.0), Length(3), Length(4)),
4363 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4364
4365 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4366 EPSG_CODE_METHOD_MERCATOR_VARIANT_B);
4367 EXPECT_FALSE(targetConv != nullptr);
4368 }
4369
4370 // ---------------------------------------------------------------------------
4371
geographicCRSInvalidEccentricity()4372 static GeographicCRSNNPtr geographicCRSInvalidEccentricity() {
4373 return GeographicCRS::create(
4374 PropertyMap(),
4375 GeodeticReferenceFrame::create(
4376 PropertyMap(), Ellipsoid::createFlattenedSphere(
4377 PropertyMap(), Length(6378137), Scale(0.1)),
4378 optional<std::string>(), PrimeMeridian::GREENWICH),
4379 EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE));
4380 }
4381
4382 // ---------------------------------------------------------------------------
4383
TEST(operation,mercator_variant_A_to_variant_B_invalid_eccentricity)4384 TEST(operation, mercator_variant_A_to_variant_B_invalid_eccentricity) {
4385 auto projCRS = ProjectedCRS::create(
4386 PropertyMap(), geographicCRSInvalidEccentricity(),
4387 Conversion::createMercatorVariantA(PropertyMap(), Angle(0), Angle(1),
4388 Scale(1.0), Length(3), Length(4)),
4389 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4390
4391 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4392 EPSG_CODE_METHOD_MERCATOR_VARIANT_B);
4393 EXPECT_FALSE(targetConv != nullptr);
4394 }
4395
4396 // ---------------------------------------------------------------------------
4397
TEST(operation,mercator_variant_B_to_variant_A)4398 TEST(operation, mercator_variant_B_to_variant_A) {
4399 auto projCRS = ProjectedCRS::create(
4400 PropertyMap(), GeographicCRS::EPSG_4326,
4401 Conversion::createMercatorVariantB(PropertyMap(),
4402 Angle(25.917499691810534), Angle(1),
4403 Length(3), Length(4)),
4404 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4405 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4406 EPSG_CODE_METHOD_MERCATOR_VARIANT_A);
4407 ASSERT_TRUE(targetConv);
4408
4409 EXPECT_EQ(targetConv->parameterValueNumeric(
4410 EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN,
4411 UnitOfMeasure::DEGREE),
4412 0);
4413
4414 EXPECT_EQ(targetConv->parameterValueNumeric(
4415 EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN,
4416 UnitOfMeasure::DEGREE),
4417 1);
4418
4419 auto k_0 = targetConv->parameterValueNumeric(
4420 EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN,
4421 UnitOfMeasure::SCALE_UNITY);
4422 EXPECT_EQ(k_0, 0.9) << k_0;
4423
4424 EXPECT_EQ(targetConv->parameterValueNumeric(
4425 EPSG_CODE_PARAMETER_FALSE_EASTING, UnitOfMeasure::METRE),
4426 3);
4427
4428 EXPECT_EQ(targetConv->parameterValueNumeric(
4429 EPSG_CODE_PARAMETER_FALSE_NORTHING, UnitOfMeasure::METRE),
4430 4);
4431 }
4432
4433 // ---------------------------------------------------------------------------
4434
TEST(operation,mercator_variant_B_to_variant_A_invalid_std1)4435 TEST(operation, mercator_variant_B_to_variant_A_invalid_std1) {
4436 auto projCRS = ProjectedCRS::create(
4437 PropertyMap(), GeographicCRS::EPSG_4326,
4438 Conversion::createMercatorVariantB(PropertyMap(), Angle(100), Angle(1),
4439 Length(3), Length(4)),
4440 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4441 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4442 EPSG_CODE_METHOD_MERCATOR_VARIANT_A);
4443 EXPECT_FALSE(targetConv != nullptr);
4444 }
4445
4446 // ---------------------------------------------------------------------------
4447
TEST(operation,mercator_variant_B_to_variant_A_invalid_eccentricity)4448 TEST(operation, mercator_variant_B_to_variant_A_invalid_eccentricity) {
4449 auto projCRS = ProjectedCRS::create(
4450 PropertyMap(), geographicCRSInvalidEccentricity(),
4451 Conversion::createMercatorVariantB(PropertyMap(), Angle(0), Angle(1),
4452 Length(3), Length(4)),
4453 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4454 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4455 EPSG_CODE_METHOD_MERCATOR_VARIANT_A);
4456 EXPECT_FALSE(targetConv != nullptr);
4457 }
4458
4459 // ---------------------------------------------------------------------------
4460
TEST(operation,lcc2sp_to_lcc1sp)4461 TEST(operation, lcc2sp_to_lcc1sp) {
4462 // equivalent to EPSG:2154
4463 auto projCRS = ProjectedCRS::create(
4464 PropertyMap(), GeographicCRS::EPSG_4269, // something using GRS80
4465 Conversion::createLambertConicConformal_2SP(
4466 PropertyMap(), Angle(46.5), Angle(3), Angle(49), Angle(44),
4467 Length(700000), Length(6600000)),
4468 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4469
4470 auto conv = projCRS->derivingConversion();
4471 auto targetConv = conv->convertToOtherMethod(
4472 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4473 ASSERT_TRUE(targetConv);
4474
4475 {
4476 auto lat_0 = targetConv->parameterValueNumeric(
4477 EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN,
4478 UnitOfMeasure::DEGREE);
4479 EXPECT_NEAR(lat_0, 46.519430223986866, 1e-12) << lat_0;
4480
4481 auto lon_0 = targetConv->parameterValueNumeric(
4482 EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN,
4483 UnitOfMeasure::DEGREE);
4484 EXPECT_NEAR(lon_0, 3.0, 1e-15) << lon_0;
4485
4486 auto k_0 = targetConv->parameterValueNumeric(
4487 EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN,
4488 UnitOfMeasure::SCALE_UNITY);
4489 EXPECT_NEAR(k_0, 0.9990510286374692, 1e-15) << k_0;
4490
4491 auto x_0 = targetConv->parameterValueNumeric(
4492 EPSG_CODE_PARAMETER_FALSE_EASTING, UnitOfMeasure::METRE);
4493 EXPECT_NEAR(x_0, 700000, 1e-15) << x_0;
4494
4495 auto y_0 = targetConv->parameterValueNumeric(
4496 EPSG_CODE_PARAMETER_FALSE_NORTHING, UnitOfMeasure::METRE);
4497 EXPECT_NEAR(y_0, 6602157.8388103368, 1e-7) << y_0;
4498 }
4499
4500 auto _2sp_from_1sp = targetConv->convertToOtherMethod(
4501 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4502 ASSERT_TRUE(_2sp_from_1sp);
4503
4504 {
4505 auto lat_0 = _2sp_from_1sp->parameterValueNumeric(
4506 EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, UnitOfMeasure::DEGREE);
4507 EXPECT_NEAR(lat_0, 46.5, 1e-15) << lat_0;
4508
4509 auto lon_0 = _2sp_from_1sp->parameterValueNumeric(
4510 EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, UnitOfMeasure::DEGREE);
4511 EXPECT_NEAR(lon_0, 3, 1e-15) << lon_0;
4512
4513 auto lat_1 = _2sp_from_1sp->parameterValueNumeric(
4514 EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
4515 UnitOfMeasure::DEGREE);
4516 EXPECT_NEAR(lat_1, 49, 1e-15) << lat_1;
4517
4518 auto lat_2 = _2sp_from_1sp->parameterValueNumeric(
4519 EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL,
4520 UnitOfMeasure::DEGREE);
4521 EXPECT_NEAR(lat_2, 44, 1e-15) << lat_2;
4522
4523 auto x_0 = _2sp_from_1sp->parameterValueNumeric(
4524 EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, UnitOfMeasure::METRE);
4525 EXPECT_NEAR(x_0, 700000, 1e-15) << x_0;
4526
4527 auto y_0 = _2sp_from_1sp->parameterValueNumeric(
4528 EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, UnitOfMeasure::METRE);
4529 EXPECT_NEAR(y_0, 6600000, 1e-15) << y_0;
4530 }
4531
4532 EXPECT_FALSE(
4533 conv->isEquivalentTo(targetConv.get(), IComparable::Criterion::STRICT));
4534 EXPECT_TRUE(conv->isEquivalentTo(targetConv.get(),
4535 IComparable::Criterion::EQUIVALENT));
4536 EXPECT_TRUE(targetConv->isEquivalentTo(conv.get(),
4537 IComparable::Criterion::EQUIVALENT));
4538 }
4539
4540 // ---------------------------------------------------------------------------
4541
TEST(operation,lcc2sp_to_lcc1sp_phi0_eq_phi1_eq_phi2)4542 TEST(operation, lcc2sp_to_lcc1sp_phi0_eq_phi1_eq_phi2) {
4543 auto projCRS = ProjectedCRS::create(
4544 PropertyMap(), GeographicCRS::EPSG_4269, // something using GRS80
4545 Conversion::createLambertConicConformal_2SP(
4546 PropertyMap(), Angle(46.5), Angle(3), Angle(46.5), Angle(46.5),
4547 Length(700000), Length(6600000)),
4548 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4549
4550 auto conv = projCRS->derivingConversion();
4551 auto targetConv = conv->convertToOtherMethod(
4552 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4553 ASSERT_TRUE(targetConv);
4554
4555 {
4556 auto lat_0 = targetConv->parameterValueNumeric(
4557 EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN,
4558 UnitOfMeasure::DEGREE);
4559 EXPECT_NEAR(lat_0, 46.5, 1e-15) << lat_0;
4560
4561 auto lon_0 = targetConv->parameterValueNumeric(
4562 EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN,
4563 UnitOfMeasure::DEGREE);
4564 EXPECT_NEAR(lon_0, 3.0, 1e-15) << lon_0;
4565
4566 auto k_0 = targetConv->parameterValueNumeric(
4567 EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN,
4568 UnitOfMeasure::SCALE_UNITY);
4569 EXPECT_NEAR(k_0, 1.0, 1e-15) << k_0;
4570
4571 auto x_0 = targetConv->parameterValueNumeric(
4572 EPSG_CODE_PARAMETER_FALSE_EASTING, UnitOfMeasure::METRE);
4573 EXPECT_NEAR(x_0, 700000, 1e-15) << x_0;
4574
4575 auto y_0 = targetConv->parameterValueNumeric(
4576 EPSG_CODE_PARAMETER_FALSE_NORTHING, UnitOfMeasure::METRE);
4577 EXPECT_NEAR(y_0, 6600000, 1e-15) << y_0;
4578 }
4579
4580 auto _2sp_from_1sp = targetConv->convertToOtherMethod(
4581 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4582 ASSERT_TRUE(_2sp_from_1sp);
4583
4584 {
4585 auto lat_0 = _2sp_from_1sp->parameterValueNumeric(
4586 EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, UnitOfMeasure::DEGREE);
4587 EXPECT_NEAR(lat_0, 46.5, 1e-15) << lat_0;
4588
4589 auto lon_0 = _2sp_from_1sp->parameterValueNumeric(
4590 EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, UnitOfMeasure::DEGREE);
4591 EXPECT_NEAR(lon_0, 3, 1e-15) << lon_0;
4592
4593 auto lat_1 = _2sp_from_1sp->parameterValueNumeric(
4594 EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
4595 UnitOfMeasure::DEGREE);
4596 EXPECT_NEAR(lat_1, 46.5, 1e-15) << lat_1;
4597
4598 auto lat_2 = _2sp_from_1sp->parameterValueNumeric(
4599 EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL,
4600 UnitOfMeasure::DEGREE);
4601 EXPECT_NEAR(lat_2, 46.5, 1e-15) << lat_2;
4602
4603 auto x_0 = _2sp_from_1sp->parameterValueNumeric(
4604 EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, UnitOfMeasure::METRE);
4605 EXPECT_NEAR(x_0, 700000, 1e-15) << x_0;
4606
4607 auto y_0 = _2sp_from_1sp->parameterValueNumeric(
4608 EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, UnitOfMeasure::METRE);
4609 EXPECT_NEAR(y_0, 6600000, 1e-15) << y_0;
4610 }
4611
4612 EXPECT_TRUE(conv->isEquivalentTo(targetConv.get(),
4613 IComparable::Criterion::EQUIVALENT));
4614 EXPECT_TRUE(targetConv->isEquivalentTo(conv.get(),
4615 IComparable::Criterion::EQUIVALENT));
4616 }
4617
4618 // ---------------------------------------------------------------------------
4619
TEST(operation,lcc2sp_to_lcc1sp_phi0_diff_phi1_and_phi1_eq_phi2)4620 TEST(operation, lcc2sp_to_lcc1sp_phi0_diff_phi1_and_phi1_eq_phi2) {
4621
4622 auto projCRS = ProjectedCRS::create(
4623 PropertyMap(), GeographicCRS::EPSG_4269, // something using GRS80
4624 Conversion::createLambertConicConformal_2SP(
4625 PropertyMap(), Angle(46.123), Angle(3), Angle(46.4567),
4626 Angle(46.4567), Length(700000), Length(6600000)),
4627 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4628
4629 auto conv = projCRS->derivingConversion();
4630 auto targetConv = conv->convertToOtherMethod(
4631 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4632 ASSERT_TRUE(targetConv);
4633
4634 {
4635 auto lat_0 = targetConv->parameterValueNumeric(
4636 EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN,
4637 UnitOfMeasure::DEGREE);
4638 EXPECT_NEAR(lat_0, 46.4567, 1e-14) << lat_0;
4639
4640 auto lon_0 = targetConv->parameterValueNumeric(
4641 EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN,
4642 UnitOfMeasure::DEGREE);
4643 EXPECT_NEAR(lon_0, 3.0, 1e-15) << lon_0;
4644
4645 auto k_0 = targetConv->parameterValueNumeric(
4646 EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN,
4647 UnitOfMeasure::SCALE_UNITY);
4648 EXPECT_NEAR(k_0, 1.0, 1e-15) << k_0;
4649
4650 auto x_0 = targetConv->parameterValueNumeric(
4651 EPSG_CODE_PARAMETER_FALSE_EASTING, UnitOfMeasure::METRE);
4652 EXPECT_NEAR(x_0, 700000, 1e-15) << x_0;
4653
4654 auto y_0 = targetConv->parameterValueNumeric(
4655 EPSG_CODE_PARAMETER_FALSE_NORTHING, UnitOfMeasure::METRE);
4656 EXPECT_NEAR(y_0, 6637093.292952879, 1e-8) << y_0;
4657 }
4658
4659 auto _2sp_from_1sp = targetConv->convertToOtherMethod(
4660 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4661 ASSERT_TRUE(_2sp_from_1sp);
4662
4663 {
4664 auto lat_0 = _2sp_from_1sp->parameterValueNumeric(
4665 EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, UnitOfMeasure::DEGREE);
4666 EXPECT_NEAR(lat_0, 46.4567, 1e-14) << lat_0;
4667
4668 auto lon_0 = _2sp_from_1sp->parameterValueNumeric(
4669 EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, UnitOfMeasure::DEGREE);
4670 EXPECT_NEAR(lon_0, 3, 1e-15) << lon_0;
4671
4672 auto lat_1 = _2sp_from_1sp->parameterValueNumeric(
4673 EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL,
4674 UnitOfMeasure::DEGREE);
4675 EXPECT_NEAR(lat_1, 46.4567, 1e-14) << lat_1;
4676
4677 auto lat_2 = _2sp_from_1sp->parameterValueNumeric(
4678 EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL,
4679 UnitOfMeasure::DEGREE);
4680 EXPECT_NEAR(lat_2, 46.4567, 1e-14) << lat_2;
4681
4682 auto x_0 = _2sp_from_1sp->parameterValueNumeric(
4683 EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, UnitOfMeasure::METRE);
4684 EXPECT_NEAR(x_0, 700000, 1e-15) << x_0;
4685
4686 auto y_0 = _2sp_from_1sp->parameterValueNumeric(
4687 EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, UnitOfMeasure::METRE);
4688 EXPECT_NEAR(y_0, 6637093.292952879, 1e-8) << y_0;
4689 }
4690
4691 EXPECT_TRUE(conv->isEquivalentTo(targetConv.get(),
4692 IComparable::Criterion::EQUIVALENT));
4693 EXPECT_TRUE(targetConv->isEquivalentTo(conv.get(),
4694 IComparable::Criterion::EQUIVALENT));
4695
4696 EXPECT_TRUE(_2sp_from_1sp->isEquivalentTo(
4697 targetConv.get(), IComparable::Criterion::EQUIVALENT));
4698 EXPECT_TRUE(targetConv->isEquivalentTo(_2sp_from_1sp.get(),
4699 IComparable::Criterion::EQUIVALENT));
4700
4701 EXPECT_TRUE(conv->isEquivalentTo(_2sp_from_1sp.get(),
4702 IComparable::Criterion::EQUIVALENT));
4703 }
4704
4705 // ---------------------------------------------------------------------------
4706
TEST(operation,lcc1sp_to_lcc2sp_invalid_eccentricity)4707 TEST(operation, lcc1sp_to_lcc2sp_invalid_eccentricity) {
4708 auto projCRS = ProjectedCRS::create(
4709 PropertyMap(), geographicCRSInvalidEccentricity(),
4710 Conversion::createLambertConicConformal_1SP(PropertyMap(), Angle(40),
4711 Angle(1), Scale(0.99),
4712 Length(3), Length(4)),
4713 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4714 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4715 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4716 EXPECT_FALSE(targetConv != nullptr);
4717 }
4718
4719 // ---------------------------------------------------------------------------
4720
TEST(operation,lcc1sp_to_lcc2sp_invalid_scale)4721 TEST(operation, lcc1sp_to_lcc2sp_invalid_scale) {
4722 auto projCRS = ProjectedCRS::create(
4723 PropertyMap(), GeographicCRS::EPSG_4326,
4724 Conversion::createLambertConicConformal_1SP(
4725 PropertyMap(), Angle(40), Angle(1), Scale(0), Length(3), Length(4)),
4726 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4727 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4728 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4729 EXPECT_FALSE(targetConv != nullptr);
4730 }
4731
4732 // ---------------------------------------------------------------------------
4733
TEST(operation,lcc1sp_to_lcc2sp_invalid_lat0)4734 TEST(operation, lcc1sp_to_lcc2sp_invalid_lat0) {
4735 auto projCRS = ProjectedCRS::create(
4736 PropertyMap(), GeographicCRS::EPSG_4326,
4737 Conversion::createLambertConicConformal_1SP(PropertyMap(), Angle(100),
4738 Angle(1), Scale(0.99),
4739 Length(3), Length(4)),
4740 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4741 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4742 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4743 EXPECT_FALSE(targetConv != nullptr);
4744 }
4745
4746 // ---------------------------------------------------------------------------
4747
TEST(operation,lcc1sp_to_lcc2sp_null_lat0)4748 TEST(operation, lcc1sp_to_lcc2sp_null_lat0) {
4749 auto projCRS = ProjectedCRS::create(
4750 PropertyMap(), GeographicCRS::EPSG_4326,
4751 Conversion::createLambertConicConformal_1SP(PropertyMap(), Angle(0),
4752 Angle(1), Scale(0.99),
4753 Length(3), Length(4)),
4754 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4755 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4756 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
4757 EXPECT_FALSE(targetConv != nullptr);
4758 }
4759
4760 // ---------------------------------------------------------------------------
4761
TEST(operation,lcc2sp_to_lcc1sp_invalid_lat0)4762 TEST(operation, lcc2sp_to_lcc1sp_invalid_lat0) {
4763 auto projCRS = ProjectedCRS::create(
4764 PropertyMap(), GeographicCRS::EPSG_4326,
4765 Conversion::createLambertConicConformal_2SP(
4766 PropertyMap(), Angle(100), Angle(3), Angle(44), Angle(49),
4767 Length(700000), Length(6600000)),
4768 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4769 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4770 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4771 EXPECT_FALSE(targetConv != nullptr);
4772 }
4773
4774 // ---------------------------------------------------------------------------
4775
TEST(operation,lcc2sp_to_lcc1sp_invalid_lat1)4776 TEST(operation, lcc2sp_to_lcc1sp_invalid_lat1) {
4777 auto projCRS = ProjectedCRS::create(
4778 PropertyMap(), GeographicCRS::EPSG_4326,
4779 Conversion::createLambertConicConformal_2SP(
4780 PropertyMap(), Angle(46.5), Angle(3), Angle(100), Angle(49),
4781 Length(700000), Length(6600000)),
4782 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4783 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4784 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4785 EXPECT_FALSE(targetConv != nullptr);
4786 }
4787
4788 // ---------------------------------------------------------------------------
4789
TEST(operation,lcc2sp_to_lcc1sp_invalid_lat2)4790 TEST(operation, lcc2sp_to_lcc1sp_invalid_lat2) {
4791 auto projCRS = ProjectedCRS::create(
4792 PropertyMap(), GeographicCRS::EPSG_4326,
4793 Conversion::createLambertConicConformal_2SP(
4794 PropertyMap(), Angle(46.5), Angle(3), Angle(44), Angle(100),
4795 Length(700000), Length(6600000)),
4796 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4797 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4798 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4799 EXPECT_FALSE(targetConv != nullptr);
4800 }
4801
4802 // ---------------------------------------------------------------------------
4803
TEST(operation,lcc2sp_to_lcc1sp_invalid_lat1_opposite_lat2)4804 TEST(operation, lcc2sp_to_lcc1sp_invalid_lat1_opposite_lat2) {
4805 auto projCRS = ProjectedCRS::create(
4806 PropertyMap(), GeographicCRS::EPSG_4326,
4807 Conversion::createLambertConicConformal_2SP(
4808 PropertyMap(), Angle(46.5), Angle(3), Angle(-49), Angle(49),
4809 Length(700000), Length(6600000)),
4810 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4811 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4812 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4813 EXPECT_FALSE(targetConv != nullptr);
4814 }
4815
4816 // ---------------------------------------------------------------------------
4817
TEST(operation,lcc2sp_to_lcc1sp_invalid_lat1_and_lat2_close_to_zero)4818 TEST(operation, lcc2sp_to_lcc1sp_invalid_lat1_and_lat2_close_to_zero) {
4819 auto projCRS = ProjectedCRS::create(
4820 PropertyMap(), GeographicCRS::EPSG_4326,
4821 Conversion::createLambertConicConformal_2SP(
4822 PropertyMap(), Angle(46.5), Angle(3), Angle(.0000000000000001),
4823 Angle(.0000000000000002), Length(700000), Length(6600000)),
4824 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4825 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4826 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4827 EXPECT_FALSE(targetConv != nullptr);
4828 }
4829
4830 // ---------------------------------------------------------------------------
4831
TEST(operation,lcc2sp_to_lcc1sp_invalid_eccentricity)4832 TEST(operation, lcc2sp_to_lcc1sp_invalid_eccentricity) {
4833 auto projCRS = ProjectedCRS::create(
4834 PropertyMap(), geographicCRSInvalidEccentricity(),
4835 Conversion::createLambertConicConformal_2SP(
4836 PropertyMap(), Angle(46.5), Angle(3), Angle(44), Angle(49),
4837 Length(700000), Length(6600000)),
4838 CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
4839 auto targetConv = projCRS->derivingConversion()->convertToOtherMethod(
4840 EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
4841 EXPECT_FALSE(targetConv != nullptr);
4842 }
4843
4844 // ---------------------------------------------------------------------------
4845
TEST(operation,three_param_equivalent_to_seven_param)4846 TEST(operation, three_param_equivalent_to_seven_param) {
4847
4848 auto three_param = Transformation::createGeocentricTranslations(
4849 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4850 2.0, 3.0, {});
4851
4852 auto seven_param_pv = Transformation::createPositionVector(
4853 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4854 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, {});
4855
4856 auto seven_param_cf = Transformation::createCoordinateFrameRotation(
4857 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4858 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, {});
4859
4860 auto seven_param_non_eq = Transformation::createPositionVector(
4861 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4862 2.0, 3.0, 1.0, 0.0, 0.0, 0.0, {});
4863
4864 EXPECT_TRUE(three_param->isEquivalentTo(
4865 seven_param_pv.get(), IComparable::Criterion::EQUIVALENT));
4866
4867 EXPECT_TRUE(three_param->isEquivalentTo(
4868 seven_param_cf.get(), IComparable::Criterion::EQUIVALENT));
4869
4870 EXPECT_TRUE(seven_param_cf->isEquivalentTo(
4871 three_param.get(), IComparable::Criterion::EQUIVALENT));
4872
4873 EXPECT_TRUE(seven_param_pv->isEquivalentTo(
4874 three_param.get(), IComparable::Criterion::EQUIVALENT));
4875
4876 EXPECT_FALSE(three_param->isEquivalentTo(
4877 seven_param_non_eq.get(), IComparable::Criterion::EQUIVALENT));
4878 }
4879
4880 // ---------------------------------------------------------------------------
4881
TEST(operation,position_vector_equivalent_coordinate_frame)4882 TEST(operation, position_vector_equivalent_coordinate_frame) {
4883
4884 auto pv = Transformation::createPositionVector(
4885 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4886 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, {});
4887
4888 auto cf = Transformation::createCoordinateFrameRotation(
4889 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4890 2.0, 3.0, -4 + 1e-11, -5.0, -6.0, 7.0, {});
4891
4892 auto cf_non_eq = Transformation::createCoordinateFrameRotation(
4893 PropertyMap(), GeographicCRS::EPSG_4269, GeographicCRS::EPSG_4326, 1.0,
4894 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, {});
4895
4896 EXPECT_TRUE(
4897 pv->isEquivalentTo(cf.get(), IComparable::Criterion::EQUIVALENT));
4898
4899 EXPECT_TRUE(
4900 cf->isEquivalentTo(pv.get(), IComparable::Criterion::EQUIVALENT));
4901
4902 EXPECT_FALSE(pv->isEquivalentTo(cf_non_eq.get(),
4903 IComparable::Criterion::EQUIVALENT));
4904 }
4905
4906 // ---------------------------------------------------------------------------
4907
TEST(operation,conversion_missing_parameter)4908 TEST(operation, conversion_missing_parameter) {
4909
4910 auto wkt1 = "PROJCS[\"NAD83(CSRS98) / UTM zone 20N (deprecated)\","
4911 " GEOGCS[\"NAD83(CSRS98)\","
4912 " DATUM[\"NAD83_Canadian_Spatial_Reference_System\","
4913 " SPHEROID[\"GRS 1980\",6378137,298.257222101,"
4914 " AUTHORITY[\"EPSG\",\"7019\"]],"
4915 " AUTHORITY[\"EPSG\",\"6140\"]],"
4916 " PRIMEM[\"Greenwich\",0,"
4917 " AUTHORITY[\"EPSG\",\"8901\"]],"
4918 " UNIT[\"degree\",0.0174532925199433,"
4919 " AUTHORITY[\"EPSG\",\"9108\"]],"
4920 " AUTHORITY[\"EPSG\",\"4140\"]],"
4921 " PROJECTION[\"Transverse_Mercator\"],"
4922 " PARAMETER[\"latitude_of_origin\",0],"
4923 " PARAMETER[\"central_meridian\",-63],"
4924 " PARAMETER[\"scale_factor\",0.9996],"
4925 " PARAMETER[\"false_easting\",500000],"
4926 " UNIT[\"metre\",1,"
4927 " AUTHORITY[\"EPSG\",\"9001\"]],"
4928 " AXIS[\"Easting\",EAST],"
4929 " AXIS[\"Northing\",NORTH],"
4930 " AUTHORITY[\"EPSG\",\"2038\"]]";
4931 auto obj1 = WKTParser().createFromWKT(wkt1);
4932 auto crs1 = nn_dynamic_pointer_cast<ProjectedCRS>(obj1);
4933 ASSERT_TRUE(crs1 != nullptr);
4934
4935 // Difference with wkt1: latitude_of_origin missing, but false_northing
4936 // added to 0
4937 auto wkt2 = "PROJCS[\"NAD83(CSRS98) / UTM zone 20N (deprecated)\","
4938 " GEOGCS[\"NAD83(CSRS98)\","
4939 " DATUM[\"NAD83_Canadian_Spatial_Reference_System\","
4940 " SPHEROID[\"GRS 1980\",6378137,298.257222101,"
4941 " AUTHORITY[\"EPSG\",\"7019\"]],"
4942 " AUTHORITY[\"EPSG\",\"6140\"]],"
4943 " PRIMEM[\"Greenwich\",0,"
4944 " AUTHORITY[\"EPSG\",\"8901\"]],"
4945 " UNIT[\"degree\",0.0174532925199433,"
4946 " AUTHORITY[\"EPSG\",\"9108\"]],"
4947 " AUTHORITY[\"EPSG\",\"4140\"]],"
4948 " PROJECTION[\"Transverse_Mercator\"],"
4949 " PARAMETER[\"central_meridian\",-63],"
4950 " PARAMETER[\"scale_factor\",0.9996],"
4951 " PARAMETER[\"false_easting\",500000],"
4952 " PARAMETER[\"false_northing\",0],"
4953 " UNIT[\"metre\",1,"
4954 " AUTHORITY[\"EPSG\",\"9001\"]],"
4955 " AXIS[\"Easting\",EAST],"
4956 " AXIS[\"Northing\",NORTH],"
4957 " AUTHORITY[\"EPSG\",\"2038\"]]";
4958 auto obj2 = WKTParser().createFromWKT(wkt2);
4959 auto crs2 = nn_dynamic_pointer_cast<ProjectedCRS>(obj2);
4960 ASSERT_TRUE(crs2 != nullptr);
4961
4962 // Difference with wkt1: false_northing added to 0
4963 auto wkt3 = "PROJCS[\"NAD83(CSRS98) / UTM zone 20N (deprecated)\","
4964 " GEOGCS[\"NAD83(CSRS98)\","
4965 " DATUM[\"NAD83_Canadian_Spatial_Reference_System\","
4966 " SPHEROID[\"GRS 1980\",6378137,298.257222101,"
4967 " AUTHORITY[\"EPSG\",\"7019\"]],"
4968 " AUTHORITY[\"EPSG\",\"6140\"]],"
4969 " PRIMEM[\"Greenwich\",0,"
4970 " AUTHORITY[\"EPSG\",\"8901\"]],"
4971 " UNIT[\"degree\",0.0174532925199433,"
4972 " AUTHORITY[\"EPSG\",\"9108\"]],"
4973 " AUTHORITY[\"EPSG\",\"4140\"]],"
4974 " PROJECTION[\"Transverse_Mercator\"],"
4975 " PARAMETER[\"latitude_of_origin\",0],"
4976 " PARAMETER[\"central_meridian\",-63],"
4977 " PARAMETER[\"scale_factor\",0.9996],"
4978 " PARAMETER[\"false_easting\",500000],"
4979 " PARAMETER[\"false_northing\",0],"
4980 " UNIT[\"metre\",1,"
4981 " AUTHORITY[\"EPSG\",\"9001\"]],"
4982 " AXIS[\"Easting\",EAST],"
4983 " AXIS[\"Northing\",NORTH],"
4984 " AUTHORITY[\"EPSG\",\"2038\"]]";
4985 auto obj3 = WKTParser().createFromWKT(wkt3);
4986 auto crs3 = nn_dynamic_pointer_cast<ProjectedCRS>(obj3);
4987 ASSERT_TRUE(crs3 != nullptr);
4988
4989 // Difference with wkt1: UNKNOWN added to non-zero
4990 auto wkt4 = "PROJCS[\"NAD83(CSRS98) / UTM zone 20N (deprecated)\","
4991 " GEOGCS[\"NAD83(CSRS98)\","
4992 " DATUM[\"NAD83_Canadian_Spatial_Reference_System\","
4993 " SPHEROID[\"GRS 1980\",6378137,298.257222101,"
4994 " AUTHORITY[\"EPSG\",\"7019\"]],"
4995 " AUTHORITY[\"EPSG\",\"6140\"]],"
4996 " PRIMEM[\"Greenwich\",0,"
4997 " AUTHORITY[\"EPSG\",\"8901\"]],"
4998 " UNIT[\"degree\",0.0174532925199433,"
4999 " AUTHORITY[\"EPSG\",\"9108\"]],"
5000 " AUTHORITY[\"EPSG\",\"4140\"]],"
5001 " PROJECTION[\"Transverse_Mercator\"],"
5002 " PARAMETER[\"latitude_of_origin\",0],"
5003 " PARAMETER[\"central_meridian\",-63],"
5004 " PARAMETER[\"scale_factor\",0.9996],"
5005 " PARAMETER[\"false_easting\",500000],"
5006 " PARAMETER[\"false_northing\",0],"
5007 " PARAMETER[\"UNKNOWN\",13],"
5008 " UNIT[\"metre\",1,"
5009 " AUTHORITY[\"EPSG\",\"9001\"]],"
5010 " AXIS[\"Easting\",EAST],"
5011 " AXIS[\"Northing\",NORTH],"
5012 " AUTHORITY[\"EPSG\",\"2038\"]]";
5013 auto obj4 = WKTParser().createFromWKT(wkt4);
5014 auto crs4 = nn_dynamic_pointer_cast<ProjectedCRS>(obj4);
5015 ASSERT_TRUE(crs4 != nullptr);
5016
5017 // Difference with wkt1: latitude_of_origin missing, but false_northing
5018 // added to non-zero
5019 auto wkt5 = "PROJCS[\"NAD83(CSRS98) / UTM zone 20N (deprecated)\","
5020 " GEOGCS[\"NAD83(CSRS98)\","
5021 " DATUM[\"NAD83_Canadian_Spatial_Reference_System\","
5022 " SPHEROID[\"GRS 1980\",6378137,298.257222101,"
5023 " AUTHORITY[\"EPSG\",\"7019\"]],"
5024 " AUTHORITY[\"EPSG\",\"6140\"]],"
5025 " PRIMEM[\"Greenwich\",0,"
5026 " AUTHORITY[\"EPSG\",\"8901\"]],"
5027 " UNIT[\"degree\",0.0174532925199433,"
5028 " AUTHORITY[\"EPSG\",\"9108\"]],"
5029 " AUTHORITY[\"EPSG\",\"4140\"]],"
5030 " PROJECTION[\"Transverse_Mercator\"],"
5031 " PARAMETER[\"central_meridian\",-63],"
5032 " PARAMETER[\"scale_factor\",0.9996],"
5033 " PARAMETER[\"false_easting\",500000],"
5034 " PARAMETER[\"false_northing\",-99999],"
5035 " UNIT[\"metre\",1,"
5036 " AUTHORITY[\"EPSG\",\"9001\"]],"
5037 " AXIS[\"Easting\",EAST],"
5038 " AXIS[\"Northing\",NORTH],"
5039 " AUTHORITY[\"EPSG\",\"2038\"]]";
5040 auto obj5 = WKTParser().createFromWKT(wkt5);
5041 auto crs5 = nn_dynamic_pointer_cast<ProjectedCRS>(obj5);
5042 ASSERT_TRUE(crs5 != nullptr);
5043
5044 EXPECT_TRUE(
5045 crs1->isEquivalentTo(crs2.get(), IComparable::Criterion::EQUIVALENT));
5046 EXPECT_TRUE(
5047 crs2->isEquivalentTo(crs1.get(), IComparable::Criterion::EQUIVALENT));
5048 EXPECT_TRUE(
5049 crs1->isEquivalentTo(crs3.get(), IComparable::Criterion::EQUIVALENT));
5050 EXPECT_TRUE(
5051 crs3->isEquivalentTo(crs1.get(), IComparable::Criterion::EQUIVALENT));
5052 EXPECT_TRUE(
5053 crs2->isEquivalentTo(crs3.get(), IComparable::Criterion::EQUIVALENT));
5054 EXPECT_TRUE(
5055 crs3->isEquivalentTo(crs2.get(), IComparable::Criterion::EQUIVALENT));
5056
5057 EXPECT_FALSE(
5058 crs1->isEquivalentTo(crs4.get(), IComparable::Criterion::EQUIVALENT));
5059 EXPECT_FALSE(
5060 crs4->isEquivalentTo(crs1.get(), IComparable::Criterion::EQUIVALENT));
5061
5062 EXPECT_FALSE(
5063 crs1->isEquivalentTo(crs5.get(), IComparable::Criterion::EQUIVALENT));
5064 EXPECT_FALSE(
5065 crs5->isEquivalentTo(crs1.get(), IComparable::Criterion::EQUIVALENT));
5066 }
5067
5068 // ---------------------------------------------------------------------------
5069
TEST(operation,conversion_missing_parameter_scale)5070 TEST(operation, conversion_missing_parameter_scale) {
5071
5072 auto wkt1 = "PROJCS[\"test\",\n"
5073 " GEOGCS[\"WGS 84\",\n"
5074 " DATUM[\"WGS 1984\",\n"
5075 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
5076 " PRIMEM[\"Greenwich\",0],\n"
5077 " UNIT[\"degree\",0.0174532925199433]],\n"
5078 " PROJECTION[\"Mercator_1SP\"],\n"
5079 " PARAMETER[\"latitude_of_origin\",-1],\n"
5080 " PARAMETER[\"central_meridian\",2],\n"
5081 " PARAMETER[\"scale_factor\",1],\n"
5082 " PARAMETER[\"false_easting\",3],\n"
5083 " PARAMETER[\"false_northing\",4],\n"
5084 " UNIT[\"metre\",1]]";
5085
5086 auto obj1 = WKTParser().createFromWKT(wkt1);
5087 auto crs1 = nn_dynamic_pointer_cast<ProjectedCRS>(obj1);
5088 ASSERT_TRUE(crs1 != nullptr);
5089
5090 // Difference with wkt1: scale_factor missing
5091 auto wkt2 = "PROJCS[\"test\",\n"
5092 " GEOGCS[\"WGS 84\",\n"
5093 " DATUM[\"WGS 1984\",\n"
5094 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
5095 " PRIMEM[\"Greenwich\",0],\n"
5096 " UNIT[\"degree\",0.0174532925199433]],\n"
5097 " PROJECTION[\"Mercator_1SP\"],\n"
5098 " PARAMETER[\"latitude_of_origin\",-1],\n"
5099 " PARAMETER[\"central_meridian\",2],\n"
5100 " PARAMETER[\"false_easting\",3],\n"
5101 " PARAMETER[\"false_northing\",4],\n"
5102 " UNIT[\"metre\",1]]";
5103
5104 auto obj2 = WKTParser().createFromWKT(wkt2);
5105 auto crs2 = nn_dynamic_pointer_cast<ProjectedCRS>(obj2);
5106 ASSERT_TRUE(crs2 != nullptr);
5107
5108 // Difference with wkt1: scale_factor set to non-1
5109 auto wkt3 = "PROJCS[\"test\",\n"
5110 " GEOGCS[\"WGS 84\",\n"
5111 " DATUM[\"WGS 1984\",\n"
5112 " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
5113 " PRIMEM[\"Greenwich\",0],\n"
5114 " UNIT[\"degree\",0.0174532925199433]],\n"
5115 " PROJECTION[\"Mercator_1SP\"],\n"
5116 " PARAMETER[\"latitude_of_origin\",-1],\n"
5117 " PARAMETER[\"central_meridian\",2],\n"
5118 " PARAMETER[\"scale_factor\",-1],\n"
5119 " PARAMETER[\"false_easting\",3],\n"
5120 " PARAMETER[\"false_northing\",4],\n"
5121 " UNIT[\"metre\",1]]";
5122 auto obj3 = WKTParser().createFromWKT(wkt3);
5123 auto crs3 = nn_dynamic_pointer_cast<ProjectedCRS>(obj3);
5124 ASSERT_TRUE(crs3 != nullptr);
5125
5126 EXPECT_TRUE(
5127 crs1->isEquivalentTo(crs2.get(), IComparable::Criterion::EQUIVALENT));
5128 EXPECT_TRUE(
5129 crs2->isEquivalentTo(crs1.get(), IComparable::Criterion::EQUIVALENT));
5130
5131 EXPECT_FALSE(
5132 crs1->isEquivalentTo(crs3.get(), IComparable::Criterion::EQUIVALENT));
5133 EXPECT_FALSE(
5134 crs3->isEquivalentTo(crs1.get(), IComparable::Criterion::EQUIVALENT));
5135 EXPECT_FALSE(
5136 crs2->isEquivalentTo(crs3.get(), IComparable::Criterion::EQUIVALENT));
5137 EXPECT_FALSE(
5138 crs3->isEquivalentTo(crs2.get(), IComparable::Criterion::EQUIVALENT));
5139 }
5140
5141 // ---------------------------------------------------------------------------
5142
TEST(operation,hotine_oblique_mercator_variant_A_export_equivalent_modulo_360)5143 TEST(operation,
5144 hotine_oblique_mercator_variant_A_export_equivalent_modulo_360) {
5145 auto conv1 = Conversion::createHotineObliqueMercatorVariantA(
5146 PropertyMap(), Angle(1), Angle(2), Angle(-3), Angle(-4), Scale(5),
5147 Length(6), Length(7));
5148 auto conv2 = Conversion::createHotineObliqueMercatorVariantA(
5149 PropertyMap(), Angle(1), Angle(2), Angle(-3 + 360), Angle(-4 + 360),
5150 Scale(5), Length(6), Length(7));
5151
5152 EXPECT_TRUE(
5153 conv1->isEquivalentTo(conv2.get(), IComparable::Criterion::EQUIVALENT));
5154 }
5155
5156 // ---------------------------------------------------------------------------
5157
TEST(operation,createChangeVerticalUnit)5158 TEST(operation, createChangeVerticalUnit) {
5159 auto conv = Conversion::createChangeVerticalUnit(PropertyMap(), Scale(1));
5160 EXPECT_TRUE(conv->validateParameters().empty());
5161 }
5162
5163 // ---------------------------------------------------------------------------
5164
TEST(operation,createGeographicGeocentric)5165 TEST(operation, createGeographicGeocentric) {
5166 auto conv = Conversion::createGeographicGeocentric(PropertyMap());
5167 EXPECT_TRUE(conv->validateParameters().empty());
5168 }
5169
5170 // ---------------------------------------------------------------------------
5171
TEST(operation,validateParameters)5172 TEST(operation, validateParameters) {
5173 {
5174 auto conv = Conversion::create(
5175 PropertyMap(),
5176 PropertyMap().set(IdentifiedObject::NAME_KEY, "unknown"), {}, {});
5177 auto validation = conv->validateParameters();
5178 EXPECT_EQ(validation, std::list<std::string>{"Unknown method unknown"});
5179 }
5180
5181 {
5182 auto conv = Conversion::create(
5183 PropertyMap(), PropertyMap().set(IdentifiedObject::NAME_KEY,
5184 "change of vertical unit"),
5185 {}, {});
5186 auto validation = conv->validateParameters();
5187 auto expected = std::list<std::string>{
5188 "Method name change of vertical unit is equivalent to official "
5189 "Change of Vertical Unit but not strictly equal",
5190 "Cannot find expected parameter Unit conversion scalar"};
5191 EXPECT_EQ(validation, expected);
5192 }
5193
5194 {
5195 auto conv = Conversion::create(
5196 PropertyMap(), PropertyMap()
5197 .set(IdentifiedObject::NAME_KEY,
5198 EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT)
5199 .set(Identifier::CODESPACE_KEY, Identifier::EPSG)
5200 .set(Identifier::CODE_KEY, "1234"),
5201 {}, {});
5202 auto validation = conv->validateParameters();
5203 auto expected = std::list<std::string>{
5204 "Method of EPSG code 1234 does not match official code (1069)",
5205 "Cannot find expected parameter Unit conversion scalar"};
5206 EXPECT_EQ(validation, expected);
5207 }
5208
5209 {
5210 auto conv = Conversion::create(
5211 PropertyMap(),
5212 PropertyMap()
5213 .set(IdentifiedObject::NAME_KEY, "some fancy name")
5214 .set(Identifier::CODESPACE_KEY, Identifier::EPSG)
5215 .set(Identifier::CODE_KEY,
5216 EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT),
5217 {}, {});
5218 auto validation = conv->validateParameters();
5219 auto expected = std::list<std::string>{
5220 "Method name some fancy name, matched to Change of Vertical Unit, "
5221 "through its EPSG code has not an equivalent name",
5222 "Cannot find expected parameter Unit conversion scalar"};
5223 EXPECT_EQ(validation, expected);
5224 }
5225
5226 {
5227 auto conv = Conversion::create(
5228 PropertyMap(),
5229 PropertyMap().set(IdentifiedObject::NAME_KEY,
5230 EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT),
5231 {OperationParameter::create(PropertyMap().set(
5232 IdentifiedObject::NAME_KEY, "unit conversion scalar"))},
5233 {ParameterValue::create(Measure(1.0, UnitOfMeasure::SCALE_UNITY))});
5234 auto validation = conv->validateParameters();
5235 auto expected = std::list<std::string>{
5236 "Parameter name unit conversion scalar is equivalent to official "
5237 "Unit conversion scalar but not strictly equal"};
5238 EXPECT_EQ(validation, expected);
5239 }
5240
5241 {
5242 auto conv = Conversion::create(
5243 PropertyMap(),
5244 PropertyMap().set(IdentifiedObject::NAME_KEY,
5245 EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT),
5246 {OperationParameter::create(
5247 PropertyMap()
5248 .set(IdentifiedObject::NAME_KEY, "fancy name")
5249 .set(Identifier::CODESPACE_KEY, Identifier::EPSG)
5250 .set(Identifier::CODE_KEY,
5251 EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR))},
5252 {ParameterValue::create(Measure(1.0, UnitOfMeasure::SCALE_UNITY))});
5253 auto validation = conv->validateParameters();
5254 auto expected = std::list<std::string>{
5255 "Parameter name fancy name, matched to Unit conversion scalar, "
5256 "through its EPSG code has not an equivalent name"};
5257 EXPECT_EQ(validation, expected);
5258 }
5259
5260 {
5261 auto conv = Conversion::create(
5262 PropertyMap(),
5263 PropertyMap().set(IdentifiedObject::NAME_KEY,
5264 EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT),
5265 {OperationParameter::create(
5266 PropertyMap().set(IdentifiedObject::NAME_KEY, "extra param"))},
5267 {ParameterValue::create(Measure(1.0, UnitOfMeasure::SCALE_UNITY))});
5268 auto validation = conv->validateParameters();
5269 auto expected = std::list<std::string>{
5270 "Cannot find expected parameter Unit conversion scalar",
5271 "Parameter extra param found but not expected for this method"};
5272 EXPECT_EQ(validation, expected);
5273 }
5274 }
5275
5276 // ---------------------------------------------------------------------------
5277
TEST(operation,normalizeForVisualization)5278 TEST(operation, normalizeForVisualization) {
5279
5280 auto authFactory =
5281 AuthorityFactory::create(DatabaseContext::create(), "EPSG");
5282
5283 // Source(geographic) must be inverted
5284 {
5285 auto src = authFactory->createCoordinateReferenceSystem("4326");
5286 auto dst = authFactory->createCoordinateReferenceSystem("32631");
5287 auto op =
5288 CoordinateOperationFactory::create()->createOperation(src, dst);
5289 ASSERT_TRUE(op != nullptr);
5290 auto opNormalized = op->normalizeForVisualization();
5291 EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get()));
5292 EXPECT_EQ(opNormalized->exportToPROJString(
5293 PROJStringFormatter::create().get()),
5294 "+proj=pipeline "
5295 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
5296 "+step +proj=utm +zone=31 +ellps=WGS84");
5297 }
5298
5299 // Target(geographic) must be inverted
5300 {
5301 auto src = authFactory->createCoordinateReferenceSystem("32631");
5302 auto dst = authFactory->createCoordinateReferenceSystem("4326");
5303 auto op =
5304 CoordinateOperationFactory::create()->createOperation(src, dst);
5305 ASSERT_TRUE(op != nullptr);
5306 auto opNormalized = op->normalizeForVisualization();
5307 EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get()));
5308 EXPECT_EQ(opNormalized->exportToPROJString(
5309 PROJStringFormatter::create().get()),
5310 "+proj=pipeline "
5311 "+step +inv +proj=utm +zone=31 +ellps=WGS84 "
5312 "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
5313 }
5314
5315 // Source(geographic) and target(projected) must be inverted
5316 {
5317 auto src = authFactory->createCoordinateReferenceSystem("4326");
5318 auto dst = authFactory->createCoordinateReferenceSystem("3040");
5319 auto op =
5320 CoordinateOperationFactory::create()->createOperation(src, dst);
5321 ASSERT_TRUE(op != nullptr);
5322 auto opNormalized = op->normalizeForVisualization();
5323 EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get()));
5324 EXPECT_EQ(opNormalized->exportToPROJString(
5325 PROJStringFormatter::create().get()),
5326 "+proj=pipeline "
5327 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
5328 "+step +proj=utm +zone=28 +ellps=GRS80");
5329 }
5330
5331 // No inversion
5332 {
5333 auto src = authFactory->createCoordinateReferenceSystem("32631");
5334 auto dst = authFactory->createCoordinateReferenceSystem("32632");
5335 auto op =
5336 CoordinateOperationFactory::create()->createOperation(src, dst);
5337 ASSERT_TRUE(op != nullptr);
5338 auto opNormalized = op->normalizeForVisualization();
5339 EXPECT_TRUE(opNormalized->_isEquivalentTo(op.get()));
5340 }
5341
5342 // Source(compoundCRS) and target(geographic 3D) must be inverted
5343 {
5344 auto ctxt =
5345 CoordinateOperationContext::create(authFactory, nullptr, 0.0);
5346 ctxt->setUsePROJAlternativeGridNames(false);
5347 auto src = CompoundCRS::create(
5348 PropertyMap(),
5349 std::vector<CRSNNPtr>{
5350 authFactory->createCoordinateReferenceSystem("4326"),
5351 // EGM2008 height
5352 authFactory->createCoordinateReferenceSystem("3855")});
5353 auto list = CoordinateOperationFactory::create()->createOperations(
5354 src,
5355 authFactory->createCoordinateReferenceSystem("4979"), // WGS 84 3D
5356 ctxt);
5357 ASSERT_EQ(list.size(), 3U);
5358 auto op = list[1];
5359 auto opNormalized = op->normalizeForVisualization();
5360 EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get()));
5361 EXPECT_EQ(
5362 opNormalized->exportToPROJString(
5363 PROJStringFormatter::create(
5364 PROJStringFormatter::Convention::PROJ_5,
5365 authFactory->databaseContext())
5366 .get()),
5367 "+proj=pipeline "
5368 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
5369 "+step +proj=vgridshift +grids=us_nga_egm08_25.tif +multiplier=1 "
5370 "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
5371 }
5372
5373 // Source(boundCRS) and target(geographic) must be inverted
5374 {
5375 auto src = BoundCRS::createFromTOWGS84(
5376 GeographicCRS::EPSG_4269, std::vector<double>{1, 2, 3, 4, 5, 6, 7});
5377 auto dst = authFactory->createCoordinateReferenceSystem("4326");
5378 auto op =
5379 CoordinateOperationFactory::create()->createOperation(src, dst);
5380 ASSERT_TRUE(op != nullptr);
5381 auto opNormalized = op->normalizeForVisualization();
5382 EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get()));
5383 EXPECT_EQ(opNormalized->exportToPROJString(
5384 PROJStringFormatter::create().get()),
5385 "+proj=pipeline "
5386 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
5387 "+step +proj=push +v_3 "
5388 "+step +proj=cart +ellps=GRS80 "
5389 "+step +proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 +s=7 "
5390 "+convention=position_vector "
5391 "+step +inv +proj=cart +ellps=WGS84 "
5392 "+step +proj=pop +v_3 "
5393 "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
5394 }
5395 }
5396
5397 // ---------------------------------------------------------------------------
5398
TEST(operation,export_of_Geographic3D_to_GravityRelatedHeight_gtx_unknown_grid)5399 TEST(operation,
5400 export_of_Geographic3D_to_GravityRelatedHeight_gtx_unknown_grid) {
5401
5402 auto wkt =
5403 "COORDINATEOPERATION[\"bla\",\n"
5404 " SOURCECRS[\n"
5405 " GEOGCRS[\"ETRS89\",\n"
5406 " DATUM[\"European Terrestrial Reference System 1989\",\n"
5407 " ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n"
5408 " LENGTHUNIT[\"metre\",1]]],\n"
5409 " PRIMEM[\"Greenwich\",0,\n"
5410 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
5411 " CS[ellipsoidal,3],\n"
5412 " AXIS[\"geodetic latitude (Lat)\",north,\n"
5413 " ORDER[1],\n"
5414 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
5415 " AXIS[\"geodetic longitude (Lon)\",east,\n"
5416 " ORDER[2],\n"
5417 " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
5418 " AXIS[\"ellipsoidal height (h)\",up,\n"
5419 " ORDER[3],\n"
5420 " LENGTHUNIT[\"metre\",1]],\n"
5421 " ID[\"EPSG\",4937]]],\n"
5422 " TARGETCRS[\n"
5423 " VERTCRS[\"bar\",\n"
5424 " VDATUM[\"bar\"],\n"
5425 " CS[vertical,1],\n"
5426 " AXIS[\"gravity-related height (H)\",up,\n"
5427 " LENGTHUNIT[\"metre\",1]]]],\n"
5428 " METHOD[\"Geographic3D to GravityRelatedHeight (gtx)\",\n"
5429 " ID[\"EPSG\",9665]],\n"
5430 " PARAMETERFILE[\"Geoid (height correction) model "
5431 "file\",\"foo.gtx\"]]";
5432
5433 auto obj = WKTParser().createFromWKT(wkt);
5434 auto crs = nn_dynamic_pointer_cast<Transformation>(obj);
5435 ASSERT_TRUE(crs != nullptr);
5436 // Test that even if the .gtx file is unknown, we export in the correct
5437 // direction
5438 EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
5439 "+proj=pipeline "
5440 "+step +proj=axisswap +order=2,1 "
5441 "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
5442 "+step +inv +proj=vgridshift +grids=foo.gtx +multiplier=1 "
5443 "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
5444 "+step +proj=axisswap +order=2,1");
5445 }
5446