fix: relax half period checks in normalization of longitudes

This commit is contained in:
Vissarion Fisikopoulos 2024-12-17 17:16:11 +02:00
parent 82ef735271
commit 0091b636a1
5 changed files with 42 additions and 29 deletions

View File

@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2020, Oracle and/or its affiliates.
// Copyright (c) 2015-2025, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -123,7 +124,7 @@ struct assign_loop<1, DimensionCount>
template <typename PointIn, typename PointOut, bool IsEquatorial = true>
struct normalize_point
{
static inline void apply(PointIn const& point_in, PointOut& point_out)
static inline void apply(PointIn const& point_in, PointOut& point_out, bool exact = true)
{
using in_coordinate_type = coordinate_type_t<PointIn>;
@ -135,7 +136,7 @@ struct normalize_point
typename geometry::detail::cs_angular_units<PointIn>::type,
IsEquatorial,
in_coordinate_type
>(longitude, latitude);
>(longitude, latitude, exact);
assign_loop
<
@ -221,13 +222,13 @@ struct cartesian_box
struct spherical_point
{
template <typename PointIn, typename PointOut>
static inline void apply(PointIn const& point_in, PointOut& point_out)
static inline void apply(PointIn const& point_in, PointOut& point_out, bool exact = true)
{
detail::normalize_point
<
PointIn, PointOut,
(! std::is_same<cs_tag_t<PointIn>, spherical_polar_tag>::value)
>::apply(point_in, point_out);
>::apply(point_in, point_out, exact);
}
};

View File

@ -5,11 +5,12 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2025.
// Modifications copyright (c) 2013-2025, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -71,9 +72,10 @@ private:
typedef typename helper_geometry<Point2>::type helper_point_type2;
helper_point_type1 point1_normalized;
strategy::normalize::spherical_point::apply(point1, point1_normalized);
bool const exact_normalized = false;
strategy::normalize::spherical_point::apply(point1, point1_normalized, exact_normalized);
helper_point_type2 point2_normalized;
strategy::normalize::spherical_point::apply(point2, point2_normalized);
strategy::normalize::spherical_point::apply(point2, point2_normalized, exact_normalized);
return point_point_generic
<

View File

@ -2,8 +2,9 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2015-2022, Oracle and/or its affiliates.
// Copyright (c) 2015-2025, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
@ -236,17 +237,22 @@ protected:
}
public:
static inline void apply(CoordinateType& longitude)
static inline void apply(CoordinateType& longitude, bool exact = true)
{
// normalize longitude
if (math::equals(math::abs(longitude), constants::half_period()))
CoordinateType const epsilon = std::numeric_limits<float>::epsilon();
static constexpr bool is_integer = std::numeric_limits<CoordinateType>::is_integer;
if (exact || is_integer ? math::equals(math::abs(longitude), constants::half_period())
: math::abs(math::abs(longitude) - constants::half_period()) <= epsilon)
{
longitude = constants::half_period();
}
else if (longitude > constants::half_period())
{
longitude = normalize_up(longitude);
if (math::equals(longitude, -constants::half_period()))
if (exact || is_integer ? math::equals(longitude, -constants::half_period())
: math::abs(longitude + constants::half_period()) <= epsilon)
{
longitude = constants::half_period();
}
@ -259,7 +265,8 @@ public:
static inline void apply(CoordinateType& longitude,
CoordinateType& latitude,
bool normalize_poles = true)
bool normalize_poles = true,
bool exact = true)
{
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
@ -288,7 +295,7 @@ public:
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
// normalize longitude
apply(longitude);
apply(longitude, exact);
// finally normalize poles
if (normalize_poles)
@ -353,22 +360,24 @@ inline void normalize_angle_cond(CoordinateType& angle)
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
CoordinateType& latitude)
CoordinateType& latitude,
bool exact = true)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType
>::apply(longitude, latitude);
>::apply(longitude, latitude, true, exact);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
CoordinateType& latitude)
CoordinateType& latitude,
bool exact = true)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude, latitude);
>::apply(longitude, latitude, true, exact);
}
/*!
@ -381,12 +390,12 @@ inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_longitude(CoordinateType& longitude)
inline void normalize_longitude(CoordinateType& longitude, bool exact = true)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType
>::apply(longitude);
>::apply(longitude, exact);
}
/*!
@ -400,7 +409,7 @@ inline void normalize_longitude(CoordinateType& longitude)
template <typename Units, typename CoordinateType>
inline void normalize_azimuth(CoordinateType& angle)
{
normalize_longitude<Units, CoordinateType>(angle);
math::normalize_longitude<Units, CoordinateType>(angle, true);
}
/*!
@ -435,7 +444,7 @@ inline CoordinateType longitude_distance_signed(CoordinateType const& longitude1
CoordinateType const& longitude2)
{
CoordinateType diff = longitude2 - longitude1;
math::normalize_longitude<Units, CoordinateType>(diff);
math::normalize_longitude<Units, CoordinateType>(diff, true);
return diff;
}

View File

@ -24,7 +24,7 @@ void test_radian()
boost::geometry::strategies::relate::geographic<> wgs84(sph_wgs84);
test_geometry<ls, mls>(
"LINESTRING(0 0, -3.14159265358979 0)",
"LINESTRING(0 0,-3.14159265358979 0)",
"MULTILINESTRING((-2.1467549799530232 -0.12217304763960295,"
"-2.5481807079117185 -0.90757121103705041,"
"-2.6529004630313784 0.85521133347722067,"

View File

@ -1,10 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Copyright (c) 2014-2025, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
#include <iostream>
@ -1160,7 +1161,7 @@ BOOST_AUTO_TEST_CASE( test_difference_ml_ml_degenerate )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl << std::endl;
std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE"
std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE"
<< " (DEGENERATE) ***"
<< std::endl;
std::cout << std::endl;
@ -1247,7 +1248,7 @@ BOOST_AUTO_TEST_CASE( test_difference_ml_ml_spikes )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl << std::endl;
std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE"
std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE"
<< " (WITH SPIKES) ***"
<< std::endl;
std::cout << std::endl;
@ -1452,7 +1453,7 @@ BOOST_AUTO_TEST_CASE( test_difference_ls_mls_geo_rad )
bg::srs::spheroid<double> sph_wgs84(6378137.0, 6356752.3142451793);
boost::geometry::strategy::intersection::geographic_segments<> wgs84(sph_wgs84);
ls g1 = from_wkt<ls>("LINESTRING(0 0, -3.14159265358979 0)");
ls g1 = from_wkt<ls>("LINESTRING(0 0,-3.14159265358979 0)");
mls g2 = from_wkt<mls>("MULTILINESTRING((-2.1467549799530232 -0.12217304763960295,"
"-2.5481807079117185 -0.90757121103705041,"
"-2.6529004630313784 0.85521133347722067,"