Merge branch 'develop' into feature/intvalid

# Conflicts:
#	test/algorithms/overlay/overlay_cases.hpp
#	test/algorithms/set_operations/intersection/intersection.cpp
#	test/algorithms/set_operations/union/union.cpp
This commit is contained in:
Barend Gehrels 2017-05-06 18:26:49 +02:00
commit e52e2a8665
32 changed files with 958 additions and 311 deletions

View File

@ -109,7 +109,7 @@ test:
#- cd $BOOST_ROOT/libs/geometry && index=0 ; run_tests() { for i in "$1"/* ; do if [ -f "$i"/Jamfile* ] ; then ((index++)) ; echo "$index - $i" ; ../../b2 cxxflags="--coverage" linkflags="--coverage" "$i" ; run_tests "$i" ; fi ; done } ; run_tests test
# so for now just run the tests from the list
- cd $BOOST_ROOT/libs/geometry && status=0; index=0 ; for t in ${TESTS[@]} ; do if [ $(((index++)%CIRCLE_NODE_TOTAL)) == $CIRCLE_NODE_INDEX ] ; then ../../b2 cxxflags="--coverage" linkflags="--coverage" $t ; fi || status=$? ; done ; exit $status :
- cd $BOOST_ROOT/libs/geometry && status=0; index=0 ; for t in ${TESTS[@]} ; do if [ $(((index++)%CIRCLE_NODE_TOTAL)) == $CIRCLE_NODE_INDEX ] ; then ../../b2 -j2 cxxflags="--coverage" linkflags="--coverage" $t ; fi || status=$? ; done ; exit $status :
parallel: true
post:

View File

@ -1431,7 +1431,7 @@ struct buffered_piece_collection
}
}
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, m_intersection_strategy, true);
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
}

View File

@ -118,15 +118,21 @@ private:
}
};
// TODO: After adding non-cartesian Segment envelope to the library
// this policy should be modified to take envelope strategy.
template <typename EnvelopeStrategy>
struct expand_box_segment
{
explicit expand_box_segment(EnvelopeStrategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Segment>
static inline void apply(Box& total, Segment const& segment)
inline void apply(Box& total, Segment const& segment) const
{
geometry::expand(total, geometry::return_envelope<Box>(segment));
geometry::expand(total,
geometry::return_envelope<Box>(segment, m_strategy));
}
EnvelopeStrategy const& m_strategy;
};
struct overlaps_box_point
@ -143,24 +149,20 @@ private:
}
};
// TODO: After implementing disjoint Segment/Box for non-cartesian geometries
// this strategy should be passed here.
// TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy
// which by default is winding containing CS-specific side strategy
// TODO: disjoint Segment/Box will be called in this case which may take
// quite long in non-cartesian CS. So we should consider passing range of bounding boxes
// of segments after calculating them once.
template <typename DisjointStrategy>
struct overlaps_box_segment
{
explicit overlaps_box_segment(DisjointStrategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Segment>
static inline bool apply(Box const& box, Segment const& segment)
inline bool apply(Box const& box, Segment const& segment) const
{
typedef typename strategy::disjoint::services::default_strategy
<
Segment, Box
>::type strategy_type;
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
}
DisjointStrategy const& m_strategy;
};
template <typename PtSegStrategy>
@ -222,12 +224,22 @@ public:
{
item_visitor_type<Strategy> visitor(strategy);
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
// TODO: disjoint Segment/Box may be called in partition multiple times
// possibly for non-cartesian segments which could be slow. We should consider
// passing a range of bounding boxes of segments after calculating them once.
// Alternatively instead of a range of segments a range of Segment/Envelope pairs
// should be passed, where envelope would be lazily calculated when needed the first time
geometry::partition
<
geometry::model::box<typename point_type<MultiPoint>::type>
>::apply(multipoint, segment_range(linear), visitor,
expand_box_point(), overlaps_box_point(),
expand_box_segment(), overlaps_box_segment());
expand_box_point(),
overlaps_box_point(),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
return ! visitor.intersection_found();
}

View File

@ -76,14 +76,16 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
typename VisitPolicy
typename VisitPolicy,
typename Strategy
>
static inline
bool are_polygon_interiors_disjoint(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
boost::ignore_unused(visitor);
@ -95,26 +97,42 @@ private:
multi_indices.insert(tit->operations[1].seg_id.multi_index);
}
typedef geometry::model::box<typename point_type<MultiPolygon>::type> box_type;
typedef typename base::template partition_item<PolygonIterator, box_type> item_type;
// put polygon iterators without turns in a vector
std::vector<PolygonIterator> polygon_iterators;
std::vector<item_type> polygon_iterators;
signed_size_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
++it, ++multi_index)
{
if (multi_indices.find(multi_index) == multi_indices.end())
{
polygon_iterators.push_back(it);
polygon_iterators.push_back(item_type(it));
}
}
typename base::item_visitor_type item_visitor;
// prepare strategies
typedef typename std::iterator_traits<PolygonIterator>::value_type polygon_type;
typedef typename Strategy::template point_in_geometry_strategy
<
polygon_type, polygon_type
>::type within_strategy_type;
within_strategy_type const within_strategy
= strategy.template get_point_in_geometry_strategy<polygon_type, polygon_type>();
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
envelope_strategy_type const envelope_strategy
= strategy.get_envelope_strategy();
// call partition to check if polygons are disjoint from each other
typename base::template item_visitor_type<within_strategy_type> item_visitor(within_strategy);
geometry::partition
<
geometry::model::box<typename point_type<MultiPolygon>::type>
>::apply(polygon_iterators, item_visitor,
typename base::expand_box(),
typename base::overlaps_box());
typename base::template expand_box<envelope_strategy_type>(envelope_strategy),
typename base::template overlaps_box<envelope_strategy_type>(envelope_strategy));
if (item_visitor.items_overlap)
{
@ -155,13 +173,15 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
typename VisitPolicy
typename VisitPolicy,
typename Strategy
>
static inline bool apply(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
signed_size_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
@ -185,7 +205,8 @@ private:
if (! Predicate::apply(*it,
filtered_turns_first,
filtered_turns_beyond,
visitor))
visitor,
strategy))
{
return false;
}
@ -200,19 +221,21 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
typename VisitPolicy
typename VisitPolicy,
typename Strategy
>
static inline bool have_holes_inside(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
return has_property_per_polygon
<
typename base::has_holes_inside
>::apply(polygons_first, polygons_beyond,
turns_first, turns_beyond, visitor);
turns_first, turns_beyond, visitor, strategy);
}
@ -221,19 +244,21 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
typename VisitPolicy
typename VisitPolicy,
typename Strategy
>
static inline bool have_connected_interior(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
return has_property_per_polygon
<
typename base::has_connected_interior
>::apply(polygons_first, polygons_beyond,
turns_first, turns_beyond, visitor);
turns_first, turns_beyond, visitor, strategy);
}
@ -307,7 +332,8 @@ public:
boost::end(multipolygon),
turns.begin(),
turns.end(),
visitor))
visitor,
strategy))
{
return false;
}
@ -320,7 +346,8 @@ public:
boost::end(multipolygon),
turns.begin(),
turns.end(),
visitor))
visitor,
strategy))
{
return false;
}
@ -332,7 +359,8 @@ public:
boost::end(multipolygon),
turns.begin(),
turns.end(),
visitor);
visitor,
strategy);
}
};

View File

