feat: include changes and tests changes

This commit is contained in:
Barend Gehrels 2025-01-16 19:04:23 +01:00
parent 3fc2739fe1
commit b93561729d
22 changed files with 573 additions and 70 deletions

View File

@ -0,0 +1,69 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2025 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2023-2024 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2024.
// Modifications copyright (c) 2017-2024 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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TRAVERSE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TRAVERSE_HPP
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \
|| defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \
|| defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)
# include <string>
# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
# include <boost/geometry/io/wkt/wkt.hpp>
#endif
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
template <typename Turn, typename Operation>
#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE
inline void debug_traverse(Turn const& turn, Operation op,
std::string const& header, bool condition = true)
{
if (! condition)
{
return;
}
std::cout << " " << header
<< " at " << op.seg_id
<< " meth: " << method_char(turn.method)
<< " op: " << operation_char(op.operation)
<< " of: " << operation_char(turn.operations[0].operation)
<< operation_char(turn.operations[1].operation)
<< " " << geometry::wkt(turn.point)
<< std::endl;
if (boost::contains(header, "Finished"))
{
std::cout << std::endl;
}
}
#else
inline void debug_traverse(Turn const& , Operation, const char*, bool = true)
{
}
#endif
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TRAVERSE_HPP

View File

@ -138,6 +138,7 @@ inline void enrich_assign(Operations& operations, Turns& turns)
&& op.seg_id == next_operation().seg_id
&& indexed.turn_index != operations[next_index].turn_index)
{
// In same cluster, on same segment, but not same turn
next_index = advance(next_index);
}
@ -286,15 +287,9 @@ inline auto create_map(Turns const& turns, IncludePolicy const& include_policy)
auto const& op = op_item.value;
if (include_policy.include(op.operation))
{
ring_identifier const ring_id
mapped_vector[ring_id_by_seg_id(op.seg_id)].emplace_back
(
op.seg_id.source_index,
op.seg_id.multi_index,
op.seg_id.ring_index
);
mapped_vector[ring_id].emplace_back
(
index, op_index, op, turn.operations[1 - op_index].seg_id
index, op_index, op, turn.operations[1 - op_index].seg_id
);
}
}
@ -403,8 +398,6 @@ inline void enrich_intersection_points(Turns& turns,
// For all operations, discard xx and none/none
// For intersections, remove uu to avoid the need to travel
// a union (during intersection) in uu/cc clusters (e.g. #31,#32,#33)
// The ux is necessary to indicate impossible paths
// (especially if rescaling is removed)
// Similarly, for union, discard ii and ix
@ -457,6 +450,8 @@ inline void enrich_intersection_points(Turns& turns,
strategy);
}
// After cleaning up clusters assign the next turns
for (auto& pair : mapped_vector)
{
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH

View File

@ -28,6 +28,7 @@
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_traverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/relate/turns.hpp>

View File

@ -23,6 +23,7 @@
#include <boost/range/value_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_traverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
@ -44,36 +45,6 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
template <typename Turn, typename Operation>
#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE
inline void debug_traverse(Turn const& turn, Operation op,
std::string const& header, bool condition = true)
{
if (! condition)
{
return;
}
std::cout << " " << header
<< " at " << op.seg_id
<< " meth: " << method_char(turn.method)
<< " op: " << operation_char(op.operation)
<< " vis: " << visited_char(op.visited)
<< " of: " << operation_char(turn.operations[0].operation)
<< operation_char(turn.operations[1].operation)
<< " " << geometry::wkt(turn.point)
<< std::endl;
if (boost::contains(header, "Finished"))
{
std::cout << std::endl;
}
}
#else
inline void debug_traverse(Turn const& , Operation, const char*, bool = true)
{
}
#endif
template
<
bool Reverse1,

View File

@ -22,6 +22,8 @@
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
#include <boost/geometry/strategies/distance/detail.hpp>
#include <boost/geometry/strategies/distance/services.hpp>
#include <boost/geometry/strategies/envelope/cartesian.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/strategies/detail.hpp>
@ -155,6 +157,13 @@ public:
return strategy::intersection::cartesian_segments<CalculationType>();
}
template <typename Geometry1, typename Geometry2>
static auto comparable_distance(Geometry1 const&, Geometry2 const&,
distance::detail::enable_if_pp_t<Geometry1, Geometry2> * = nullptr)
{
return strategy::distance::comparable::pythagoras<CalculationType>();
}
// side
static auto side()

View File

