mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
432 lines
15 KiB
C++
432 lines
15 KiB
C++
// Boost.Geometry
|
|
// Unit Test
|
|
|
|
// Copyright (c) 2021-2022, Oracle and/or its affiliates.
|
|
|
|
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
|
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
|
|
|
// Licensed under the Boost Software License version 1.0.
|
|
// http://www.boost.org/users/license.html
|
|
|
|
#ifndef BOOST_TEST_MODULE
|
|
#define BOOST_TEST_MODULE test_algorithms_closest_points_pointlike_linear
|
|
#endif
|
|
|
|
#include "common.hpp"
|
|
#include "empty_geometry.hpp"
|
|
#include <boost/geometry/algorithms/length.hpp>
|
|
|
|
namespace bg = boost::geometry;
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_point_segment(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "point/segment closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<Point, Segment, Segment>;
|
|
|
|
tester::apply("POINT(1 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
tester::apply("POINT(0 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(0 1,0 1)",
|
|
strategies);
|
|
|
|
//default strategies
|
|
tester::apply("POINT(1 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies, true, true);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename InputPoint, typename OutputPoint, typename Strategies>
|
|
void test_closest_points_point_segment_integral(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "point/segment closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using InputSegment = bg::model::segment<InputPoint>;
|
|
using OutputSegment = bg::model::segment<OutputPoint>;
|
|
using tester = test_geometry<InputPoint, InputSegment, OutputSegment>;
|
|
|
|
tester::apply("POINT(1 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
using tester_integral_output = test_geometry<InputPoint, InputSegment, InputSegment>;
|
|
|
|
tester_integral_output::apply("POINT(1 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(1 1,0 0)",
|
|
"SEGMENT(1 1,0 0)",
|
|
"SEGMENT(1 1,0 0)",
|
|
strategies);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_point_segment_diff_spheroid(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "point/segment closest_points tests non-default spheroid"
|
|
<< std::endl;
|
|
#endif
|
|
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<Point, Segment, Segment>;
|
|
|
|
tester::apply("POINT(1 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(1 1,0.311318 0.673915)",
|
|
strategies);
|
|
|
|
tester::apply("POINT(0 1)",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(0 1,0 1)",
|
|
strategies);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_point_linestring(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "point/linestring closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using Linestring = bg::model::linestring<Point>;
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<Point, Linestring, Segment>;
|
|
|
|
tester::apply("POINT(1 1)",
|
|
"LINESTRING(3 2, 1 3, 0 3, 0 1, 1 0, 0 0)",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
tester::apply("POINT(3 2)",
|
|
"LINESTRING(3 2, 1 3, 0 3, 0 1, 1 0, 0 0)",
|
|
"SEGMENT(3 2,3 2)",
|
|
strategies);
|
|
|
|
//default strategies
|
|
tester::apply("POINT(3 2)",
|
|
"LINESTRING(3 2, 1 3, 0 3, 0 1, 1 0, 0 0)",
|
|
"SEGMENT(3 2,3 2)",
|
|
strategies, true, true);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_point_multi_linestring(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "point/multi_linestring closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using Linestring = bg::model::linestring<Point>;
|
|
using MultiLinestring = bg::model::multi_linestring<Linestring>;
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<Point, MultiLinestring, Segment>;
|
|
|
|
tester::apply("POINT(1 1)",
|
|
"MULTILINESTRING((3 2, 1 3, 0 3, 0 1, 1 0, 0 0),(2 0,3 1,4 0))",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
tester::apply("POINT(1 3)",
|
|
"MULTILINESTRING((3 2, 1 3, 0 3, 0 1, 1 0, 0 0),(2 0,3 1,4 0))",
|
|
"SEGMENT(1 3,1 3)",
|
|
strategies);
|
|
|
|
//default strategies
|
|
tester::apply("POINT(1 3)",
|
|
"MULTILINESTRING((3 2, 1 3, 0 3, 0 1, 1 0, 0 0),(2 0,3 1,4 0))",
|
|
"SEGMENT(1 3,1 3)",
|
|
strategies, true, true);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_multi_point_segment(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "multi point/segment closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using MultiPoint = bg::model::multi_point<Point>;
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<MultiPoint, Segment, Segment>;
|
|
|
|
tester::apply("MULTIPOINT((2 0),(1 1),(1 2))",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
tester::apply("MULTIPOINT((0 1),(1 1),(1 2))",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(0 1,0 1)",
|
|
strategies);
|
|
|
|
//default strategies
|
|
tester::apply("MULTIPOINT((0 1),(1 1),(1 2))",
|
|
"SEGMENT(0 1,1 0)",
|
|
"SEGMENT(0 1,0 1)",
|
|
strategies, true, true);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_multi_point_linestring(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "multi point/linestring closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using MultiPoint = bg::model::multi_point<Point>;
|
|
using Linestring = bg::model::linestring<Point>;
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<MultiPoint, Linestring, Segment>;
|
|
|
|
tester::apply("MULTIPOINT((2 0),(1 1),(3 0))",
|
|
"LINESTRING(4 2,3 2, 1 3, 0 3, 0 1, 1 0, 0 0)",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
tester::apply("MULTIPOINT((3 2),(1 1),(3 0))",
|
|
"LINESTRING(4 2,3 2, 1 3, 0 3, 0 1, 1 0, 0 0)",
|
|
"SEGMENT(3 2,3 2)",
|
|
strategies);
|
|
|
|
//default strategies
|
|
tester::apply("MULTIPOINT((3 2),(1 1),(3 0))",
|
|
"LINESTRING(4 2,3 2, 1 3, 0 3, 0 1, 1 0, 0 0)",
|
|
"SEGMENT(3 2,3 2)",
|
|
strategies, true, true);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_closest_points_multi_point_multi_linestring(Strategies const& strategies)
|
|
{
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS
|
|
std::cout << std::endl;
|
|
std::cout << "multi point/multi linestring closest_points tests" << std::endl;
|
|
#endif
|
|
|
|
using MultiPoint = bg::model::multi_point<Point>;
|
|
using Linestring = bg::model::linestring<Point>;
|
|
using MultiLinestring = bg::model::multi_linestring<Linestring>;
|
|
using Segment = bg::model::segment<Point>;
|
|
using tester = test_geometry<MultiPoint, MultiLinestring, Segment>;
|
|
|
|
tester::apply("MULTIPOINT((5 0),(1 1),(6 0))",
|
|
"MULTILINESTRING((3 2, 1 3, 0 3, 0 1, 1 0, 0 0),(2 0,3 1,4 0))",
|
|
"SEGMENT(1 1,0.5 0.5)",
|
|
"SEGMENT(1 1,0.499962 0.500095)",
|
|
"SEGMENT(1 1,0.503314 0.496737)",
|
|
strategies);
|
|
|
|
tester::apply("MULTIPOINT((5 0),(1 3),(6 0))",
|
|
"MULTILINESTRING((3 2, 1 3, 0 3, 0 1, 1 0, 0 0),(2 0,3 1,4 0))",
|
|
"SEGMENT(1 3,1 3)",
|
|
strategies);
|
|
|
|
//default strategies
|
|
tester::apply("MULTIPOINT((5 0),(1 3),(6 0))",
|
|
"MULTILINESTRING((3 2, 1 3, 0 3, 0 1, 1 0, 0 0),(2 0,3 1,4 0))",
|
|
"SEGMENT(1 3,1 3)",
|
|
strategies, true, true);
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//===========================================================================
|
|
//===========================================================================
|
|
|
|
template <typename Point, typename Strategies>
|
|
void test_all_pl_l(Strategies strategies)
|
|
{
|
|
test_closest_points_point_segment<Point>(strategies);
|
|
test_closest_points_point_linestring<Point>(strategies);
|
|
test_closest_points_point_multi_linestring<Point>(strategies);
|
|
|
|
test_closest_points_multi_point_segment<Point>(strategies);
|
|
test_closest_points_multi_point_linestring<Point>(strategies);
|
|
test_closest_points_multi_point_multi_linestring<Point>(strategies);
|
|
|
|
test_more_empty_input_pointlike_linear<Point>(strategies);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE( test_all_pointlike_linear )
|
|
{
|
|
test_all_pl_l<car_point>(cartesian());
|
|
|
|
test_all_pl_l<sph_point>(spherical());
|
|
test_all_pl_l<sph_point>(spherical(
|
|
bg::formula::mean_radius<double>(bg::srs::spheroid<double>())));
|
|
|
|
test_all_pl_l<geo_point>(andoyer());
|
|
test_all_pl_l<geo_point>(thomas());
|
|
test_all_pl_l<geo_point>(vincenty());
|
|
|
|
using stype = bg::srs::spheroid<double>;
|
|
|
|
test_closest_points_point_segment_diff_spheroid<geo_point>
|
|
(andoyer(stype(5000000,6000000)));
|
|
|
|
using int_car_point = bg::model::point<int, 2, bg::cs::cartesian>;
|
|
test_closest_points_point_segment_integral<int_car_point, car_point>(cartesian());
|
|
}
|
|
|
|
// tests from https://github.com/boostorg/geometry/pull/707#issuecomment-786650747
|
|
|
|
template <typename CT>
|
|
void closest_path_tester(std::string point_wkt,
|
|
std::string segment_wkt,
|
|
double error)
|
|
{
|
|
using point_type = bg::model::point
|
|
<
|
|
CT,
|
|
2,
|
|
bg::cs::geographic<bg::degree>
|
|
>;
|
|
using segment_type = bg::model::segment<point_type>;
|
|
|
|
point_type point;
|
|
segment_type segment;
|
|
|
|
bg::read_wkt(point_wkt, point);
|
|
bg::read_wkt(segment_wkt, segment);
|
|
|
|
const auto distance = bg::distance(point, segment);
|
|
|
|
segment_type projection;
|
|
bg::closest_points(point, segment, projection);
|
|
|
|
auto p0 = point_type(bg::get<0,0>(projection), bg::get<0,1>(projection));
|
|
auto p1 = point_type(bg::get<1,0>(projection), bg::get<1,1>(projection));
|
|
|
|
const auto dist1 = bg::distance(p0, p1);//bg::length(projection);
|
|
const auto dist2 = bg::distance(p0, segment);//should be equal to dist1
|
|
const auto dist3 = bg::distance(p1, segment);//should be 0
|
|
|
|
|
|
#ifdef BOOST_GEOMETRY_TEST_DEBUG_CLOSEST_POINTS_CLOSEST_POINTS
|
|
std::cout << std::setprecision(30)
|
|
<< "Point: " << bg::wkt(point) << "\n"
|
|
<< "Segment: " << bg::wkt(segment) << "\n"
|
|
<< "Distance: " << distance << "\n"
|
|
<< "Projection: " << bg::wkt(projection) << "\n"
|
|
<< "Distance 1: " << dist1 << "\n"
|
|
<< "Distance 2: " << dist2 << "\n"
|
|
<< "Distance 3: " << dist3 << std::endl;
|
|
#endif
|
|
|
|
BOOST_CHECK_CLOSE_FRACTION(distance, dist1, error);
|
|
BOOST_CHECK_CLOSE_FRACTION(dist1, dist2, error);
|
|
BOOST_CHECK(dist3 == 0);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(closest_path_test_1)
|
|
{
|
|
auto point_wkt = "POINT(11.845747600604916272 50.303247769986953131)";
|
|
auto segment_wkt = "SEGMENT(11.8449176 50.3030635,11.8458063 50.3032608)";
|
|
|
|
closest_path_tester<double>(point_wkt, segment_wkt, 1e-20);
|
|
closest_path_tester<long double>(point_wkt, segment_wkt, 1e-20);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(clostest_path_test_2)
|
|
{
|
|
auto point_wkt = "POINT(11.921418190002441406 50.316425323486328125)";
|
|
auto segment_wkt = "SEGMENT(11.9214920 50.3161678,11.9212341 50.3161381)";
|
|
|
|
closest_path_tester<double>(point_wkt, segment_wkt, 1e-12);
|
|
closest_path_tester<long double>(point_wkt, segment_wkt, 1e-8);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(clostest_path_test_3)
|
|
{
|
|
auto point_wkt = "POINT(11.904624124918561169 50.317349861000025692)";
|
|
auto segment_wkt = "SEGMENT(11.9046808 50.3173523,11.9045925 50.3173485)";
|
|
|
|
closest_path_tester<double>(point_wkt, segment_wkt, 1e-20);
|
|
closest_path_tester<long double>(point_wkt, segment_wkt, 1e-20);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(clostest_path_test_4)
|
|
{
|
|
auto point_wkt = "POINT(11.907328887553041017 50.311933736642272308)";
|
|
auto segment_wkt = "SEGMENT(11.9072659 50.3119291,11.9074099 50.3119397)";
|
|
|
|
closest_path_tester<double>(point_wkt, segment_wkt, 1e-20);
|
|
closest_path_tester<long double>(point_wkt, segment_wkt, 1e-20);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(clostest_path_test_5)
|
|
{
|
|
auto point_wkt = "POINT(11.894846916198730469 50.316379547119140625)";
|
|
auto segment_wkt = "SEGMENT(11.8958402 50.3155918,11.8953426 50.3155504)";
|
|
|
|
closest_path_tester<double>(point_wkt, segment_wkt, 1e-6);
|
|
closest_path_tester<long double>(point_wkt, segment_wkt, 1e-6);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(clostest_path_test_6)
|
|
{
|
|
auto point_wkt = "POINT(11.914519782008024862 50.319138765234583843)";
|
|
auto segment_wkt = "SEGMENT(11.9145157 50.3191017,11.9145257 50.3191925)";
|
|
|
|
closest_path_tester<double>(point_wkt, segment_wkt, 1e-6);
|
|
closest_path_tester<long double>(point_wkt, segment_wkt, 1e-20);
|
|
}
|