/****************************************************************************** * * Project: PROJ * Purpose: Test TIN shift * Author: Even Rouault * ****************************************************************************** * Copyright (c) 2020, Even Rouault * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "gtest_include.h" #define PROJ_COMPILATION #define TINSHIFT_NAMESPACE TestTINShift #include "transformations/tinshift.hpp" using namespace TINSHIFT_NAMESPACE; namespace { static json getMinValidContent() { json j; j["file_type"] = "triangulation_file"; j["format_version"] = "1.0"; j["input_crs"] = "EPSG:2393"; j["output_crs"] = "EPSG:3067"; j["transformed_components"] = {"horizontal"}; j["vertices_columns"] = {"source_x", "source_y", "target_x", "target_y"}; j["triangles_columns"] = {"idx_vertex1", "idx_vertex2", "idx_vertex3"}; j["vertices"] = {{0, 0, 101, 101}, {0, 1, 100, 101}, {1, 1, 100, 100}}; j["triangles"] = {{0, 1, 2}}; return j; } // --------------------------------------------------------------------------- TEST(tinshift, basic) { EXPECT_THROW(TINShiftFile::parse("foo"), ParsingException); EXPECT_THROW(TINShiftFile::parse("null"), ParsingException); EXPECT_THROW(TINShiftFile::parse("{}"), ParsingException); const auto jMinValid(getMinValidContent()); { auto f = TINShiftFile::parse(jMinValid.dump()); EXPECT_EQ(f->fileType(), "triangulation_file"); EXPECT_EQ(f->formatVersion(), "1.0"); EXPECT_EQ(f->inputCRS(), "EPSG:2393"); EXPECT_EQ(f->outputCRS(), "EPSG:3067"); EXPECT_EQ(f->fallbackStrategy(), FALLBACK_NONE); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_FALSE(eval.forward(-0.1, 0.0, 1000.0, x_out, y_out, z_out)); EXPECT_TRUE(eval.forward(0.0, 0.0, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 101.0); EXPECT_EQ(y_out, 101.0); EXPECT_EQ(z_out, 1000.0); EXPECT_TRUE(eval.forward(0.0, 1.0, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 100.0); EXPECT_EQ(y_out, 101.0); EXPECT_EQ(z_out, 1000.0); EXPECT_TRUE(eval.forward(1.0, 1.0, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 100.0); EXPECT_EQ(y_out, 100.0); EXPECT_EQ(z_out, 1000.0); EXPECT_TRUE(eval.forward(0.0, 0.5, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 100.5); EXPECT_EQ(y_out, 101.0); EXPECT_EQ(z_out, 1000.0); EXPECT_TRUE(eval.forward(0.5, 0.5, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 100.5); EXPECT_EQ(y_out, 100.5); EXPECT_EQ(z_out, 1000.0); EXPECT_TRUE(eval.forward(0.5, 0.75, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 100.25); EXPECT_EQ(y_out, 100.5); EXPECT_EQ(z_out, 1000.0); EXPECT_TRUE(eval.inverse(100.25, 100.5, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.5); EXPECT_EQ(y_out, 0.75); EXPECT_EQ(z_out, 1000.0); } // Vertical only, through source_z / target_z { auto j(jMinValid); j["transformed_components"] = {"vertical"}; j["vertices_columns"] = {"source_x", "source_y", "source_z", "target_z"}; j["triangles_columns"] = {"idx_vertex1", "idx_vertex2", "idx_vertex3"}; j["vertices"] = { {0, 0, 10.5, 10.6}, {0, 1, 15.0, 15.2}, {1, 1, 17.5, 18.0}}; j["triangles"] = {{0, 1, 2}}; auto f = TINShiftFile::parse(j.dump()); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_TRUE(eval.forward(0.0, 0.0, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.0); EXPECT_EQ(y_out, 0.0); EXPECT_EQ(z_out, 1000.1); EXPECT_TRUE(eval.forward(0.5, 0.75, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.5); EXPECT_EQ(y_out, 0.75); EXPECT_EQ(z_out, 1000.325); EXPECT_TRUE(eval.inverse(0.5, 0.75, 1000.325, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.5); EXPECT_EQ(y_out, 0.75); EXPECT_EQ(z_out, 1000.0); } // Vertical only, through offset_z { auto j(jMinValid); j["transformed_components"] = {"vertical"}; j["vertices_columns"] = {"source_x", "source_y", "offset_z"}; j["triangles_columns"] = {"idx_vertex1", "idx_vertex2", "idx_vertex3"}; j["vertices"] = {{0, 0, 0.1}, {0, 1, 0.2}, {1, 1, 0.5}}; j["triangles"] = {{0, 1, 2}}; auto f = TINShiftFile::parse(j.dump()); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_TRUE(eval.forward(0.0, 0.0, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.0); EXPECT_EQ(y_out, 0.0); EXPECT_EQ(z_out, 1000.1); EXPECT_TRUE(eval.forward(0.5, 0.75, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.5); EXPECT_EQ(y_out, 0.75); EXPECT_EQ(z_out, 1000.325); EXPECT_TRUE(eval.inverse(0.5, 0.75, 1000.325, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.5); EXPECT_EQ(y_out, 0.75); EXPECT_EQ(z_out, 1000.0); } // Horizontal + vertical { auto j(jMinValid); j["transformed_components"] = {"horizontal", "vertical"}; j["vertices_columns"] = {"source_x", "source_y", "target_x", "target_y", "offset_z"}; j["triangles_columns"] = {"idx_vertex1", "idx_vertex2", "idx_vertex3"}; j["vertices"] = {{0, 0, 101, 101, 0.1}, {0, 1, 100, 101, 0.2}, {1, 1, 100, 100, 0.5}}; j["triangles"] = {{0, 1, 2}}; auto f = TINShiftFile::parse(j.dump()); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_TRUE(eval.forward(0.0, 0.0, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 101.0); EXPECT_EQ(y_out, 101.0); EXPECT_EQ(z_out, 1000.1); EXPECT_TRUE(eval.forward(0.5, 0.75, 1000.0, x_out, y_out, z_out)); EXPECT_EQ(x_out, 100.25); EXPECT_EQ(y_out, 100.5); EXPECT_EQ(z_out, 1000.325); EXPECT_TRUE(eval.inverse(100.25, 100.5, 1000.325, x_out, y_out, z_out)); EXPECT_EQ(x_out, 0.5); EXPECT_EQ(y_out, 0.75); EXPECT_EQ(z_out, 1000.0); } // invalid fallback_strategy field with 1.0 version { auto j(jMinValid); j["fallback_strategy"] = "none"; EXPECT_THROW(TINShiftFile::parse(j.dump()), ParsingException); } // invalid fallback_strategy field with 1.1 version { auto j(jMinValid); j["format_version"] = "1.1"; j["fallback_strategy"] = "invalid"; EXPECT_THROW(TINShiftFile::parse(j.dump()), ParsingException); } // fail with no triangles and fallback nearest_side { auto j(jMinValid); j["format_version"] = "1.1"; j["fallback_strategy"] = "nearest_side"; j["triangles"] = json::array(); // empty auto f = TINShiftFile::parse(j.dump()); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_FALSE(eval.forward(1.0, 1.0, 1.0, x_out, y_out, z_out)); } // fail with only degenerate triangles (one size is zero length) and // fallback nearest_side { auto j(jMinValid); j["format_version"] = "1.1"; j["fallback_strategy"] = "nearest_side"; j["vertices"] = {{0, 0, 101, 101}, {0, 1, 100, 101}, {0, 1, 100, 100}}; auto f = TINShiftFile::parse(j.dump()); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_FALSE(eval.forward(1.0, 1.0, 1.0, x_out, y_out, z_out)); } // fail with only degenerate triangles (two angles are 0°) and fallback // nearest_side { auto j(jMinValid); j["format_version"] = "1.1"; j["fallback_strategy"] = "nearest_side"; j["vertices"] = { {0, 0, 101, 101}, {0, 0.5, 100, 101}, {0, 1, 100, 100}}; auto f = TINShiftFile::parse(j.dump()); auto eval = Evaluator(std::move(f)); double x_out = 0; double y_out = 0; double z_out = 0; EXPECT_FALSE(eval.forward(1.0, 1.0, 1.0, x_out, y_out, z_out)); } } } // namespace