mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-31 08:12:13 +00:00
Merge branch 'develop' of https://github.com/boostorg/geometry into develop
This commit is contained in:
@@ -1471,7 +1471,8 @@ struct buffered_piece_collection
|
||||
// negative rings (negative child with negative parent)
|
||||
detail::overlay::assign_parents(offsetted_rings, traversed_rings,
|
||||
selected, m_intersection_strategy, true, false);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out,
|
||||
m_area_strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -62,6 +62,13 @@ inline void convert_and_add(GeometryOut& result,
|
||||
}
|
||||
}
|
||||
|
||||
enum add_rings_error_handling
|
||||
{
|
||||
add_rings_ignore_unordered,
|
||||
add_rings_add_unordered,
|
||||
add_rings_throw_if_reversed
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryOut,
|
||||
@@ -69,17 +76,18 @@ template
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RingCollection,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename AreaStrategy
|
||||
>
|
||||
inline OutputIterator add_rings(SelectionMap const& map,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RingCollection const& collection,
|
||||
OutputIterator out,
|
||||
bool require_positive_area = true)
|
||||
AreaStrategy const& area_strategy,
|
||||
add_rings_error_handling error_handling = add_rings_ignore_unordered)
|
||||
{
|
||||
typedef typename SelectionMap::const_iterator iterator;
|
||||
typedef typename SelectionMap::mapped_type property_type;
|
||||
typedef typename property_type::area_type area_type;
|
||||
typedef typename AreaStrategy::return_type area_type;
|
||||
|
||||
area_type const zero = 0;
|
||||
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
|
||||
@@ -123,11 +131,22 @@ inline OutputIterator add_rings(SelectionMap const& map,
|
||||
// Only add rings if they satisfy minimal requirements.
|
||||
// This cannot be done earlier (during traversal), not
|
||||
// everything is figured out yet (sum of positive/negative rings)
|
||||
if (geometry::num_points(result) >= min_num_points
|
||||
&& (! require_positive_area
|
||||
|| math::larger(geometry::area(result), zero)))
|
||||
if (geometry::num_points(result) >= min_num_points)
|
||||
{
|
||||
*out++ = result;
|
||||
area_type const area = geometry::area(result, area_strategy);
|
||||
// Ignore if area is 0
|
||||
if (! math::equals(area, zero))
|
||||
{
|
||||
if (error_handling == add_rings_add_unordered
|
||||
|| area > zero)
|
||||
{
|
||||
*out++ = result;
|
||||
}
|
||||
else if (error_handling == add_rings_throw_if_reversed)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(invalid_output_exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,15 +160,17 @@ template
|
||||
typename SelectionMap,
|
||||
typename Geometry,
|
||||
typename RingCollection,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename AreaStrategy
|
||||
>
|
||||
inline OutputIterator add_rings(SelectionMap const& map,
|
||||
Geometry const& geometry,
|
||||
RingCollection const& collection,
|
||||
OutputIterator out)
|
||||
OutputIterator out,
|
||||
AreaStrategy const& area_strategy)
|
||||
{
|
||||
Geometry empty;
|
||||
return add_rings<GeometryOut>(map, geometry, empty, collection, out);
|
||||
return add_rings<GeometryOut>(map, geometry, empty, collection, out, area_strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -234,7 +234,8 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
|
||||
select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them, strategy);
|
||||
ring_container_type rings;
|
||||
assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy);
|
||||
return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
|
||||
return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out,
|
||||
strategy.template get_area_strategy<point_type1>());
|
||||
}
|
||||
|
||||
|
||||
@@ -370,9 +371,8 @@ std::cout << "traverse" << std::endl;
|
||||
selected_ring_properties, strategy);
|
||||
|
||||
// Add rings created during traversal
|
||||
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
|
||||
{
|
||||
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
|
||||
|
||||
ring_identifier id(2, 0, -1);
|
||||
for (typename boost::range_iterator<ring_container_type>::type
|
||||
it = boost::begin(rings);
|
||||
@@ -390,10 +390,18 @@ std::cout << "traverse" << std::endl;
|
||||
// NOTE: There is no need to check result area for union because
|
||||
// as long as the polygons in the input are valid the resulting
|
||||
// polygons should be valid as well.
|
||||
// This also solves the issue with non-cartesian CSes, the result may
|
||||
// be too big so the area is negative but it's returned anyway.
|
||||
// This also solves the issue with non-cartesian CSes. The result may
|
||||
// be too big, so the area is negative. In this case either it's returned
|
||||
// anyway (default) or an exception is thrown (based on #define).
|
||||
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out,
|
||||
OverlayType != overlay_union);
|
||||
area_strategy,
|
||||
OverlayType == overlay_union ?
|
||||
#ifdef BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION
|
||||
add_rings_throw_if_reversed
|
||||
#else
|
||||
add_rings_add_unordered
|
||||
#endif
|
||||
: add_rings_ignore_unordered);
|
||||
}
|
||||
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2017.
|
||||
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -83,6 +83,25 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Invalid Output Exception
|
||||
\ingroup core
|
||||
\details The invalid_output_exception is thrown if valid output cannot be
|
||||
generated by a function even if arguments are valid, e.g. union of
|
||||
geographic polygons covering more than half of the area of the globe.
|
||||
*/
|
||||
class invalid_output_exception : public geometry::exception
|
||||
{
|
||||
public:
|
||||
|
||||
inline invalid_output_exception() {}
|
||||
|
||||
virtual char const* what() const throw()
|
||||
{
|
||||
return "Boost.Geometry Invalid-Output exception";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
@@ -246,9 +246,8 @@ struct dissolve_ring_or_polygon
|
||||
detail::overlay::select_rings<overlay_dissolve_union>(geometry, turn_info_per_ring, selected, strategy);
|
||||
|
||||
// Add intersected rings
|
||||
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
|
||||
{
|
||||
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
|
||||
|
||||
ring_identifier id(2, 0, -1);
|
||||
for (typename boost::range_iterator<std::vector<ring_type> const>::type
|
||||
it = boost::begin(rings);
|
||||
@@ -264,7 +263,7 @@ struct dissolve_ring_or_polygon
|
||||
// children with negative parents
|
||||
detail::overlay::assign_parents(geometry, rings, selected,
|
||||
strategy, true, true);
|
||||
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out);
|
||||
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out, area_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -58,21 +58,36 @@ void test_geographic_one(std::string const& wkt1, std::string const& wkt2,
|
||||
boost::geometry::read_wkt(wkt2, p2);
|
||||
|
||||
multipolygon result;
|
||||
boost::geometry::union_(p1, p2, result, is);
|
||||
|
||||
double result_area = bg::area(result, as);
|
||||
#ifdef BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION
|
||||
if (expected_area >= 0)
|
||||
{
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
boost::geometry::union_(p1, p2, result, is);
|
||||
|
||||
std::size_t result_count = boost::size(result);
|
||||
std::size_t result_exterior_points = std::for_each(boost::begin(result),
|
||||
boost::end(result),
|
||||
exterior_points_counter()).count;
|
||||
std::size_t result_interiors = std::for_each(boost::begin(result),
|
||||
boost::end(result),
|
||||
interiors_counter()).count;
|
||||
BOOST_CHECK_EQUAL(result_count, count);
|
||||
BOOST_CHECK_EQUAL(result_exterior_points, exterior_points_count);
|
||||
BOOST_CHECK_EQUAL(result_interiors, interiors_count);
|
||||
BOOST_CHECK_CLOSE(result_area, expected_area, 0.001);
|
||||
double result_area = bg::area(result, as);
|
||||
|
||||
std::size_t result_count = boost::size(result);
|
||||
std::size_t result_exterior_points = std::for_each(boost::begin(result),
|
||||
boost::end(result),
|
||||
exterior_points_counter()).count;
|
||||
std::size_t result_interiors = std::for_each(boost::begin(result),
|
||||
boost::end(result),
|
||||
interiors_counter()).count;
|
||||
BOOST_CHECK_EQUAL(result_count, count);
|
||||
BOOST_CHECK_EQUAL(result_exterior_points, exterior_points_count);
|
||||
BOOST_CHECK_EQUAL(result_interiors, interiors_count);
|
||||
BOOST_CHECK_CLOSE(result_area, expected_area, 0.001);
|
||||
}
|
||||
#ifdef BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION
|
||||
else
|
||||
{
|
||||
BOOST_CHECK_THROW(boost::geometry::union_(p1, p2, result, is),
|
||||
bg::invalid_output_exception);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user