@ -20,6 +20,8 @@
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/distance/detail.hpp>
#include <boost/geometry/strategies/distance/services.hpp>
#include <boost/geometry/strategies/envelope/geographic.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/strategies/detail.hpp>
@ -78,6 +80,16 @@ public:
>(base_t::m_spheroid);
}
template <typename Geometry1, typename Geometry2>
auto comparable_distance(Geometry1 const&, Geometry2 const&,
distance::detail::enable_if_pp_t<Geometry1, Geometry2> * = nullptr) const
{
return strategy::distance::geographic
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
// covered_by
template <typename Geometry1, typename Geometry2>

View File

@ -20,6 +20,8 @@
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/distance/detail.hpp>
#include <boost/geometry/strategies/distance/services.hpp>
#include <boost/geometry/strategies/envelope/spherical.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/strategies/detail.hpp>
@ -77,6 +79,16 @@ public:
>(base_t::radius());
}
template <typename Geometry1, typename Geometry2>
auto comparable_distance(Geometry1 const&, Geometry2 const&,
distance::detail::enable_if_pp_t<Geometry1, Geometry2> * = nullptr) const
{
return strategy::distance::comparable::haversine
<
typename base_t::radius_type, CalculationType
>(base_t::radius());
}
// covered_by
template <typename Geometry1, typename Geometry2>

View File