@ -144,39 +144,85 @@ protected:
};
// Iterator value_type is a Ring or Polygon
template <typename Iterator, typename Box>
struct partition_item
{
explicit partition_item(Iterator it)
: m_it(it)
, m_is_initialized(false)
{}
Iterator get() const
{
return m_it;
}
template <typename EnvelopeStrategy>
Box const& get_envelope(EnvelopeStrategy const& strategy) const
{
if (! m_is_initialized)
{
m_box = geometry::return_envelope<Box>(*m_it, strategy);
m_is_initialized = true;
}
return m_box;
}
private:
Iterator m_it;
mutable Box m_box;
mutable bool m_is_initialized;
};
// structs for partition -- start
template <typename EnvelopeStrategy>
struct expand_box
{
explicit expand_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
template <typename Box, typename Iterator>
static inline void apply(Box& total, Iterator const& it)
inline void apply(Box& total, partition_item<Iterator, Box> const& item) const
{
geometry::expand(total, geometry::return_envelope<Box>(*it));
geometry::expand(total, item.get_envelope(m_strategy));
}
EnvelopeStrategy const& m_strategy;
};
template <typename EnvelopeStrategy>
struct overlaps_box
{
explicit overlaps_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
template <typename Box, typename Iterator>
static inline bool apply(Box const& box, Iterator const& it)
inline bool apply(Box const& box, partition_item<Iterator, Box> const& item) const
{
return ! geometry::disjoint(*it, box);
return ! geometry::disjoint(item.get_envelope(m_strategy), box);
}
EnvelopeStrategy const& m_strategy;
};
template <typename WithinStrategy>
struct item_visitor_type
{
bool items_overlap;
WithinStrategy const& m_strategy;
item_visitor_type() : items_overlap(false) {}
explicit item_visitor_type(WithinStrategy const& strategy)
: items_overlap(false)
, m_strategy(strategy)
{}
template <typename Item1, typename Item2>
inline bool apply(Item1 const& item1, Item2 const& item2)
template <typename Iterator, typename Box>
inline bool apply(partition_item<Iterator, Box> const& item1,
partition_item<Iterator, Box> const& item2)
{
if (! items_overlap
&& (geometry::within(*points_begin(*item1), *item2)
|| geometry::within(*points_begin(*item2), *item1))
&& (geometry::within(*points_begin(*item1.get()), *item2.get(), m_strategy)
|| geometry::within(*points_begin(*item2.get()), *item1.get(), m_strategy))
)
{
items_overlap = true;
@ -193,14 +239,16 @@ protected:
typename RingIterator,
typename ExteriorRing,
typename TurnIterator,
typename VisitPolicy
typename VisitPolicy,
typename Strategy
>
static inline bool are_holes_inside(RingIterator rings_first,
RingIterator rings_beyond,
ExteriorRing const& exterior_ring,
TurnIterator turns_first,
TurnIterator turns_beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
boost::ignore_unused(visitor);
@ -221,6 +269,14 @@ protected:
}
}
// prepare strategy
typedef typename std::iterator_traits<RingIterator>::value_type inter_ring_type;
typename Strategy::template point_in_geometry_strategy
<
inter_ring_type, ExteriorRing
>::type const in_exterior_strategy
= strategy.template get_point_in_geometry_strategy<inter_ring_type, ExteriorRing>();
signed_size_type ring_index = 0;
for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index)
@ -228,7 +284,7 @@ protected:
// do not examine interior rings that have turns with the
// exterior ring
if (ring_indices.find(ring_index) == ring_indices.end()
&& ! geometry::covered_by(range::front(*it), exterior_ring))
&& ! geometry::covered_by(range::front(*it), exterior_ring, in_exterior_strategy))
{
return visitor.template apply<failure_interior_rings_outside>();
}
@ -241,26 +297,42 @@ protected:
ring_indices.insert(tit->operations[1].seg_id.ring_index);
}
typedef geometry::model::box<typename point_type<Polygon>::type> box_type;
typedef partition_item<RingIterator, box_type> item_type;
// put iterators for interior rings without turns in a vector
std::vector<RingIterator> ring_iterators;
std::vector<item_type> ring_iterators;
ring_index = 0;
for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index)
{
if (ring_indices.find(ring_index) == ring_indices.end())
{
ring_iterators.push_back(it);
ring_iterators.push_back(item_type(it));
}
}
// call partition to check is interior rings are disjoint from
// prepare strategies
typedef typename Strategy::template point_in_geometry_strategy
<
inter_ring_type, inter_ring_type
>::type in_interior_strategy_type;
in_interior_strategy_type const in_interior_strategy
= strategy.template get_point_in_geometry_strategy<inter_ring_type, inter_ring_type>();
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
envelope_strategy_type const envelope_strategy
= strategy.get_envelope_strategy();
// call partition to check if interior rings are disjoint from
// each other
item_visitor_type item_visitor;
item_visitor_type<in_interior_strategy_type> item_visitor(in_interior_strategy);
geometry::partition
<
geometry::model::box<typename point_type<Polygon>::type>
>::apply(ring_iterators, item_visitor, expand_box(), overlaps_box());
box_type
>::apply(ring_iterators, item_visitor,
expand_box<envelope_strategy_type>(envelope_strategy),
overlaps_box<envelope_strategy_type>(envelope_strategy));
if (item_visitor.items_overlap)
{
@ -277,35 +349,40 @@ protected:
typename InteriorRings,
typename ExteriorRing,
typename TurnIterator,
typename VisitPolicy
typename VisitPolicy,
typename Strategy
>
static inline bool are_holes_inside(InteriorRings const& interior_rings,
ExteriorRing const& exterior_ring,
TurnIterator first,
TurnIterator beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
return are_holes_inside(boost::begin(interior_rings),
boost::end(interior_rings),
exterior_ring,
first,
beyond,
visitor);
visitor,
strategy);
}
struct has_holes_inside
{
template <typename TurnIterator, typename VisitPolicy>
template <typename TurnIterator, typename VisitPolicy, typename Strategy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
TurnIterator beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& strategy)
{
return are_holes_inside(geometry::interior_rings(polygon),
geometry::exterior_ring(polygon),
first,
beyond,
visitor);
visitor,
strategy);
}
};
@ -314,11 +391,12 @@ protected:
struct has_connected_interior
{
template <typename TurnIterator, typename VisitPolicy>
template <typename TurnIterator, typename VisitPolicy, typename Strategy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
TurnIterator beyond,
VisitPolicy& visitor)
VisitPolicy& visitor,
Strategy const& )
{
boost::ignore_unused(visitor);
@ -392,7 +470,8 @@ public:
if (! has_holes_inside::apply(polygon,
turns.begin(), turns.end(),
visitor))
visitor,
strategy))
{
return false;
}
@ -403,7 +482,8 @@ public:
return has_connected_interior::apply(polygon,
turns.begin(),
turns.end(),
visitor);
visitor,
strategy);
}
};

View File

