co-maps/libs/geometry/geometry_tests/circle_on_earth_tests.cpp
2025-11-22 13:58:55 +01:00

73 lines
2.4 KiB
C++

#include "testing/testing.hpp"
#include "geometry/circle_on_earth.hpp"
#include "geometry/distance_on_sphere.hpp"
#include "geometry/mercator.hpp"
#include "geometry/point2d.hpp"
#include "base/math.hpp"
#include <sstream>
#include <vector>
namespace
{
void TestGeometryAlmostEqualAbs(std::vector<m2::PointD> const & geometry, std::vector<m2::PointD> const & answer,
double eps)
{
TEST_EQUAL(geometry.size(), answer.size(), ());
for (size_t i = 0; i < geometry.size(); ++i)
TEST_ALMOST_EQUAL_ABS(geometry[i], answer[i], eps, ());
}
void TestGeometryAlmostEqualMeters(std::vector<m2::PointD> const & geometry, std::vector<m2::PointD> const & answer,
double epsMeters)
{
TEST_EQUAL(geometry.size(), answer.size(), ());
for (size_t i = 0; i < geometry.size(); ++i)
TEST_LESS(mercator::DistanceOnEarth(geometry[i], answer[i]), epsMeters, ());
}
} // namespace
UNIT_TEST(CircleOnEarth)
{
ms::LatLon const center(90.0 /* lat */, 0.0 /* lon */);
double const radiusMeters = 2.0 * math::pi * ms::kEarthRadiusMeters / 4.0;
auto const geometry = ms::CreateCircleGeometryOnEarth(center, radiusMeters, 90.0 /* angleStepDegree */);
std::vector<m2::PointD> const result = {mercator::FromLatLon(0.0, 0.0), mercator::FromLatLon(0.0, 90.0),
mercator::FromLatLon(0.0, 180.0), mercator::FromLatLon(0.0, -90.0)};
TestGeometryAlmostEqualAbs(geometry, result, 1e-9 /* eps */);
}
UNIT_TEST(CircleOnEarthEquator)
{
ms::LatLon const center(0.0 /* lat */, 0.0 /* lon */);
auto const point = mercator::FromLatLon(center);
auto constexpr kRadiusMeters = 10000.0;
double const kRadiusMercator = mercator::MetersToMercator(kRadiusMeters);
auto constexpr kAngleStepDegree = 30.0;
auto constexpr kN = static_cast<size_t>(360.0 / kAngleStepDegree);
std::vector<m2::PointD> result;
result.reserve(kN);
auto constexpr kStepRad = math::DegToRad(kAngleStepDegree);
double angleSumRad = 0.0;
double angleRad = -math::pi2;
while (angleSumRad < 2 * math::pi)
{
angleSumRad += kStepRad;
result.emplace_back(point.x + kRadiusMercator * cos(angleRad), point.y + kRadiusMercator * sin(angleRad));
angleRad += kStepRad;
if (angleRad > 2 * math::pi)
angleRad -= 2 * math::pi;
}
auto const geometry = ms::CreateCircleGeometryOnEarth(center, kRadiusMeters, kAngleStepDegree);
TestGeometryAlmostEqualMeters(geometry, result, 20.0 /* epsMeters */);
}