@ -15,7 +15,6 @@ endforeach()
# Tests for all geometry types, cartesian, for one floating point type
foreach(item IN ITEMS
buffer_point
buffer_linestring
buffer_ring
buffer_polygon
buffer_multi_point
@ -38,6 +37,17 @@ foreach(item IN ITEMS
target_compile_definitions(${BOOST_GEOMETRY_UNIT_TEST_NAME} PRIVATE BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
endforeach()
# Tests which take a long time and are not run by default.
# Besides that, the buffer_countries test requires the WKT files.
foreach(item IN ITEMS
buffer_countries
buffer_linestring
buffer_linestring_geo
)
boost_geometry_add_unit_test("algorithms" ${item} "not_run")
target_compile_definitions(${BOOST_GEOMETRY_UNIT_TEST_NAME} PRIVATE BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
endforeach()
# Other tests
foreach(item IN ITEMS
buffer_with_strategies

View File

@ -0,0 +1,144 @@
// Boost.Geometry
// Copyright (c) 2025 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_TEST_BUFFER_CASES_HPP
#define BOOST_GEOMETRY_TEST_BUFFER_CASES_HPP
#include <string>
// The "w" series of recursive_polygons_buffer, which are or were failing for traversing through the graph
// using the biconnected components.
// Needs aligning position codes in assign_clustered_counts
static std::string const rt_w1
= "MULTIPOLYGON(((2 0,2 1,3 1,3 0,2 0)),((4 2,4 3,5 2,4 2)),((1 6,0 6,0 7,1 6)),((1 6,2 5,1 5,1 6)))";
// Caused by a wrong block_q in get_turn_info (resulting in ix i/o iu)
static std::string const rt_w2
= "MULTIPOLYGON(((6 3,6 4,7 4,6 3)),((6 3,5 2,5 3,6 3)))";
// Goes wrong either way
static std::string const rt_w3
= "MULTIPOLYGON(((8 3,8 4,9 4,9 3,8 3)),((7 5,7 6,8 6,7 5)),((5 5,4 4,4 5,5 5)),((5 5,6 5,5 4,5 5)),((0 7,0 8,1 8,0 7)),((2 2,2 3,3 3,2 2)),((2 8,3 8,3 7,3 6,2 6,2 8)))";
// Needs fix in arrival handling - it had weird turn info near node 3, ux, while both continue.
static std::string const rt_w4
= "MULTIPOLYGON(((4 6,4 7,5 6,4 6)),((8 0,8 1,9 1,8 0)),((1 6,1 7,2 7,1 6)),((0 2,0 3,1 2,0 2)),((5 2,6 3,6 2,5 2)),((5 2,5 1,4 1,4 2,5 2)),((2 9,3 8,2 8,1 8,1 9,2 9)))";
// Having a big clusters with all position codes, and two interior rings
static std::string const rt_w5
= "MULTIPOLYGON(((2 1,2 2,3 2,3 1,2 1)),((2 6,2 7,3 7,3 6,2 6)),((3 4,3 5,4 5,4 4,3 4)),((5 3,5 2,4 2,5 3)),((5 3,5 4,6 3,5 3)),((0 2,1 1,0 0,0 2)),((0 8,1 8,1 7,0 7,0 8)),((0 5,1 5,2 5,1 4,0 3,0 5)),((7 1,6 1,6 2,7 1)),((7 1,8 0,7 0,7 1)),((8 6,7 6,7 8,8 8,8 6)),((6 8,6 7,5 7,5 8,6 8)),((6 1,5 0,5 1,6 1)),((7 8,7 9,8 9,7 8)),((6 4,7 3,6 3,6 4)),((6 4,6 5,7 5,7 4,6 4)),((7 6,6 6,6 7,7 6)),((5 8,4 7,4 8,5 8)),((5 8,5 9,6 9,5 8)),((7 4,8 3,7 3,7 4)),((8 3,8 4,9 4,9 3,8 3)))";
// Fixed regression
static std::string const rt_w6
= "MULTIPOLYGON(((7 0,7 1,8 0,7 0)),((8 6,8 7,9 7,9 6,8 6)),((2 8,3 9,3 8,2 8)),((4 3,4 4,5 4,4 3)),((6 5,6 6,7 6,6 5)),((1 7,2 7,1 6,0 6,1 7)),((1 5,0 4,0 5,1 5)),((1 5,2 6,2 5,1 5)),((0 4,1 4,0 3,0 4)),((2 1,1 0,0 0,0 1,2 1)),((7 4,6 3,6 4,7 4)),((7 4,7 5,8 5,7 4)),((6 3,7 3,6 2,6 3)))";
// Fixed by first handling non-clustered turns
static std::string const rt_w7
= "MULTIPOLYGON(((6 0,6 1,7 1,6 0)),((6 6,7 7,7 6,6 6)),((8 0,8 1,9 1,8 0)),((2 7,2 8,3 7,2 7)),((1 2,1 3,2 3,1 2)),((8 2,8 3,9 2,8 2)),((4 5,4 4,3 4,4 5)),((4 5,5 6,5 5,4 5)))";
// Fixed select_collinear_target_edge
static std::string const rt_w8
= "MULTIPOLYGON(((0 4,0 5,1 5,0 4)),((1 3,1 4,2 4,1 3)),((2 8,2 9,3 8,2 8)),((6 3,6 4,7 3,6 3)),((7 1,7 2,8 2,8 1,7 1)),((0 2,0 3,1 2,0 2)),((0 2,1 1,0 1,0 2)),((3 2,3 1,2 1,3 2)),((3 2,2 2,3 3,3 2)),((9 6,9 5,8 5,9 6)),((9 6,8 6,8 7,9 7,9 6)),((5 2,5 1,4 1,4 2,5 2)),((5 2,5 3,6 2,5 2)),((5 6,4 6,4 7,5 6)),((5 6,6 5,5 5,5 6)),((5 6,6 7,6 6,5 6)))";
// fixed by setting operations to blocked
static std::string const rt_w9
= "MULTIPOLYGON(((3 8,4 9,4 8,3 8)),((4 2,4 4,5 3,5 2,4 2)),((4 2,4 1,3 1,3 2,4 2)),((2 4,2 5,3 5,3 4,3 3,2 3,2 2,1 2,1 3,2 4)),((8 8,7 8,7 9,8 8)),((8 8,9 8,8 7,8 8)),((1 2,0 2,0 3,1 2)),((4 6,3 6,3 7,4 6)),((4 6,5 6,5 5,4 5,4 6)),((8 7,8 6,7 6,8 7)),((8 6,9 7,9 6,8 6)))";
// fixed by position_code=3 in assign_clustered_counts
static std::string const rt_w10
= "MULTIPOLYGON(((3 2,3 3,4 3,3 2)),((2 8,2 9,3 9,3 8,2 8)),((7 8,7 9,8 9,7 8)),((4 4,5 5,5 4,4 4)),((5 7,5 8,6 7,5 7)),((6 2,7 3,7 2,6 2)),((0 3,1 4,1 3,0 2,0 3)),((8 5,8 4,7 4,8 5)),((8 5,8 6,9 5,8 5)),((7 4,6 4,6 5,7 5,7 4)),((3 6,4 7,4 6,3 6)),((3 6,3 5,2 5,3 6)),((8 2,8 1,7 1,8 2)),((8 2,8 3,9 2,8 2)),((1 3,2 2,1 2,1 3)))";
// same as rt_w1 - also its configuration is similar.
static std::string const rt_w11
= "MULTIPOLYGON(((2 8,2 9,3 9,3 8,2 8)),((6 7,6 8,7 8,7 7,6 7)),((5 0,5 1,6 1,6 0,5 0)),((4 2,4 3,5 2,4 2)),((4 2,4 1,3 1,3 2,4 2)),((1 6,0 6,0 7,1 6)),((1 6,2 5,1 5,1 6)),((4 1,4 0,3 0,4 1)))";
static std::string const rt_w12
= "MULTIPOLYGON(((0 7,0 8,1 7,0 7)),((4 3,4 4,5 3,4 3)),((5 2,6 3,6 2,5 2)),((5 2,4 1,4 2,5 2)))";
// fixed by using continue with count-left 0
static std::string const rt_w13
= "MULTIPOLYGON(((6 2,6 3,7 2,6 2)),((4 4,4 3,3 3,3 4,4 4)),((4 4,4 5,5 4,4 4)),((4 3,4 2,3 2,4 3)))";
// Caused by a wrong block_q in get_turn_info (resulting in ix i/o iu)
static std::string const rt_w14
= "MULTIPOLYGON(((6 0,6 1,7 0,6 0)),((1 4,2 5,2 4,1 4)),((1 2,1 3,2 3,1 2)),((3 7,3 8,4 7,3 7)),((2 1,3 2,3 1,2 1)),((3 5,3 6,4 6,4 5,3 5)),((7 4,6 4,6 5,7 4)),((7 4,8 3,7 3,7 4)))";
// Would need calling assign_count before enrich. But it is now harmonized
// to be the same as union/intersection
static std::string const rt_w15
= "MULTIPOLYGON(((3 8,3 9,4 9,4 8,3 8)),((0 8,1 9,1 8,0 8)),((1 6,1 7,2 7,2 6,1 6)),((7 7,8 8,8 7,7 7)),((4 3,3 3,3 4,4 3)),((4 3,5 2,4 2,4 3)),((1 5,2 5,2 4,2 3,1 3,1 4,0 4,1 5)),((6 1,7 0,6 0,6 1)),((6 1,5 1,6 2,6 1)),((7 0,7 1,8 0,7 0)),((2 1,3 1,3 0,1 0,2 1)),((2 1,2 2,3 2,2 1)))";
// fixed by ahead_side in cc
static std::string const rt_w16
= "MULTIPOLYGON(((6 4,6 5,7 5,6 4)),((4 0,4 1,5 0,4 0)),((4 2,4 3,5 3,4 2)),((1 2,1 3,2 3,2 2,1 2)))";
// fixed by keeping set_both_verified
static std::string const rt_w17
= "MULTIPOLYGON(((3 1,4 2,4 1,3 1)),((5 3,6 4,6 3,5 3)),((5 0,5 1,6 1,6 0,5 0)),((8 5,9 6,9 5,8 5)),((8 5,7 4,7 5,8 5)))";
static std::string const rt_w18
= "MULTIPOLYGON(((4 4,4 5,5 4,4 4)),((5 6,6 7,6 6,5 6)),((5 1,4 1,4 2,5 3,5 1)),((7 6,7 7,8 7,7 6)),((0 6,1 6,1 5,1 4,0 4,0 6)),((1 8,2 7,1 7,1 8)),((1 8,2 9,2 8,1 8)),((1 6,1 7,2 6,1 6)),((7 3,7 2,6 2,7 3)),((7 3,7 4,8 4,8 3,7 3)),((3 2,3 1,2 1,3 2)),((3 2,2 2,2 3,3 3,3 2)),((5 8,5 7,4 7,4 8,5 8)),((5 8,6 9,6 8,5 8)))";
// Contains a cc turn (1) located wrongly.
// Reported at 1/1, but should be 0/1 - or it should have a segment id belonging to previous segment.
// Fixed by removing specific arriving handling.
static std::string const rt_w19
= "MULTIPOLYGON(((3 8,3 9,4 9,3 8)),((3 4,4 5,4 4,3 4)),((7 0,7 1,8 1,7 0)),((8 5,9 6,9 5,8 5)),((2 7,3 7,3 6,2 6,2 7)),((7 4,8 3,7 3,6 3,7 4)))";
// REPORTED as #1359 - but somehow now fixed - issue was: start turn discarded while it should not be.
static std::string const rt_w20
= "MULTIPOLYGON(((2 8,2 9,3 8,2 8)),((7 1,7 2,8 1,7 1)),((5 2,5 3,6 2,5 2)),((2 2,2 3,3 3,2 2)),((1 3,1 4,2 4,1 3)),((6 4,6 5,7 4,6 4)),((9 8,8 8,9 9,9 8)),((9 8,9 7,8 7,9 8)))";
// reproduction of wrong order (i/u)
static std::string const rt_w21
= "MULTIPOLYGON(((2 8,2 9,3 8,2 8)),((4 6,4 7,5 6,4 6)),((4 2,5 2,4 1,4 2)))";
// Needs a spike. Also, it misses a small triangle, so area is not completely correct
static std::string const rt_w22
= "MULTIPOLYGON(((6 3,6 4,7 4,7 3,6 3)),((6 1,6 2,7 2,6 1)),((2 8,2 9,3 9,2 8)),((4 7,5 8,5 7,4 7)),((2 1,2 0,1 0,2 1)),((2 1,2 2,3 2,3 1,2 1)),((3 3,2 2,2 3,3 3)),((3 3,3 4,4 3,3 3)),((0 5,1 4,1 3,0 3,0 5)),((8 6,9 6,9 5,8 5,8 6)),((8 6,7 6,6 6,7 7,8 6)),((1 3,1 2,0 2,1 3)),((4 3,5 3,4 2,4 3)),((4 2,5 1,4 1,4 2)))";
// Caused by spike handling.
static std::string const rt_w23
= "MULTIPOLYGON(((4 0,4 1,5 1,5 0,4 0)),((1 3,1 4,2 4,2 3,1 3)),((6 3,6 4,7 4,7 3,6 3)),((6 8,7 9,7 8,6 8)),((4 8,5 9,5 8,4 8)),((4 4,4 5,5 5,5 4,4 4)),((8 1,8 0,7 0,7 1,8 1)))";
// Case with suspicious UX turn, causing a wrong graph, and more. Old algorithm could cope with it.
// This should be fixed in get_turn_info.
static std::string const rt_w24
= "MULTIPOLYGON(((2 3,2 4,3 3,2 3)),((8 5,8 6,9 6,8 5)),((3 6,4 5,3 5,3 6)),((3 6,4 7,4 6,3 6)),((5 2,5 3,6 3,5 2)),((5 8,6 9,6 8,5 8)),((0 5,1 6,1 5,0 5)),((0 1,0 2,1 1,0 1)))";
// Case with wrong order (i/u), corrected to cc, but it also needs adapting the left counts.
static std::string const rt_w25
= "MULTIPOLYGON(((0 5,0 6,1 5,0 5)),((6 1,7 1,7 0,6 0,6 1)),((1 6,1 7,2 6,1 6)),((8 7,8 8,9 8,9 7,8 7)),((8 1,9 2,9 1,8 1)),((0 1,0 2,1 2,1 1,0 1)),((6 3,6 4,7 3,6 3)),((4.5 8.5,5 8,4 8,4 9,5 9,4.5 8.5)),((2 4,3 5,4 5,4 4,2 4)),((3 7,4 8,4 7,3 7)),((3 7,2 7,2 8,3 7)))";
// Needs skip-count to be translated to travels_to_ip_index as -1, for a cc turn.
static std::string const rt_w26
= "MULTIPOLYGON(((6 6,6 7,7 6,6 6)),((0 0,0 1,1 1,1 0,0 0)),((3 6,2 5,2 7,2.5 6.5,3 7,4 6,5 5,3 5,3 6)),((3 2,2 2,2 3,1 3,3 5,3 2)),((3 1,4 0,3 0,3 1)),((3 1,2 0,2 1,3 1)),((3 7,2 7,2 8,3 7)),((1 8,0 8,0 9,1 9,1 8)),((1 8,2 7,1 7,1 8)),((2 5,1 5,1 6,2 6,1.5 5.5,2 5)),((5 0,5 1,6 1,6 0,5 0)),((1 3,1 2,0 2,1 3)),((4 6,4 7,5 7,5 6,4 6)),((1 6,0 6,0 7,1 6)),((1 5,1 4,0 4,0 5,1 5)),((6 1,6 2,7 2,7 1,6 1)),((6 2,6 3,7 3,6 2)),((7 1,8 1,8 0,7 0,7 1)))";
// Fixed by fixing by suspicious UX turn.
static std::string const rt_w27
= "MULTIPOLYGON(((3 6,4 7,4 6,3 6)),((4 3,4 4,5 4,5 3,4 3)),((5 8,6 9,6 8,5 8)),((2 7,2 8,3 8,3 7,2 7)))";
// Fixed by fixing by suspicious UX turn.
static std::string const rt_w28
= "MULTIPOLYGON(((8 8,8 9,9 9,8 8)),((1 2,1 3,2 3,1 2)),((3 8,3 9,4 9,3 8)),((1 1,2 1,1 0,1 1)),((1 1,0 1,0 2,1 1)),((3 0,2 0,2 1,3 0)),((1 8,2 7,1 7,1 8)),((1 8,0 8,0 9,2 9,1 8)),((2.5 5.5,3 5,2 5,2 6,3 6,2.5 5.5)),((5 5,6 5,6 4,5 4,5 5)),((7 3,8 4,8 3,7 3)),((7 3,6 3,6 4,7 4,7 3)),((7 4,7 5,7 6,8 6,8 4,7 4)),((7 8,7 7,6 7,6 8,7 8)),((4 8,5 9,6 8,4 8)),((4 8,4 7,3 7,4 8)),((2 7,2 6,1 6,2 7)),((1 6,2 5,1 5,1 6)),((5 4,5 3,3 3,3 4,4 4,4 5,5 4)),((2 5,2 4,1 4,2 5)),((8 4,9 5,9 4,8 4)),((6 7,6 6,5 6,5 7,6 7)))";
// Needs original arrival behaviour
static std::string const rt_w29
= "MULTIPOLYGON(((3 7,3 8,4 7,3 7)),((6 5,7 4,5 4,6 5)),((5 4,5 3,4 3,5 4)))";
// Needs to skip the "target ahead" check in is_cc_target_for_union
static std::string const rt_w30
= "MULTIPOLYGON(((6 6,7 7,7 6,6 6)),((8 3,9 3,8.5 2.5,9 2,8 2,8 3)),((4 0,4 1,5 0,4 0)),((0 5,1 6,1 5,0 5)),((3 8,4 9,4 8,3 8)),((7 4,7 5,8 5,7 4)),((7 4,6 3,6 4,7 4)))";
// Like rt_w30, needs to skip the "target ahead" check
static std::string const rt_w31
= "MULTIPOLYGON(((0 1,0 2,1 2,1 1,0 1)),((0 4,0 5,1 5,0 4)),((3 8,4 8,3 7,2 7,3 8)),((3 2,3 3,4 3,3 2)),((0 6,0 7,1 6,0 6)),((0 8,0 9,1 8,0 8)),((4 5,4 4,3 4,3 5,4 5)),((4 5,4 6,5 6,4 5)),((9 3,9 2,8 2,8 3,9 3)),((7 4,7 5,8 5,7 4)),((7 4,6 3,6 4,7 4)),((6 8,7 8,6.5 7.5,7 7,6 7,6 8)),((5 6,5 7,6 6,5 6)))";
#endif

View File

@ -119,6 +119,13 @@ void test_all()
const std::string base_folder = "data/";
const std::string gr = read_from_wkt_file<mpt>(base_folder + "gr.wkt");
if (gr.empty())
{
// If this file is not found, the others won't be find either.
std::cerr << "Error: cannot read WKT files from " << base_folder << std::endl;
return;
}
const std::string it = read_from_wkt_file<mpt>(base_folder + "it.wkt");
const std::string nl = read_from_wkt_file<mpt>(base_folder + "nl.wkt");
const std::string no = read_from_wkt_file<mpt>(base_folder + "no.wkt");

View File

@ -12,6 +12,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include "test_buffer.hpp"
#include "buffer_cases.hpp"
static std::string const simplex
= "MULTIPOLYGON(((0 1,2 5,5 3,0 1)),((1 1,5 2,5 0,1 1)))";
@ -411,6 +412,10 @@ static std::string const mysql_report_2015_07_05_1
static std::string const mysql_report_2015_07_05_2
= "MULTIPOLYGON(((19777 -21893,3.22595e+307 6.86823e+307,-40 -13,19777 -21893)),((-1322 4851,8.49998e+307 3.94481e+307,75 -69,8.64636e+307 3.94909e+307,-1.15292e+18 7.20576e+16,-1322 4851)))";
#define TEST_BUFFER(caseid, join, end, area, distance) (test_one<multi_polygon_type, polygon_type>) \
( #caseid "_buf", caseid, join, end, area, distance)
template <bool Clockwise, typename P>
void test_all()
{
@ -597,6 +602,50 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("rt_v3", rt_v3, join_round32, end_flat, 22.9158, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_v4", rt_v4, join_round32, end_flat, 23.4146, 1.0);
TEST_BUFFER(rt_w1, join_miter, end_flat, 30.3995, 1.0);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w2, join_miter, end_flat, 13.65685, 1.0);
TEST_BUFFER(rt_w3, join_miter, end_flat, 19.39949, 1.0);
#endif
TEST_BUFFER(rt_w4, join_miter, end_flat, 57.37, 1.0);
TEST_BUFFER(rt_w5, join_miter, end_flat, 106.7279, 1.0);
TEST_BUFFER(rt_w6, join_miter, end_flat, 79.799, 1.0);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w7, join_miter, end_flat, 58.8701, 1.0);
#endif
TEST_BUFFER(rt_w8, join_miter, end_flat, 83.4852, 1.0);
TEST_BUFFER(rt_w9, join_miter, end_flat, 68.9852, 1.0);
TEST_BUFFER(rt_w10, join_miter, end_flat, 88.1985, 1.0);
TEST_BUFFER(rt_w11, join_miter, end_flat, 53.4853, 1.0);
TEST_BUFFER(rt_w12, join_miter, end_flat, 28.7353, 1.0);
TEST_BUFFER(rt_w13, join_miter, end_flat, 25.5711, 1.0);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w14, join_miter, end_flat, 58.05634, 1.0);
#endif
TEST_BUFFER(rt_w15, join_miter, end_flat, 80.1348, 1.0);
TEST_BUFFER(rt_w16, join_miter, end_flat, 31.6495, 1.0);
TEST_BUFFER(rt_w17, join_miter, end_flat, 33.74264, 1.0);
TEST_BUFFER(rt_w18, join_miter, end_flat, 82.4779, 1.0);
TEST_BUFFER(rt_w19, join_miter, end_flat, 53.7132, 1.0);
TEST_BUFFER(rt_w20, join_miter, end_flat, 63.0269, 1.0);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w21, join_miter, end_flat, 26.3137, 1.0);
#endif
TEST_BUFFER(rt_w22, join_miter, end_flat, 86.0416, 1.0);
TEST_BUFFER(rt_w23, join_miter, end_flat, 59.5711, 1.0);
TEST_BUFFER(rt_w24, join_miter, end_flat, 64.1985, 1.0);
TEST_BUFFER(rt_w25, join_miter, end_flat, 84.3848, 1.0);
TEST_BUFFER(rt_w26, join_miter, end_flat, 91.6569, 1.0);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w27, join_miter, end_flat, 31.6569, 1.0);
#endif
TEST_BUFFER(rt_w28, join_miter, end_flat, 100.0710, 1.0);
TEST_BUFFER(rt_w29, join_miter, end_flat, 25.1421, 1.0);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w30, join_miter, end_flat, 59.4485, 1.0);
TEST_BUFFER(rt_w31, join_miter, end_flat, 85.7916, 1.0);
#endif
test_one<multi_polygon_type, polygon_type>("nores_mt_1", nores_mt_1, join_round32, end_flat, 13.4113, 1.0);
test_one<multi_polygon_type, polygon_type>("nores_mt_2", nores_mt_2, join_round32, end_flat, 17.5265, 1.0);
test_one<multi_polygon_type, polygon_type>("nores_mt_3", nores_mt_3, join_round32, end_flat, 25.6091, 1.0);

View File

@ -38,8 +38,6 @@ inline std::string read_from_wkt_file(std::string const& filename)
out << std::fixed << std::setprecision(20) << bg::wkt(mp);
}
BOOST_CHECK(! out.str().empty());
return out.str();
}