@ -20,7 +20,8 @@
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/geometries/box.hpp>
@ -37,30 +38,70 @@ namespace detail { namespace overlay
template
<
typename Item,
typename InnerGeometry,
typename Geometry1, typename Geometry2,
typename RingCollection
typename RingCollection,
typename Strategy
>
static inline bool within_selected_input(Item const& item2, ring_identifier const& ring_id,
static inline bool within_selected_input(Item const& item2,
InnerGeometry const& inner_geometry,
ring_identifier const& outer_id,
Geometry1 const& geometry1, Geometry2 const& geometry2,
RingCollection const& collection)
RingCollection const& collection,
Strategy const& strategy)
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
switch (ring_id.source_index)
// NOTE: range_in_geometry first checks the item2.point and then
// if this point is on boundary it checks points of inner_geometry
// ring until a point inside/outside other geometry ring is found
switch (outer_id.source_index)
{
// covered_by
case 0 :
return range_in_geometry(item2.point, inner_geometry,
get_ring<tag1>::apply(outer_id, geometry1), strategy) >= 0;
case 1 :
return range_in_geometry(item2.point, inner_geometry,
get_ring<tag2>::apply(outer_id, geometry2), strategy) >= 0;
case 2 :
return range_in_geometry(item2.point, inner_geometry,
get_ring<void>::apply(outer_id, collection), strategy) >= 0;
}
return false;
}
template
<
typename Item,
typename Geometry1, typename Geometry2,
typename RingCollection,
typename Strategy
>
static inline bool within_selected_input(Item const& item2,
ring_identifier const& inner_id, ring_identifier const& outer_id,
Geometry1 const& geometry1, Geometry2 const& geometry2,
RingCollection const& collection,
Strategy const& strategy)
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
switch (inner_id.source_index)
{
case 0 :
return geometry::within(item2.point,
get_ring<tag1>::apply(ring_id, geometry1));
break;
return within_selected_input(item2,
get_ring<tag1>::apply(inner_id, geometry1),
outer_id, geometry1, geometry2, collection, strategy);
case 1 :
return geometry::within(item2.point,
get_ring<tag2>::apply(ring_id, geometry2));
break;
return within_selected_input(item2,
get_ring<tag2>::apply(inner_id, geometry2),
outer_id, geometry1, geometry2, collection, strategy);
case 2 :
return geometry::within(item2.point,
get_ring<void>::apply(ring_id, collection));
break;
return within_selected_input(item2,
get_ring<void>::apply(inner_id, collection),
outer_id, geometry1, geometry2, collection, strategy);
}
return false;
}
@ -104,7 +145,14 @@ struct ring_info_helper_ovelaps_box
}
};
template <typename Geometry1, typename Geometry2, typename Collection, typename RingMap>
template
<
typename Geometry1,
typename Geometry2,
typename Collection,
typename RingMap,
typename Strategy
>
struct assign_visitor
{
typedef typename RingMap::mapped_type ring_info_type;
@ -113,14 +161,16 @@ struct assign_visitor
Geometry2 const& m_geometry2;
Collection const& m_collection;
RingMap& m_ring_map;
Strategy const& m_strategy;
bool m_check_for_orientation;
inline assign_visitor(Geometry1 const& g1, Geometry2 const& g2, Collection const& c,
RingMap& map, bool check)
RingMap& map, Strategy const& strategy, bool check)
: m_geometry1(g1)
, m_geometry2(g2)
, m_collection(c)
, m_ring_map(map)
, m_strategy(strategy)
, m_check_for_orientation(check)
{}
@ -140,8 +190,10 @@ struct assign_visitor
{
ring_info_type& inner_in_map = m_ring_map[inner.id];
if (geometry::within(inner_in_map.point, outer.envelope)
&& within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection)
if (geometry::covered_by(inner_in_map.point, outer.envelope)
&& within_selected_input(inner_in_map, inner.id, outer.id,
m_geometry1, m_geometry2, m_collection,
m_strategy)
)
{
// Assign a parent if there was no earlier parent, or the newly
@ -166,12 +218,14 @@ template
<
typename Geometry1, typename Geometry2,
typename RingCollection,
typename RingMap
typename RingMap,
typename Strategy
>
inline void assign_parents(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RingCollection const& collection,
RingMap& ring_map,
Strategy const& strategy,
bool check_for_orientation = false)
{
typedef typename geometry::tag<Geometry1>::type tag1;
@ -205,17 +259,21 @@ inline void assign_parents(Geometry1 const& geometry1,
{
case 0 :
geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
item.envelope);
item.envelope, strategy.get_envelope_strategy());
break;
case 1 :
geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
item.envelope);
item.envelope, strategy.get_envelope_strategy());
break;
case 2 :
geometry::envelope(get_ring<void>::apply(it->first, collection),
item.envelope);
item.envelope, strategy.get_envelope_strategy());
break;
}
// Expand envelope slightly
expand_by_epsilon(item.envelope);
if (item.real_area > 0)
{
count_positive++;
@ -258,8 +316,9 @@ inline void assign_parents(Geometry1 const& geometry1,
assign_visitor
<
Geometry1, Geometry2,
RingCollection, RingMap
> visitor(geometry1, geometry2, collection, ring_map, check_for_orientation);
RingCollection, RingMap,
Strategy
> visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation);
geometry::partition
<
@ -316,18 +375,20 @@ template
<
typename Geometry,
typename RingCollection,
typename RingMap
typename RingMap,
typename Strategy
>
inline void assign_parents(Geometry const& geometry,
RingCollection const& collection,
RingMap& ring_map,
Strategy const& strategy,
bool check_for_orientation)
{
// Call it with an empty geometry as second geometry (source_id == 1)
// (ring_map should be empty for source_id==1)
Geometry empty;
assign_parents(geometry, empty, collection, ring_map, check_for_orientation);
assign_parents(geometry, empty, collection, ring_map, strategy, check_for_orientation);
}

View File

@ -36,6 +36,7 @@
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/util/range.hpp>

View File

@ -2,10 +2,10 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, 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
@ -55,21 +55,14 @@ template
typename Turn,
typename Operation,
typename LineString,
typename Polygon
typename Polygon,
typename PtInPolyStrategy
>
static inline bool last_covered_by(Turn const& turn, Operation const& op,
LineString const& linestring, Polygon const& polygon)
LineString const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy)
{
// Check any point between the this one and the first IP
typedef typename geometry::point_type<LineString>::type point_type;
point_type point_in_between;
detail::point_on_border::midpoint_helper
<
point_type,
0, dimension<point_type>::value
>::apply(point_in_between, *(::boost::begin(linestring) + op.seg_id.segment_index), turn.point);
return geometry::covered_by(point_in_between, polygon);
return geometry::covered_by(range::at(linestring, op.seg_id.segment_index), polygon, strategy);
}
@ -78,17 +71,19 @@ template
typename Turn,
typename Operation,
typename LineString,
typename Polygon
typename Polygon,
typename PtInPolyStrategy
>
static inline bool is_leaving(Turn const& turn, Operation const& op,
bool entered, bool first,
LineString const& linestring, Polygon const& polygon)
LineString const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy)
{
if (op.operation == operation_union)
{
return entered
|| turn.method == method_crosses
|| (first && last_covered_by(turn, op, linestring, polygon))
|| (first && last_covered_by(turn, op, linestring, polygon, strategy))
;
}
return false;
@ -100,11 +95,13 @@ template
typename Turn,
typename Operation,
typename LineString,
typename Polygon
typename Polygon,
typename PtInPolyStrategy
>
static inline bool is_staying_inside(Turn const& turn, Operation const& op,
bool entered, bool first,
LineString const& linestring, Polygon const& polygon)
LineString const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy)
{
if (turn.method == method_crosses)
{
@ -115,7 +112,7 @@ static inline bool is_staying_inside(Turn const& turn, Operation const& op,
if (is_entering(turn, op))
{
return entered || (first && last_covered_by(turn, op, linestring, polygon));
return entered || (first && last_covered_by(turn, op, linestring, polygon, strategy));
}
return false;
@ -126,14 +123,16 @@ template
typename Turn,
typename Operation,
typename Linestring,
typename Polygon
typename Polygon,
typename PtInPolyStrategy
>
static inline bool was_entered(Turn const& turn, Operation const& op, bool first,
Linestring const& linestring, Polygon const& polygon)
Linestring const& linestring, Polygon const& polygon,
PtInPolyStrategy const& strategy)
{
if (first && (turn.method == method_collinear || turn.method == method_equal))
{
return last_covered_by(turn, op, linestring, polygon);
return last_covered_by(turn, op, linestring, polygon, strategy);
}
return false;
}
@ -235,17 +234,9 @@ struct action_selector<overlay_intersection, RemoveSpikes>
return entered;
}
template
<
typename Point,
typename Geometry,
typename RobustPolicy
>
static inline bool included(Point const& point,
Geometry const& geometry,
RobustPolicy const& )
static inline bool included(int inside_value)
{
return geometry::covered_by(point, geometry);
return inside_value >= 0; // covered_by
}
};
@ -319,17 +310,9 @@ struct action_selector<overlay_difference, RemoveSpikes>
return ! normal_action::is_entered(entered);
}
template
<
typename Point,
typename Geometry,
typename RobustPolicy
>
static inline bool included(Point const& point,
Geometry const& geometry,
RobustPolicy const& robust_policy)
static inline bool included(int inside_value)
{
return ! normal_action::included(point, geometry, robust_policy);
return ! normal_action::included(inside_value);
}
};
@ -403,33 +386,27 @@ class follow
public :
template
<
typename Point,
typename Geometry,
typename RobustPolicy
>
static inline bool included(Point const& point,
Geometry const& geometry,
RobustPolicy const& robust_policy)
static inline bool included(int inside_value)
{
return following::action_selector
<
OverlayType, RemoveSpikes
>::included(point, geometry, robust_policy);
>::included(inside_value);
}
template
<
typename Turns,
typename OutputIterator,
typename RobustPolicy
typename RobustPolicy,
typename Strategy
>
static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
detail::overlay::operation_type , // TODO: this parameter might be redundant
Turns& turns,
RobustPolicy const& robust_policy,
OutputIterator out)
OutputIterator out,
Strategy const& strategy)
{
typedef typename boost::range_iterator<Turns>::type turn_iterator;
typedef typename boost::range_value<Turns>::type turn_type;
@ -440,6 +417,12 @@ public :
typedef following::action_selector<OverlayType, RemoveSpikes> action;
typename Strategy::template point_in_geometry_strategy
<
LineString, Polygon
>::type const pt_in_poly_strategy
= strategy.template get_point_in_geometry_strategy<LineString, Polygon>();
// Sort intersection points on segments-along-linestring, and distance
// (like in enrich is done for poly/poly)
std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
@ -454,13 +437,13 @@ public :
{
turn_operation_iterator_type iit = boost::begin(it->operations);
if (following::was_entered(*it, *iit, first, linestring, polygon))
if (following::was_entered(*it, *iit, first, linestring, polygon, pt_in_poly_strategy))
{
debug_traverse(*it, *iit, "-> Was entered");
entered = true;
}
if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon))
if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
{
debug_traverse(*it, *iit, "-> Staying inside");
@ -476,7 +459,7 @@ public :
robust_policy,
out);
}
else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))
else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
{
debug_traverse(*it, *iit, "-> Leaving");

View File

@ -476,10 +476,13 @@ public:
sections_type sec1, sec2;
typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;
typename IntersectionStrategy::envelope_strategy_type const
envelope_strategy = intersection_strategy.get_envelope_strategy();
geometry::sectionalize<Reverse1, dimensions>(geometry1, robust_policy,
sec1, 0);
sec1, envelope_strategy, 0);
geometry::sectionalize<Reverse2, dimensions>(geometry2, robust_policy,
sec2, 1);
sec2, envelope_strategy, 1);
// ... and then partition them, intersecting overlapping sections in visitor method
section_visitor

