Files
openstreetmap-osm2pgsql/tests/test-geom-transform.cpp
2025-06-26 12:03:29 +02:00

256 lines
8.4 KiB
C++

/**
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This file is part of osm2pgsql (https://osm2pgsql.org/).
*
* Copyright (C) 2006-2025 by the osm2pgsql developer community.
* For a full list of authors see the git log.
*/
#include <catch.hpp>
#include "geom-functions.hpp"
#include "geom-output.hpp"
#include "geom.hpp"
#include "projection.hpp"
#include "reprojection.hpp"
namespace {
void check(geom::point_t a, geom::point_t b)
{
REQUIRE(a.x() == Approx(b.x()));
REQUIRE(a.y() == Approx(b.y()));
}
} // anonymous namespace
double const X55 = 612257.1993630046; // lon 5.5
double const Y44 = 490287.90003313165; // lat 4.4
double const X33 = 367354.31961780274; // lon 3.3
double const Y22 = 244963.0806270098; // lat 2.2
double const X0 = 0; // lon 0.0
double const Y0 = 0; // lat 0.0
double const X1 = 111319.49079327357; // lon 1.0
double const Y1 = 111325.14286638486; // lat 1.0
double const X01 = 11131.949079327358; // lon 0.1
double const Y01 = 11131.954730972562; // lat 0.1
double const X09 = 100187.54171394622; // lon 0.9
double const Y09 = 100191.66201561989; // lat 0.9
TEST_CASE("Transform geom::null_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t const geom{};
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_null());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
}
TEST_CASE("Transform geom::point_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t const geom{geom::point_t{5.5, 4.4}};
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_point());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
check(result.get<geom::point_t>(),
geom::point_t{612257.1993630046, 490287.90003313165});
}
TEST_CASE("Transform geom::linestring_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t const geom{geom::linestring_t{{5.5, 4.4}, {3.3, 2.2}}};
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_linestring());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
auto const &r = result.get<geom::linestring_t>();
check(r[0], geom::point_t{X55, Y44});
check(r[1], geom::point_t{X33, Y22});
}
TEST_CASE("Transform geom::polygon_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t geom{
geom::polygon_t{geom::ring_t{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}}};
geom.get<geom::polygon_t>().add_inner_ring(geom::ring_t{
{0.1, 0.1}, {0.1, 0.9}, {0.9, 0.9}, {0.9, 0.1}, {0.1, 0.1}});
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_polygon());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
auto const &polygon = result.get<geom::polygon_t>();
auto const &outer = polygon.outer();
REQUIRE(outer.size() == 5);
check(outer[0], geom::point_t{X0, Y0});
check(outer[1], geom::point_t{X0, Y1});
check(outer[2], geom::point_t{X1, Y1});
check(outer[3], geom::point_t{X1, Y0});
check(outer[4], geom::point_t{X0, Y0});
REQUIRE(polygon.inners().size() == 1);
auto const &inner = polygon.inners()[0];
REQUIRE(inner.size() == 5);
check(inner[0], geom::point_t{X01, Y01});
check(inner[1], geom::point_t{X01, Y09});
check(inner[2], geom::point_t{X09, Y09});
check(inner[3], geom::point_t{X09, Y01});
check(inner[4], geom::point_t{X01, Y01});
}
TEST_CASE("Transform geom::multipoint_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t geom{geom::multipoint_t{}};
auto &mp = geom.get<geom::multipoint_t>();
mp.add_geometry({5.5, 4.4});
mp.add_geometry({3.3, 2.2});
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_multipoint());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
auto const &rmp = result.get<geom::multipoint_t>();
REQUIRE(rmp.num_geometries() == 2);
check(rmp[0], geom::point_t{X55, Y44});
check(rmp[1], geom::point_t{X33, Y22});
}
TEST_CASE("Transform geom::multilinestring_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t geom{geom::multilinestring_t{}};
auto &ml = geom.get<geom::multilinestring_t>();
ml.add_geometry(geom::linestring_t{{0, 0}, {5.5, 4.4}});
ml.add_geometry(geom::linestring_t{{0, 0}, {3.3, 2.2}});
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_multilinestring());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
auto const &rml = result.get<geom::multilinestring_t>();
REQUIRE(rml.num_geometries() == 2);
REQUIRE(rml[0].size() == 2);
check(rml[0][0], geom::point_t{X0, Y0});
check(rml[0][1], geom::point_t{X55, Y44});
REQUIRE(rml[1].size() == 2);
check(rml[1][0], geom::point_t{X0, Y0});
check(rml[1][1], geom::point_t{X33, Y22});
}
TEST_CASE("Transform geom::multipolygon_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t geom{geom::multipolygon_t{}};
auto &mp = geom.get<geom::multipolygon_t>();
mp.add_geometry(
geom::polygon_t{geom::ring_t{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}});
mp.add_geometry(geom::polygon_t{geom::ring_t{
{0.1, 0.1}, {0.1, 0.9}, {0.9, 0.9}, {0.9, 0.1}, {0.1, 0.1}}});
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_multipolygon());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
auto const &rmp = result.get<geom::multipolygon_t>();
REQUIRE(rmp.num_geometries() == 2);
auto const &first = rmp[0].outer();
REQUIRE(first.size() == 5);
check(first[0], geom::point_t{X0, Y0});
check(first[1], geom::point_t{X0, Y1});
check(first[2], geom::point_t{X1, Y1});
check(first[3], geom::point_t{X1, Y0});
check(first[4], geom::point_t{X0, Y0});
auto const &second = rmp[1].outer();
REQUIRE(second.size() == 5);
check(second[0], geom::point_t{X01, Y01});
check(second[1], geom::point_t{X01, Y09});
check(second[2], geom::point_t{X09, Y09});
check(second[3], geom::point_t{X09, Y01});
check(second[4], geom::point_t{X01, Y01});
}
TEST_CASE("Transform geom::collection_t", "[NoDB]")
{
auto const &reprojection =
reprojection::create_projection(PROJ_SPHERE_MERC);
geom::geometry_t geom{geom::collection_t{}};
auto &c = geom.get<geom::collection_t>();
c.add_geometry(geom::geometry_t{geom::point_t{5.5, 4.4}});
c.add_geometry(
geom::geometry_t{geom::linestring_t{{0.0, 0.0}, {5.5, 4.4}}});
c.add_geometry(geom::geometry_t{
geom::polygon_t{geom::ring_t{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}}});
{
geom::geometry_t mpgeom{geom::multipoint_t{}};
auto &mp = mpgeom.get<geom::multipoint_t>();
mp.add_geometry({5.5, 4.4});
mp.add_geometry({3.3, 2.2});
c.add_geometry(std::move(mpgeom));
}
auto const result = geom::transform(geom, *reprojection);
REQUIRE(result.is_collection());
REQUIRE(result.srid() == PROJ_SPHERE_MERC);
auto const &rc = result.get<geom::collection_t>();
REQUIRE(rc.num_geometries() == 4);
REQUIRE(rc[0].is_point());
REQUIRE(rc[0].srid() == 0);
auto const &rc0 = rc[0].get<geom::point_t>();
check(rc0, geom::point_t{X55, Y44});
REQUIRE(rc[1].is_linestring());
REQUIRE(rc[1].srid() == 0);
auto const &rc1 = rc[1].get<geom::linestring_t>();
REQUIRE(rc1.size() == 2);
check(rc1[0], geom::point_t{X0, Y0});
check(rc1[1], geom::point_t{X55, Y44});
REQUIRE(rc[2].is_polygon());
REQUIRE(rc[2].srid() == 0);
auto const &rc2 = rc[2].get<geom::polygon_t>();
REQUIRE(rc2.outer().size() == 5);
check(rc2.outer()[0], geom::point_t{X0, Y0});
check(rc2.outer()[1], geom::point_t{X0, Y1});
check(rc2.outer()[2], geom::point_t{X1, Y1});
check(rc2.outer()[3], geom::point_t{X1, Y0});
check(rc2.outer()[4], geom::point_t{X0, Y0});
REQUIRE(rc[3].is_multipoint());
REQUIRE(rc[3].srid() == 0);
auto const &rc3 = rc[3].get<geom::multipoint_t>();
REQUIRE(rc3.num_geometries() == 2);
check(rc3[0], geom::point_t{X55, Y44});
check(rc3[1], geom::point_t{X33, Y22});
}