File diff suppressed because one or more lines are too long

View File

@ -1182,6 +1182,12 @@ static std::string issue_1186[2] =
"POLYGON((-13848.1446527556 6710443.1496919869,-13848.2559722463 6710440.2884572418,-13847.8106942832 6710440.1096301023,-13847.6993747924 6710443.1496919869,-13847.3654163201 6710442.9708647905,-13846.0295824308 6710442.9708647905,-13846.4748603939 6710435.1024718173,-13847.8106942832 6710435.1024718173,-13848.1446527556 6710435.1024718173,-13849.8144451172 6710443.1496919869,-13848.1446527556 6710443.1496919869),(-13847.4767358109 6710440.1096301023,-13847.8106942832 6710440.1096301023,-13847.9220137740 6710439.9308029665,-13847.5880553017 6710439.7519758362,-13847.4767358109 6710440.1096301023))"
};
static std::string issue_1211[2] =
{
"POLYGON((0.875 0.4375, 0.875 0.375, 0.9375 0.375))",
"POLYGON((1. 0., 1. 0.581662834, 0.824054539 0.))"
};
static std::string issue_1226[2] =
{
"POLYGON((-0.90478776881879274807 0.51756843862589896332,-0.91 0.48,-1.2 0.4,-1.4 1.9,-0.90478776881879274807 0.51756843862589896332))",
@ -1291,6 +1297,12 @@ static std::string issue_1345_b[2] =
)""""
};
static std::string issue_1363[2] =
{
"MULTIPOLYGON(((2.0611606968426476882 0.61095000000000010409,2.046160696842648008 0.62595000000000000639,2.0311606968426478836 0.6409499999999999087,1.9486606968426476438 0.73094999999999987761,1.9261606968426476794 0.76094999999999990425,1.9336606968426472974 0.78344999999999986873,2.0161606968426477593 0.85844999999999993534,2.0236606968426480435 0.8584499999999997133,2.0461606968426475639 0.90344999999999986429,2.0911606968426479369 0.88844999999999973994,2.098660696842647333 0.8734499999999996156,2.1136606968426479014 0.86594999999999977547,2.1286606968426480258 0.85094999999999976215,2.1436606968426472619 0.83594999999999985985,2.143660696842647706 0.62594999999999989537,2.0836606968426476527 0.62594999999999989537,2.0611606968426476882 0.61095000000000010409)))",
"MULTIPOLYGON(((2.0461606968426484521 0.90344999999999986429,2.001160696842647635 0.91095000000000003748,1.8511606968426477238 0.91094999999999992646,1.813660696842647635 0.91844999999999998863,1.813660696842647635 0.9409499999999999531,1.8211606968426479192 1.1059499999999999886,1.8286606968426479813 1.263449999999999962,1.9636606968426479902 1.263449999999999962,2.0461606968426484521 1.2559499999999998998,2.0536606968426478481 1.2409499999999999975,2.1286606968426480258 1.2409499999999999975,2.1286606968426480258 1.1059499999999999886,2.1211606968426477415 0.92594999999999982876,2.1136606968426479014 0.89594999999999980211,2.091160696842648381 0.88844999999999996199,2.0461606968426484521 0.90344999999999986429)))"
};
static std::string ggl_list_20120229_volker[3] =
{
"POLYGON((1716 1554,2076 2250,2436 2352,2796 1248,3156 2484,3516 2688,3516 2688,3156 2484,2796 1248,2436 2352,2076 2250, 1716 1554))",

View File

@ -27,7 +27,7 @@
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
//#include <boost/geometry/algorithms/detail/overlay/self_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/has_self_intersections.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

View File

@ -20,7 +20,7 @@
// check less functor for turns
template <typename Turns, typename Less>
inline void verify_less_for_turns(Turns turns, Less const& less)
inline void verify_less_for_turns(Turns const& turns, Less const& less)
{
typedef typename boost::range_iterator<Turns const>::type iterator_type;

View File

@ -26,6 +26,7 @@
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/register/linestring.hpp>
#include <boost/geometry/algorithms/detail/has_self_intersections.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/constexpr.hpp>

View File

@ -248,6 +248,8 @@ int test_main(int, char* [])
TEST_CASE(case_145_multi);
TEST_CASE_WITH(case_146_multi, 0, 1, ut_settings().ignore_validity_intersection());
TEST_CASE(case_147_multi);
TEST_CASE(case_148_multi);
TEST_CASE(case_149_multi);
TEST_CASE_WITH(issue_1221, 0, 1, ut_settings().ignore_validity_diff());
@ -274,7 +276,32 @@ int test_main(int, char* [])
TEST_CASE_WITH(issue_1349, 0, 1, ut_settings().ignore_diff());
TEST_CASE(issue_1349_inverse);
TEST_CASE(issue_1350_comment);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
// Fails in nearly all operations
TEST_CASE(issue_1363);
#endif
TEST_CASE(case_bitset_1);
TEST_CASE(case_bitset_2);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
// Needs a fix in assign_parents
TEST_CASE(case_bitset_3);
#endif
TEST_CASE(case_recursive_boxes_89);
TEST_CASE(case_recursive_boxes_90);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_CASE(case_recursive_boxes_91);
#endif
TEST_CASE(case_recursive_boxes_92);
TEST_CASE(case_recursive_boxes_93);
TEST_CASE(case_recursive_boxes_94);
TEST_CASE(case_recursive_boxes_95);
TEST_CASE(case_recursive_boxes_96);
TEST_CASE(case_recursive_boxes_97);
TEST_CASE(case_recursive_boxes_98);
TEST_CASE(case_recursive_boxes_99);
TEST_CASE_WITH(case_recursive_boxes_99, 2, 3, ut_settings());
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
// Fails in union or intersection, and in difference. Also the union is invalid.
@ -282,4 +309,4 @@ int test_main(int, char* [])
#endif
return 0;
}
}

View File

@ -5,6 +5,37 @@
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
function(boost_geometry_add_robustness_test item)
set(robustness_test_name "boost_geometry_robustness_${item}")
add_executable(${robustness_test_name} ${item}.cpp)
# Add a dependency to Boost.Geometry
target_link_libraries(${robustness_test_name}
PRIVATE
Boost::geometry)
# Include the main Geometry test folder and the current folder,
# and the robustness test folder
target_include_directories(${robustness_test_name}
PRIVATE
"${PROJECT_SOURCE_DIR}/test/robustness"
"${PROJECT_SOURCE_DIR}/test"
"${PROJECT_SOURCE_DIR}/index/test"
.)
# To compile with C++14
target_compile_features(${robustness_test_name} PRIVATE cxx_std_14)
# Add a dependency to the global robustness tests target
add_dependencies(robustness_tests ${robustness_test_name})
endfunction()
if (NOT TARGET robustness_tests)
add_custom_target(robustness_tests)
endif()
add_subdirectory(convex_hull)
add_subdirectory(overlay)
#add_subdirectory(within)

View File

@ -1,25 +1,24 @@
# Boost.Geometry
#
# Copyright (c) 2025 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2024, Oracle and/or its affiliates.
# Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
foreach(item IN ITEMS
#general_intersection_precision
general_intersection_precision
interior_triangles
intersection_pies
intersection_stars
intersects
random_bitset_grids
random_ellipses_stars
recursive_polygons
star_comb
#ticket_9081
random_bitset_grids
)
boost_geometry_add_unit_test("robustness" ${item})
target_include_directories(${BOOST_GEOMETRY_UNIT_TEST_NAME}
PRIVATE
"${PROJECT_SOURCE_DIR}/test/robustness"
.)
boost_geometry_add_robustness_test(${item})
endforeach()

View File

@ -12,17 +12,19 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_GEOMETRY_NO_BOOST_TEST
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <geometry_test_common.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <geometry_test_common.hpp>
// Basic case. Union should deliver 22.0
static std::string case_a[2] =
{
@ -207,18 +209,17 @@ std::size_t test_all(std::size_t case_index, std::size_t min_vertex_index,
std::cout << case_index
<< " #cases: " << n << " #errors: " << error_count << std::endl;
BOOST_CHECK_EQUAL(error_count, 0u);
return error_count;
}
int test_main(int argc, char** argv)
int main(int argc, char** argv)
{
BoostGeometryWriteTestConfiguration();
using coor_t = default_test_type;
test_settings settings;
settings.do_output = argc > 2 && atol(argv[2]) == 1;
settings.do_output = true;
// Test three polygons, for the last test two types of intersections
test_all<coor_t, true, bg::overlay_union>(1, 0, 3, 22.0, settings);

View File

@ -10,9 +10,5 @@ foreach(item IN ITEMS
#multi_point_growth
recursive_polygons_buffer
)
boost_geometry_add_unit_test("robustness" ${item})
target_include_directories(${BOOST_GEOMETRY_UNIT_TEST_NAME}
PRIVATE
"${PROJECT_SOURCE_DIR}/test/robustness"
.)
boost_geometry_add_robustness_test(${item})
endforeach()