View File

@ -30,10 +30,11 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
@ -288,6 +289,27 @@ struct intersection_of_linestring_with_areal
>::apply(boost::begin(turns), boost::end(turns));
}
template <typename Turns>
static inline int inside_or_outside_turn(Turns const& turns)
{
using namespace overlay;
for (typename Turns::const_iterator it = turns.begin();
it != turns.end(); ++it)
{
operation_type op0 = it->operations[0].operation;
operation_type op1 = it->operations[1].operation;
if (op0 == operation_intersection && op1 == operation_intersection)
{
return 1; // inside
}
else if (op0 == operation_union && op1 == operation_union)
{
return -1; // outside
}
}
return 0;
}
template
<
typename LineString, typename Areal,
@ -331,19 +353,21 @@ struct intersection_of_linestring_with_areal
if (no_crossing_turns_or_empty(turns))
{
// No intersection points, it is either completely
// No intersection points, it is either
// inside (interior + borders)
// or completely outside
// or outside (exterior + borders)
// Use border point (on a segment) to check this
// (because turn points might skip some cases)
point_type border_point;
if (! geometry::point_on_border(border_point, linestring, true))
// analyse the turns
int inside_value = inside_or_outside_turn(turns);
if (inside_value == 0)
{
return out;
// if needed analyse points of a linestring
// NOTE: range_in_geometry checks points of a linestring
// until a point inside/outside areal is found
inside_value = overlay::range_in_geometry(linestring, areal, strategy);
}
if (follower::included(border_point, areal, robust_policy))
// add point to the output if conditions are met
if (inside_value != 0 && follower::included(inside_value))
{
LineStringOut copy;
geometry::convert(linestring, copy);
@ -365,7 +389,7 @@ struct intersection_of_linestring_with_areal
(
linestring, areal,
geometry::detail::overlay::operation_intersection,
turns, robust_policy, out
turns, robust_policy, out, strategy
);
}
};

View File

@ -129,11 +129,11 @@ template
<
typename GeometryOut, overlay_type OverlayType, bool ReverseOut,
typename Geometry1, typename Geometry2,
typename OutputIterator
typename OutputIterator, typename Strategy
>
inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out)
OutputIterator out, Strategy const& strategy)
{
typedef std::deque
<
@ -165,9 +165,9 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
std::map<ring_identifier, ring_turn_info> empty;
std::map<ring_identifier, properties> all_of_one_of_them;
select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them);
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);
assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy);
return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
}
@ -202,7 +202,7 @@ struct overlay
return return_if_one_input_is_empty
<
GeometryOut, OverlayType, ReverseOut
>(geometry1, geometry2, out);
>(geometry1, geometry2, out, strategy);
}
typedef typename geometry::point_type<GeometryOut>::type point_type;
@ -292,7 +292,7 @@ std::cout << "traverse" << std::endl;
// Select all rings which are NOT touched by any intersection point
std::map<ring_identifier, properties> selected_ring_properties;
select_rings<OverlayType>(geometry1, geometry2, turn_info_per_ring,
selected_ring_properties);
selected_ring_properties, strategy);
// Add rings created during traversal
{
@ -308,7 +308,7 @@ std::cout << "traverse" << std::endl;
}
}
assign_parents(geometry1, geometry2, rings, selected_ring_properties);
assign_parents(geometry1, geometry2, rings, selected_ring_properties, strategy);
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
}

View File

