mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 21:44:04 +00:00
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:
commit
e52e2a8665
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
<
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
{}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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()
|
||||
{}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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))",
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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],
|
||||
|
@ -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],
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user