@ -129,23 +129,55 @@ class multipoint_linear_point
{
private:
// structs for partition -- start
struct expand_box
struct expand_box_point
{
template <typename Box, typename Geometry>
static inline void apply(Box& total, Geometry const& geometry)
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
geometry::expand(total, geometry::return_envelope<Box>(geometry));
geometry::expand(total, point);
}
};
struct overlaps_box
template <typename EnvelopeStrategy>
struct expand_box_segment
{
template <typename Box, typename Geometry>
static inline bool apply(Box const& box, Geometry const& geometry)
explicit expand_box_segment(EnvelopeStrategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Segment>
inline void apply(Box& total, Segment const& segment) const
{
return ! geometry::disjoint(geometry, box);
geometry::expand(total,
geometry::return_envelope<Box>(segment, m_strategy));
}
EnvelopeStrategy const& m_strategy;
};
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
return ! geometry::disjoint(point, box);
}
};
template <typename DisjointStrategy>
struct overlaps_box_segment
{
explicit overlaps_box_segment(DisjointStrategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Segment>
inline bool apply(Box const& box, Segment const& segment) const
{
return ! geometry::disjoint(segment, box, m_strategy);
}
DisjointStrategy const& m_strategy;
};
template <typename OutputIterator, typename Strategy>
@ -206,16 +238,25 @@ private:
{
item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
segment_range rng(linear);
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
// TODO: disjoint Segment/Box may be called in partition multiple times
// possibly for non-cartesian segments which could be slow. We should consider
// passing a range of bounding boxes of segments after calculating them once.
// Alternatively instead of a range of segments a range of Segment/Envelope pairs
// should be passed, where envelope would be lazily calculated when needed the first time
geometry::partition
<
geometry::model::box
<
typename boost::range_value<MultiPoint>::type
>
>::apply(multipoint, rng, item_visitor,
expand_box(), overlaps_box());
>::apply(multipoint, segment_range(linear), item_visitor,
expand_box_point(),
overlaps_box_point(),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
return oit;
}

View File

@ -0,0 +1,178 @@
// Boost.Geometry
// Copyright (c) 2017 Oracle and/or its affiliates.
// 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_RANGE_IN_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
template
<
typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type
>
struct points_range
{
typedef geometry::point_iterator<Geometry const> iterator_type;
explicit points_range(Geometry const& geometry)
: m_geometry(geometry)
{}
iterator_type begin() const
{
return geometry::points_begin(m_geometry);
}
iterator_type end() const
{
return geometry::points_end(m_geometry);
}
Geometry const& m_geometry;
};
// Specialized because point_iterator doesn't support boxes
template <typename Box>
struct points_range<Box, box_tag>
{
typedef typename geometry::point_type<Box>::type point_type;
typedef const point_type * iterator_type;
explicit points_range(Box const& box)
{
detail::assign_box_corners(box,
m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
}
iterator_type begin() const
{
return m_corners;
}
iterator_type end() const
{
return m_corners + 4;
}
point_type m_corners[4];
};
template
<
typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type
>
struct point_in_geometry_helper
{
template <typename Point, typename Strategy>
static inline int apply(Point const& point, Geometry const& geometry,
Strategy const& strategy)
{
return detail::within::point_in_geometry(point, geometry, strategy);
}
};
// Specialized because point_in_geometry doesn't support Boxes
template <typename Box>
struct point_in_geometry_helper<Box, box_tag>
{
template <typename Point, typename Strategy>
static inline int apply(Point const& point, Box const& box,
Strategy const&)
{
return geometry::covered_by(point, box) ? 1 : -1;
}
};
// This function returns
// when it finds a point of geometry1 inside or outside geometry2
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline int range_in_geometry(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
bool skip_first = false)
{
int result = 0;
points_range<Geometry1> points(geometry1);
typedef typename points_range<Geometry1>::iterator_type iterator_type;
iterator_type const end = points.end();
iterator_type it = points.begin();
if (it == end)
{
return result;
}
else if (skip_first)
{
++it;
}
typename Strategy::template point_in_geometry_strategy
<
Geometry1, Geometry2
>::type const in_strategy
= strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
for ( ; it != end; ++it)
{
result = point_in_geometry_helper<Geometry2>::apply(*it, geometry2, in_strategy);
if (result != 0)
{
return result;
}
}
// all points contained entirely by the boundary
return result;
}
// This function returns if first_point1 is inside or outside geometry2 or
// when it finds a point of geometry1 inside or outside geometry2
template <typename Point1, typename Geometry1, typename Geometry2, typename Strategy>
inline int range_in_geometry(Point1 const& first_point1,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
// check a point on border of geometry1 first
int result = point_in_geometry_helper<Geometry2>::apply(first_point1, geometry2,
strategy.template get_point_in_geometry_strategy<Point1, Geometry2>());
if (result == 0)
{
// if a point is on boundary of geometry2
// check points of geometry1 until point inside/outside is found
// NOTE: skip first point because it should be already tested above
result = range_in_geometry(geometry1, geometry2, strategy, true);
}
return result;
}
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP

View File

@ -2,6 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// 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)
@ -59,10 +63,7 @@ struct ring_properties
, parent_area(-1)
{
this->area = geometry::area(ring_or_box);
// We should take a point somewhere in the middle of the ring,
// to avoid taking a point on a (self)tangency,
// in cases where multiple points come together
valid = geometry::point_on_border(this->point, ring_or_box, true);
valid = geometry::point_on_border(this->point, ring_or_box);
}
inline area_type get_area() const

View File

@ -3,6 +3,10 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// 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)
@ -18,9 +22,10 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
@ -221,20 +226,21 @@ struct decide<overlay_intersection>
}
};
template
<
overlay_type OverlayType,
typename Geometry1,
typename Geometry2,
typename TurnInfoMap,
typename RingPropertyMap
typename RingPropertyMap,
typename Strategy
>
inline void update_ring_selection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
TurnInfoMap const& turn_info_map,
RingPropertyMap const& all_ring_properties,
RingPropertyMap& selected_ring_properties)
RingPropertyMap& selected_ring_properties,
Strategy const& strategy)
{
selected_ring_properties.clear();
@ -263,11 +269,16 @@ inline void update_ring_selection(Geometry1 const& geometry1,
// a point lying on the ring
switch(id.source_index)
{
// within
case 0 :
info.within_other = geometry::within(it->second.point, geometry2);
info.within_other = range_in_geometry(it->second.point,
geometry1, geometry2,
strategy) > 0;
break;
case 1 :
info.within_other = geometry::within(it->second.point, geometry1);
info.within_other = range_in_geometry(it->second.point,
geometry2, geometry1,
strategy) > 0;
break;
}
@ -290,11 +301,13 @@ template
typename Geometry1,
typename Geometry2,
typename RingTurnInfoMap,
typename RingPropertyMap
typename RingPropertyMap,
typename Strategy
>
inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
RingTurnInfoMap const& turn_info_per_ring,
RingPropertyMap& selected_ring_properties)
RingPropertyMap& selected_ring_properties,
Strategy const& strategy)
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
@ -306,7 +319,8 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
ring_identifier(1, -1, -1), all_ring_properties);
update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,
all_ring_properties, selected_ring_properties);
all_ring_properties, selected_ring_properties,
strategy);
}
template
@ -314,11 +328,13 @@ template
overlay_type OverlayType,
typename Geometry,
typename RingTurnInfoMap,
typename RingPropertyMap
typename RingPropertyMap,
typename Strategy
>
inline void select_rings(Geometry const& geometry,
RingTurnInfoMap const& turn_info_per_ring,
RingPropertyMap& selected_ring_properties)
RingPropertyMap& selected_ring_properties,
Strategy const& strategy)
{
typedef typename geometry::tag<Geometry>::type tag;
@ -327,7 +343,8 @@ inline void select_rings(Geometry const& geometry,
ring_identifier(0, -1, -1), all_ring_properties);
update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,
all_ring_properties, selected_ring_properties);
all_ring_properties, selected_ring_properties,
strategy);
}

View File

@ -145,7 +145,8 @@ struct get_turns
typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
sections_type sec;
geometry::sectionalize<false, dimensions>(geometry, robust_policy, sec);
geometry::sectionalize<false, dimensions>(geometry, robust_policy, sec,
intersection_strategy.get_envelope_strategy());
self_section_visitor
<

View File

@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// 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.
@ -18,6 +22,7 @@
#include <cstddef>
#include <boost/range.hpp>
#include <boost/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
@ -29,6 +34,8 @@
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/util/condition.hpp>
namespace boost { namespace geometry
{
@ -39,10 +46,10 @@ namespace detail { namespace point_on_border
{
template<typename Point>
struct get_point
{
static inline bool apply(Point& destination, Point const& source, bool)
template <typename Point>
static inline bool apply(Point& destination, Point const& source)
{
destination = source;
return true;
@ -74,13 +81,17 @@ struct midpoint_helper<Point, DimensionCount, DimensionCount>
};
template<typename Point, typename Range>
template <bool Midpoint>
struct point_on_range
{
static inline bool apply(Point& point, Range const& range, bool midpoint)
template<typename Point, typename Range>
static inline bool apply(Point& point, Range const& range)
{
typedef typename geometry::cs_tag<Point>::type cs_tag;
BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value));
const std::size_t n = boost::size(range);
if (midpoint && n > 1)
if (Midpoint && n > 1)
{
typedef typename boost::range_iterator
<
@ -114,26 +125,27 @@ struct point_on_range
};
template<typename Point, typename Polygon>
template <bool Midpoint>
struct point_on_polygon
{
static inline bool apply(Point& point, Polygon const& polygon, bool midpoint)
template<typename Point, typename Polygon>
static inline bool apply(Point& point, Polygon const& polygon)
{
return point_on_range
<
Point,
typename ring_type<Polygon>::type
>::apply(point, exterior_ring(polygon), midpoint);
Midpoint
>::apply(point, exterior_ring(polygon));
}
};
template<typename Point, typename Box>
template <bool Midpoint>
struct point_on_box
{
static inline bool apply(Point& point, Box const& box, bool midpoint)
template<typename Point, typename Box>
static inline bool apply(Point& point, Box const& box)
{
if (midpoint)
if (BOOST_GEOMETRY_CONDITION(Midpoint))
{
Point p1, p2;
detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);
@ -154,15 +166,11 @@ struct point_on_box
};
template
<
typename Point,
typename MultiGeometry,
typename Policy
>
template <typename Policy>
struct point_on_multi
{
static inline bool apply(Point& point, MultiGeometry const& multi, bool midpoint)
template<typename Point, typename MultiGeometry>
static inline bool apply(Point& point, MultiGeometry const& multi)
{
// Take a point on the first multi-geometry
// (i.e. the first that is not empty)
@ -173,7 +181,7 @@ struct point_on_multi
it != boost::end(multi);
++it)
{
if (Policy::apply(point, *it, midpoint))
if (Policy::apply(point, *it))
{
return true;
}
@ -195,70 +203,57 @@ namespace dispatch
template
<
typename GeometryTag,
typename Point,
typename Geometry
bool Midpoint
>
struct point_on_border
{};
template<typename Point>
struct point_on_border<point_tag, Point, Point>
: detail::point_on_border::get_point<Point>
template <bool Midpoint>
struct point_on_border<point_tag, Midpoint>
: detail::point_on_border::get_point
{};
template<typename Point, typename Linestring>
struct point_on_border<linestring_tag, Point, Linestring>
: detail::point_on_border::point_on_range<Point, Linestring>
template <bool Midpoint>
struct point_on_border<linestring_tag, Midpoint>
: detail::point_on_border::point_on_range<Midpoint>
{};
template<typename Point, typename Ring>
struct point_on_border<ring_tag, Point, Ring>
: detail::point_on_border::point_on_range<Point, Ring>
template <bool Midpoint>
struct point_on_border<ring_tag, Midpoint>
: detail::point_on_border::point_on_range<Midpoint>
{};
template<typename Point, typename Polygon>
struct point_on_border<polygon_tag, Point, Polygon>
: detail::point_on_border::point_on_polygon<Point, Polygon>
template <bool Midpoint>
struct point_on_border<polygon_tag, Midpoint>
: detail::point_on_border::point_on_polygon<Midpoint>
{};
template<typename Point, typename Box>
struct point_on_border<box_tag, Point, Box>
: detail::point_on_border::point_on_box<Point, Box>
template <bool Midpoint>
struct point_on_border<box_tag, Midpoint>
: detail::point_on_border::point_on_box<Midpoint>
{};
template<typename Point, typename Multi>
struct point_on_border<multi_polygon_tag, Point, Multi>
template <bool Midpoint>
struct point_on_border<multi_polygon_tag, Midpoint>
: detail::point_on_border::point_on_multi
<
Point,
Multi,
detail::point_on_border::point_on_polygon
<
Point,
typename boost::range_value<Multi>::type
>
detail::point_on_border::point_on_polygon<Midpoint>
>
{};
template<typename Point, typename Multi>
struct point_on_border<multi_linestring_tag, Point, Multi>
template <bool Midpoint>
struct point_on_border<multi_linestring_tag, Midpoint>
: detail::point_on_border::point_on_multi
<
Point,
Multi,
detail::point_on_border::point_on_range
<
Point,
typename boost::range_value<Multi>::type
>
detail::point_on_border::point_on_range<Midpoint>
>
{};
@ -273,18 +268,12 @@ struct point_on_border<multi_linestring_tag, Point, Multi>
\tparam Geometry geometry type. This also defines the type of the output point
\param point to assign
\param geometry geometry to take point from
\param midpoint boolean flag, true if the point should not be a vertex, but some point
in between of two vertices
\return TRUE if successful, else false.
It is only false if polygon/line have no points
\note for a polygon, it is always a point on the exterior ring
\note for take_midpoint, it is not taken from two consecutive duplicate vertices,
(unless there are no other).
*/
template <typename Point, typename Geometry>
inline bool point_on_border(Point& point,
Geometry const& geometry,
bool midpoint = false)
inline bool point_on_border(Point& point, Geometry const& geometry)
{
concepts::check<Point>();
concepts::check<Geometry const>();
@ -292,12 +281,32 @@ inline bool point_on_border(Point& point,
return dispatch::point_on_border
<
typename tag<Geometry>::type,
Point,
Geometry
>::apply(point, geometry, midpoint);
false
>::apply(point, geometry);
}
/*!
\tparam Midpoint boolean flag, true if the point should not be a vertex, but some point
in between of two vertices
\note for Midpoint, it is not taken from two consecutive duplicate vertices,
(unless there are no other).
*/
/*
template <bool Midpoint, typename Point, typename Geometry>
inline bool point_on_border(Point& point, Geometry const& geometry)
{
concepts::check<Point>();
concepts::check<Geometry const>();
return dispatch::point_on_border
<
typename tag<Geometry>::type,
Midpoint
>::apply(point, geometry);
}
*/
}} // namespace boost::geometry

View File

@ -29,6 +29,8 @@
#include <boost/mpl/vector_c.hpp>
#include <boost/range.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
@ -54,6 +56,7 @@
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
@ -272,19 +275,21 @@ struct assign_loop<T, Count, Count>
template <typename CSTag>
struct box_first_in_section
{
template <typename Box, typename Point>
static inline void apply(Box & box, Point const& prev, Point const& curr)
template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& prev, Point const& curr,
Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
geometry::envelope(seg, box);
geometry::envelope(seg, box, strategy);
}
};
template <>
struct box_first_in_section<cartesian_tag>
{
template <typename Box, typename Point>
static inline void apply(Box & box, Point const& prev, Point const& curr)
template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& prev, Point const& curr,
Strategy const& )
{
geometry::envelope(prev, box);
geometry::expand(box, curr);
@ -294,19 +299,21 @@ struct box_first_in_section<cartesian_tag>
template <typename CSTag>
struct box_next_in_section
{
template <typename Box, typename Point>
static inline void apply(Box & box, Point const& prev, Point const& curr)
template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& prev, Point const& curr,
Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
geometry::expand(box, seg);
geometry::expand(box, seg, strategy);
}
};
template <>
struct box_next_in_section<cartesian_tag>
{
template <typename Box, typename Point>
static inline void apply(Box & box, Point const& , Point const& curr)
template <typename Box, typename Point, typename Strategy>
static inline void apply(Box & box, Point const& , Point const& curr,
Strategy const& )
{
geometry::expand(box, curr);
}
@ -334,6 +341,30 @@ struct sectionalize_part
RobustPolicy const& robust_policy,
ring_identifier ring_id,
std::size_t max_count)
{
typedef typename strategy::envelope::services::default_strategy
<
typename cs_tag<typename Sections::box_type>::type
>::type envelope_strategy_type;
apply(sections, begin, end,
robust_policy, envelope_strategy_type(),
ring_id, max_count);
}
template
<
typename Iterator,
typename RobustPolicy,
typename Sections,
typename EnvelopeStrategy
>
static inline void apply(Sections& sections,
Iterator begin, Iterator end,
RobustPolicy const& robust_policy,
EnvelopeStrategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
boost::ignore_unused_variable_warning(robust_policy);
@ -449,14 +480,14 @@ struct sectionalize_part
// In cartesian this is envelope of previous point expanded with current point
// in non-cartesian this is envelope of a segment
box_first_in_section<typename cs_tag<robust_point_type>::type>
::apply(section.bounding_box, previous_robust_point, current_robust_point);
::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy);
}
else
{
// In cartesian this is expand with current point
// in non-cartesian this is expand with a segment
box_next_in_section<typename cs_tag<robust_point_type>::type>
::apply(section.bounding_box, previous_robust_point, current_robust_point);
::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy);
}
section.end_index = index + 1;
@ -501,11 +532,13 @@ struct sectionalize_range
<
typename Range,
typename RobustPolicy,
typename Sections
typename Sections,
typename EnvelopeStrategy
>
static inline void apply(Range const& range,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
@ -534,7 +567,7 @@ struct sectionalize_range
sectionalize_part<Point, DimensionVector>::apply(sections,
boost::begin(view), boost::end(view),
robust_policy, ring_id, max_count);
robust_policy, strategy, ring_id, max_count);
}
};
@ -549,12 +582,15 @@ struct sectionalize_polygon
<
typename Polygon,
typename RobustPolicy,
typename Sections
typename Sections,
typename EnvelopeStrategy
>
static inline void apply(Polygon const& poly,
RobustPolicy const& robust_policy,
Sections& sections,
ring_identifier ring_id, std::size_t max_count)
EnvelopeStrategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
typedef typename point_type<Polygon>::type point_type;
typedef sectionalize_range
@ -564,7 +600,7 @@ struct sectionalize_polygon
> per_range;
ring_id.ring_index = -1;
per_range::apply(exterior_ring(poly), robust_policy, sections, ring_id, max_count);
per_range::apply(exterior_ring(poly), robust_policy, sections, strategy, ring_id, max_count);
ring_id.ring_index++;
typename interior_return_type<Polygon const>::type
@ -572,7 +608,7 @@ struct sectionalize_polygon
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
{
per_range::apply(*it, robust_policy, sections, ring_id, max_count);
per_range::apply(*it, robust_policy, sections, strategy, ring_id, max_count);
}
}
};
@ -584,11 +620,13 @@ struct sectionalize_box
<
typename Box,
typename RobustPolicy,
typename Sections
typename Sections,
typename EnvelopeStrategy
>
static inline void apply(Box const& box,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& ,
ring_identifier const& ring_id, std::size_t max_count)
{
typedef typename point_type<Box>::type point_type;
@ -613,12 +651,15 @@ struct sectionalize_box
points.push_back(lr);
points.push_back(ll);
// NOTE: Use cartesian envelope strategy in all coordinate systems
// because edges of a box are not geodesic segments
sectionalize_range
<
closed, false,
point_type,
DimensionVector
>::apply(points, robust_policy, sections,
strategy::envelope::cartesian_segment<>(),
ring_id, max_count);
}
};
@ -630,11 +671,15 @@ struct sectionalize_multi
<
typename MultiGeometry,
typename RobustPolicy,
typename Sections
typename Sections,
typename EnvelopeStrategy
>
static inline void apply(MultiGeometry const& multi,
RobustPolicy const& robust_policy,
Sections& sections, ring_identifier ring_id, std::size_t max_count)
Sections& sections,
EnvelopeStrategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
ring_id.multi_index = 0;
for (typename boost::range_iterator<MultiGeometry const>::type
@ -642,7 +687,7 @@ struct sectionalize_multi
it != boost::end(multi);
++it, ++ring_id.multi_index)
{
Policy::apply(*it, robust_policy, sections, ring_id, max_count);
Policy::apply(*it, robust_policy, sections, strategy, ring_id, max_count);
}
}
};
@ -814,14 +859,18 @@ template
typename DimensionVector,
typename Geometry,
typename Sections,
typename RobustPolicy
typename RobustPolicy,
typename EnvelopeStrategy
>
inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy,
Sections& sections,
EnvelopeStrategy const& strategy,
int source_index = 0,
std::size_t max_count = 10)
{
BOOST_STATIC_ASSERT((! boost::is_fundamental<EnvelopeStrategy>::value));
concepts::check<Geometry const>();
typedef typename boost::range_value<Sections>::type section_type;
@ -855,12 +904,36 @@ inline void sectionalize(Geometry const& geometry,
Geometry,
Reverse,
DimensionVector
>::apply(geometry, robust_policy, sections, ring_id, max_count);
>::apply(geometry, robust_policy, sections, strategy, ring_id, max_count);
detail::sectionalize::enlarge_sections(sections);
}
template
<
bool Reverse,
typename DimensionVector,
typename Geometry,
typename Sections,
typename RobustPolicy
>
inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy,
Sections& sections,
int source_index = 0,
std::size_t max_count = 10)
{
typedef typename strategy::envelope::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type envelope_strategy_type;
sectionalize<Reverse, DimensionVector>(geometry, robust_policy, sections,
envelope_strategy_type(),
source_index, max_count);
}
}} // namespace boost::geometry

View File

@ -298,7 +298,8 @@ struct dissolver_generic
typedef typename geometry::point_type<value_type>::type point_type;
typedef model::box<point_type> box_type;
// TODO: create and use envelope strategy
typename Strategy::envelope_strategy_type const
envelope_strategy = strategy.get_envelope_strategy();
typename Strategy::template area_strategy<value_type>::type const
area_strategy = strategy.template get_area_strategy<value_type>();
@ -308,7 +309,7 @@ struct dissolver_generic
++it, ++index)
{
helper.push_back(dissolve_helper<box_type>(index,
geometry::return_envelope<box_type>(*it),
geometry::return_envelope<box_type>(*it, envelope_strategy),
geometry::area(*it, area_strategy),
source));
}

View File

@ -229,7 +229,7 @@ struct dissolve_ring_or_polygon
std::map<ring_identifier, properties> selected;
detail::overlay::select_rings<overlay_dissolve>(geometry, map, selected);
detail::overlay::select_rings<overlay_dissolve>(geometry, map, selected, strategy);
// Add intersected rings
{
@ -244,7 +244,7 @@ struct dissolve_ring_or_polygon
}
}
detail::overlay::assign_parents(geometry, rings, selected, true);
detail::overlay::assign_parents(geometry, rings, selected, strategy, true);
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out);
}

View File

@ -388,6 +388,20 @@ class winding
public:
typedef typename SideStrategy::envelope_strategy_type envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
{
return m_side_strategy.get_envelope_strategy();
}
typedef typename SideStrategy::disjoint_strategy_type disjoint_strategy_type;
inline disjoint_strategy_type get_disjoint_strategy() const
{
return m_side_strategy.get_disjoint_strategy();
}
winding()
{}

View File

@ -36,6 +36,7 @@
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@ -133,6 +134,14 @@ struct cartesian_segments
return strategy_type();
}
typedef envelope::cartesian_segment<CalculationType>
envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
{

View File

@ -26,6 +26,9 @@
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
@ -66,6 +69,19 @@ class side_by_triangle
};
public :
typedef strategy::envelope::cartesian_segment<CalculationType> envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
typedef strategy::disjoint::segment_box disjoint_strategy_type;
static inline disjoint_strategy_type get_disjoint_strategy()
{
return disjoint_strategy_type();
}
// Template member function, because it is not always trivial
// or convenient to explicitly mention the typenames in the

View File

@ -34,6 +34,7 @@
#include <boost/geometry/strategies/geographic/area.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/geographic/side.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@ -135,6 +136,14 @@ struct geographic_segments
return strategy_type(m_spheroid);
}
typedef envelope::geographic_segment<FormulaPolicy, Spheroid, CalculationType>
envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
{
return envelope_strategy_type(m_spheroid);
}
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
template <typename CoordinateType, typename SegmentRatio>

View File

@ -26,6 +26,8 @@
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/side.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
@ -56,6 +58,30 @@ template
class geographic
{
public:
typedef strategy::envelope::geographic_segment
<
FormulaPolicy,
Spheroid,
CalculationType
> envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
{
return envelope_strategy_type(m_model);
}
typedef strategy::disjoint::segment_box_geographic
<
FormulaPolicy,
Spheroid,
CalculationType
> disjoint_strategy_type;
inline disjoint_strategy_type get_disjoint_strategy() const
{
return disjoint_strategy_type(m_model);
}
geographic()
{}

View File

@ -41,6 +41,7 @@
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/strategies/spherical/area.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/within.hpp>
@ -147,6 +148,14 @@ struct ecef_segments
return strategy_type();
}
typedef envelope::spherical_segment<CalculationType>
envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
// segment_intersection_info cannot outlive relate_ecef_segments

View File

@ -23,6 +23,8 @@
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
@ -82,6 +84,20 @@ class spherical_side_formula
{
public :
typedef strategy::envelope::spherical_segment<CalculationType> envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
typedef strategy::disjoint::segment_box_spherical disjoint_strategy_type;
static inline disjoint_strategy_type get_disjoint_strategy()
{
return disjoint_strategy_type();
}
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{

View File

@ -528,21 +528,37 @@ static std::string case_102[2] =
"POLYGON((3 6,4 5,5 4,3 2,1 4,3 6),(4 5,3 4,3.5 3.5,4 4,4 5))"
};
static const std::string case_103[2] =
static std::string case_103[2] =
{
// intersection
// all points of [1] the same as some points of [0]
"POLYGON((0 0,0 1,1 1,1 0,0 0))",
"POLYGON((0 0,0 1,1 0,0 0))"
};
static std::string case_104[2] =
{
// union in hole
// all points of [1] the same as some points of [0]
"POLYGON((0 0,0 10,10 10,10 0,0 0),(1 1,9 1,9 9,1 9,1 1))",
"POLYGON((1 1,1 9,9 9,9 1,1 1))"
};
static const std::string case_103m[2] =
{
// Smaller adapted version of case_126_multi
"POLYGON((5 5,5 10,10 10,10 5,5 5),(9 8,7 9,5 8,7 7,9 8))",
"POLYGON((0 3,6 3,6 9,0 9,0 3))"
};
static const std::string case_104[2] =
static const std::string case_104m[2] =
{
// Same but with hole in second polygon too
case_103[0],
case_103m[0],
"POLYGON((0 3,6 3,6 9,0 9,0 3),(2 6,4 7,6 6,4 5,2 6))"
};
static const std::string case_105[2] =
static const std::string case_105m[2] =
{
// Multiple touching interiors
"POLYGON((0 0,0 10,10 10,10 0,0 0),(3 3,7 3,7 7,3 7,3 3))",

View File

@ -48,7 +48,12 @@ void test_geometry(std::string const& wkt1, std::string const& wkt2,
map_type selected;
std::map<bg::ring_identifier, bg::detail::overlay::ring_turn_info> empty;
bg::detail::overlay::select_rings<OverlayType>(geometry1, geometry2, empty, selected);
typedef typename bg::strategy::intersection::services::default_strategy
<
typename bg::cs_tag<Geometry1>::type
>::type strategy_type;
bg::detail::overlay::select_rings<OverlayType>(geometry1, geometry2, empty, selected, strategy_type());
BOOST_CHECK_EQUAL(selected.size(), expected_ids.size());

View File

@ -232,9 +232,9 @@ void test_all()
4, 18, 1.5,
3, 15, 4.0625);
TEST_DIFFERENCE(case_103, 1, 12, 17.5, 2, 9, 32.5);
TEST_DIFFERENCE(case_104, 2, 16, 18.0, 2, 16, 29.0);
TEST_DIFFERENCE(case_105, 4, 20, 8.0, 1, 9, 16.0);
TEST_DIFFERENCE(case_103m, 1, 12, 17.5, 2, 9, 32.5);
TEST_DIFFERENCE(case_104m, 2, 16, 18.0, 2, 16, 29.0);
TEST_DIFFERENCE(case_105m, 4, 20, 8.0, 1, 9, 16.0);
test_one<polygon, polygon, polygon>("winded",
winded[0], winded[1],

View File

@ -347,15 +347,22 @@ void test_areal()
case_102[0], case_102[1],
0, -1, 3.1875);
test_one<Polygon, Polygon, Polygon>("case_103",
case_103[0], case_103[1],
1, -1, 0.5);
test_one<Polygon, Polygon, Polygon>("case_104",
case_104[0], case_104[1],
0, -1, 0.0);
#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
TEST_INTERSECTION(case_103, 2, -1, 3.5);
TEST_INTERSECTION(case_104, 3, -1, 3.0);
TEST_INTERSECTION(case_103m, 2, -1, 3.5);
TEST_INTERSECTION(case_104m, 3, -1, 3.0);
#else
TEST_INTERSECTION_IGNORE(case_103, 0, -1, 3.5);
TEST_INTERSECTION_IGNORE(case_104, 0, -1, 3.0);
TEST_INTERSECTION_IGNORE(case_103m, 0, -1, 3.5);
TEST_INTERSECTION_IGNORE(case_104m, 0, -1, 3.0);
#endif
TEST_INTERSECTION(case_105, 1, 34, 76.0);
TEST_INTERSECTION(case_105m, 1, 34, 76.0);
test_one<Polygon, Polygon, Polygon>("mysql_21964049",
mysql_21964049[0], mysql_21964049[1],

View File

@ -237,8 +237,15 @@ void test_areal()
test_one<Polygon, Polygon, Polygon>("102",
case_102[0], case_102[1], 1, 1, 17, 8.75);
test_one<Polygon, Polygon, Polygon>("105",
case_105[0], case_105[1], 1, 0, 5, 100);
test_one<Polygon, Polygon, Polygon>("103",
case_103[0], case_103[1],
1, 0, 5, 1.0);
test_one<Polygon, Polygon, Polygon>("104",
case_104[0], case_104[1],
1, 0, 5, 100.0);
test_one<Polygon, Polygon, Polygon>("105m",
case_105m[0], case_105m[1], 1, 0, 5, 100);
/*
test_one<Polygon, Polygon, Polygon>(102,