[geometry] added point_in_geometry() and used in within() and covered_by(), also added within_no_turns()

This commit is contained in:
Adam Wulkiewicz
2013-12-08 00:20:46 +01:00
parent 1b3edc3e0d
commit 72205cf03e
9 changed files with 679 additions and 213 deletions

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -77,14 +80,7 @@ struct covered_by<Point, Ring, point_tag, ring_tag>
template <typename Strategy>
static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy)
{
return detail::within::point_in_ring
<
Point,
Ring,
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value,
Strategy
>::apply(point, ring, strategy) >= 0;
return detail::within::point_in_geometry(point, ring, strategy) >= 0;
}
};
@@ -94,14 +90,7 @@ struct covered_by<Point, Polygon, point_tag, polygon_tag>
template <typename Strategy>
static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy)
{
return detail::within::point_in_polygon
<
Point,
Polygon,
order_as_direction<geometry::point_order<Polygon>::value>::value,
geometry::closure<Polygon>::value,
Strategy
>::apply(point, polygon, strategy) >= 0;
return detail::within::point_in_geometry(point, polygon, strategy) >= 0;
}
};

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -30,6 +33,7 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
namespace boost { namespace geometry
@@ -65,38 +69,6 @@ struct disjoint_interrupt_policy
template
<
typename Point1, typename Point2,
std::size_t Dimension, std::size_t DimensionCount
>
struct point_point
{
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
{
return true;
}
return point_point
<
Point1, Point2,
Dimension + 1, DimensionCount
>::apply(p1, p2);
}
};
template <typename Point1, typename Point2, std::size_t DimensionCount>
struct point_point<Point1, Point2, DimensionCount, DimensionCount>
{
static inline bool apply(Point1 const& , Point2 const& )
{
return false;
}
};
template
<
typename Point, typename Box,
@@ -318,44 +290,10 @@ inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
}
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2>
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
{
return point_point
<
Point1, Point2,
0, dimension<Point1>::type::value
>::apply(point1, point2);
}
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace equals
{
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2>
inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
{
return ! detail::disjoint::disjoint_point_point(point1, point2);
}
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP

View File

@@ -0,0 +1,106 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template
<
typename Point1, typename Point2,
std::size_t Dimension, std::size_t DimensionCount
>
struct point_point
{
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
{
return true;
}
return point_point
<
Point1, Point2,
Dimension + 1, DimensionCount
>::apply(p1, p2);
}
};
template <typename Point1, typename Point2, std::size_t DimensionCount>
struct point_point<Point1, Point2, DimensionCount, DimensionCount>
{
static inline bool apply(Point1 const& , Point2 const& )
{
return false;
}
};
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2>
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
{
return point_point
<
Point1, Point2,
0, dimension<Point1>::type::value
>::apply(point1, point2);
}
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace equals
{
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2>
inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
{
return ! detail::disjoint::disjoint_point_point(point1, point2);
}
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP

View File

@@ -0,0 +1,249 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
template <typename Point, typename Range, typename Strategy> inline
int point_in_range(Point const& point, Range const& range, Strategy const& strategy)
{
typedef typename boost::range_iterator<Range const>::type iterator_type;
typename Strategy::state_type state;
iterator_type it = boost::begin(range);
iterator_type end = boost::end(range);
bool stop = false;
for ( iterator_type previous = it++ ;
it != end && ! stop ;
++previous, ++it )
{
if ( ! strategy.apply(point, *previous, *it, state) )
{
stop = true;
}
}
return strategy.result(state);
}
// checks the relation between a point P and geometry G
// returns 1 if P is in the interior of G
// returns 0 if P is on the boundry of G
// returns -1 if P is in the exterior of G
template <typename G, typename T = typename geometry::tag<G>::type>
struct point_in_geometry_dispatch
{
BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (T));
};
template <typename Linestring>
struct point_in_geometry_dispatch<Linestring, linestring_tag>
{
template <typename Point, typename Strategy> static inline
int apply(Point const& pt, Linestring const& ls, Strategy const& strategy)
{
std::size_t count = boost::size(ls);
if ( 2 <= count )
{
if ( 0 != detail::within::point_in_range(pt, ls, strategy) )
return -1;
// if the linestring doesn't have a boundary
if ( detail::equals::equals_point_point(*boost::begin(ls), *(--boost::end(ls))) )
return 1;
// else if the point is equal to the one of the terminal points
else if ( detail::equals::equals_point_point(pt, *boost::begin(ls))
|| detail::equals::equals_point_point(pt, *(--boost::end(ls))) )
return 0;
else
return 1;
}
else if ( 1 == count
&& detail::equals::equals_point_point(pt, *boost::begin(ls)) )
return 0;
return -1;
}
};
template <typename Ring>
struct point_in_geometry_dispatch<Ring, ring_tag>
{
template <typename Point, typename Strategy> static inline
int apply(Point const& point, Ring const& ring, Strategy const& strategy)
{
static const iterate_direction direction = order_as_direction<geometry::point_order<Ring>::value>::value;
static const closure_selector closure = geometry::closure<Ring>::value;
if (int(boost::size(ring))
< core_detail::closure::minimum_ring_size<closure>::value)
{
return -1;
}
typedef typename reversible_view<Ring const, direction>::type rev_view_type;
typedef typename closeable_view
<
rev_view_type const, closure
>::type cl_view_type;
typedef typename boost::range_iterator<cl_view_type const>::type iterator_type;
rev_view_type rev_view(ring);
cl_view_type view(rev_view);
return point_in_range(point, view, strategy);
}
};
//// Polygon: in exterior ring, and if so, not within interior ring(s)
template <typename Polygon>
struct point_in_geometry_dispatch<Polygon, polygon_tag>
{
template <typename Point, typename Strategy>
static inline int apply(Point const& point, Polygon const& poly,
Strategy const& strategy)
{
int const code = point_in_geometry_dispatch
<
typename ring_type<Polygon>::type
>::apply(point, exterior_ring(poly), strategy);
if (code == 1)
{
typename interior_return_type<Polygon const>::type rings
= interior_rings(poly);
for (BOOST_AUTO_TPL(it, boost::begin(rings));
it != boost::end(rings);
++it)
{
int const interior_code = point_in_geometry_dispatch
<
typename ring_type<Polygon>::type
>::apply(point, *it, strategy);
if (interior_code != -1)
{
// If 0, return 0 (touch)
// If 1 (inside hole) return -1 (outside polygon)
// If -1 (outside hole) check other holes if any
return -interior_code;
}
}
}
return code;
}
};
template <typename G>
struct point_in_geometry_dispatch<G, multi_polygon_tag>
{
template <typename P, typename S> static inline
int apply(P const& p, G const& g, S const& s)
{
// For invalid multipolygons
//int res = -1; // outside
typedef typename boost::range_value<G>::type polygon_type;
typedef typename boost::range_const_iterator<G>::type iterator;
for ( iterator it = boost::begin(g) ; it != boost::end(g) ; ++it )
{
int pip = detail::within::point_in_geometry_dispatch<polygon_type>::apply(p, *it, s);
if ( 1 == pip ) // inside polygon
return 1;
// Only for valid multi-polygons
if ( 0 == pip )
return 0;
// For invalid multi-polygons
//if ( res < pip ) // point must be inside at least one polygon
// res = pip;
}
//return res; // for invalid multipolygons
return -1; // for valid multipolygons
}
};
template <typename G>
struct point_in_geometry_dispatch<G, multi_linestring_tag>
{
template <typename P, typename S> static inline
int apply(P const& p, G const& g, S const& s)
{
int pip = -1; // outside
typedef typename boost::range_value<G>::type linestring_type;
typedef typename boost::range_value<linestring_type>::type point_type;
typedef typename boost::range_iterator<G const>::type iterator;
iterator it = boost::begin(g);
for ( ; it != boost::end(g) ; ++it )
{
pip = detail::within::point_in_geometry_dispatch<linestring_type>::apply(p, *it, s);
if ( 0 <= pip )
break;
}
// outside
if ( pip < 0 )
return -1;
unsigned boundaries = pip == 0 ? 1 : 0;
for ( ; it != boost::end(g) ; ++it )
{
if ( boost::size(*it) < 2 )
continue;
point_type const& front = *boost::begin(*it);
point_type const& back = *(--boost::end(*it));
// is closed_ring
if ( detail::equals::equals_point_point(front, back) )
continue;
if ( detail::equals::equals_point_point(p, front)
|| detail::equals::equals_point_point(p, back) )
++boundaries;
}
return boundaries % 2 ? 1 : 0;
}
};
// 1 - in the interior
// 0 - in the boundry
// -1 - in the exterior
template <typename P, typename G, typename Strategy> inline
int point_in_geometry(P const& p, G const& g, Strategy const& strategy)
{
BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal<Strategy>) );
return point_in_geometry_dispatch<G>::apply(p, g, strategy);
}
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP

View File

@@ -0,0 +1,200 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
// returns true if G1 is within G2
// this function should be called only if there are no intersection points
// otherwise it may return invalid result
// e.g. when non-first point of G1 is outside G2 or when some rings of G1 are the same as rings of G2
template <typename G1, typename G2, typename T1 = typename geometry::tag<G1>::type, typename T2 = typename geometry::tag<G2>::type>
struct within_no_turns_dispatch
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
typedef typename geometry::point_type<G1>::type point1_type;
point1_type p;
if ( !geometry::point_on_border(p, g1) )
return false;
return point_in_geometry(p, g2, s) >= 0;
}
};
template <typename G1, typename G2>
struct within_no_turns_dispatch<G1, G2, ring_tag, polygon_tag>
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
typedef typename geometry::point_type<G1>::type point1_type;
typedef typename geometry::point_type<G2>::type point2_type;
point1_type p;
if ( !geometry::point_on_border(p, g1) )
return false;
// check if one of ring points is outside the polygon
if ( point_in_geometry(p, g2, s) < 0 )
return false;
// Now check if holes of G2 aren't inside G1
typedef typename boost::range_const_iterator<typename geometry::interior_type<G2>::type>::type It;
for ( It it = boost::begin(geometry::interior_rings(g2)) ; it != boost::end(geometry::interior_rings(g2)) ; ++it )
{
point2_type p;
if ( !geometry::point_on_border(p, *it) )
return false;
if ( point_in_geometry(p, g1, s) > 0 )
return false;
}
return true;
}
};
template <typename G1, typename G2>
struct within_no_turns_dispatch<G1, G2, polygon_tag, polygon_tag>
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
typedef typename geometry::point_type<G1>::type point1_type;
typedef typename geometry::point_type<G2>::type point2_type;
point1_type p;
if ( !geometry::point_on_border(p, g1) )
return false;
// check if one of ring points is outside the polygon
if ( point_in_geometry(p, g2, s) < 0 )
return false;
// Now check if holes of G2 aren't inside G1
typedef typename boost::range_const_iterator<typename geometry::interior_type<G2>::type>::type It2;
for ( It2 it = boost::begin(geometry::interior_rings(g2)) ; it != boost::end(geometry::interior_rings(g2)) ; ++it )
{
point2_type p2;
if ( !geometry::point_on_border(p2, *it) )
return false;
// if the hole of G2 is inside G1
if ( point_in_geometry(p2, g1, s) > 0 )
{
// if it's also inside one of the G1 holes, it's ok
bool ok = false;
typedef typename boost::range_const_iterator<typename geometry::interior_type<G1>::type>::type It1;
for ( It1 it1 = boost::begin(geometry::interior_rings(g1)) ; it1 != boost::end(geometry::interior_rings(g1)) ; ++it1 )
{
if ( point_in_geometry(p2, *it1, s) < 0 )
{
ok = true;
break;
}
}
if ( !ok )
return false;
}
}
return true;
}
};
// TODO: later move it to directory boost/geometry/multi/algorithms/detail/within
template <typename G1,
typename G2,
typename T1 = typename geometry::tag<G1>::type,
typename T2 = typename geometry::tag<G2>::type,
bool IsMulti1 = boost::is_base_of<geometry::multi_tag, T1>::value,
bool IsMulti2 = boost::is_base_of<geometry::multi_tag, T2>::value>
struct within_no_turns_multi_dispatch
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
return within_no_turns_dispatch<G1, G2>::apply(g1, g2, s);
}
};
template <typename G1, typename G2, typename T1, typename T2>
struct within_no_turns_multi_dispatch<G1, G2, T1, T2, true, false>
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
// All values of G1 must be inside G2
typedef typename boost::range_value<G1>::type V1;
typedef typename boost::range_const_iterator<G1>::type It;
for ( It it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
{
if ( !within_no_turns_dispatch<V1, G2>::apply(*it, g2, s) )
return false;
}
return true;
}
};
template <typename G1, typename G2, typename T1, typename T2>
struct within_no_turns_multi_dispatch<G1, G2, T1, T2, false, true>
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
// G1 must be within at least one value of G2
typedef typename boost::range_value<G2>::type P2;
typedef typename boost::range_const_iterator<G2>::type It;
for ( It it = boost::begin(g2) ; it != boost::end(g2) ; ++it )
{
if ( within_no_turns_dispatch<G1, P2>::apply(g1, *it, s) )
return true;
}
return false;
}
};
template <typename G1, typename G2, typename T1, typename T2>
struct within_no_turns_multi_dispatch<G1, G2, T1, T2, true, true>
{
template <typename S> static inline
bool apply(G1 const& g1, G2 const& g2, S const& s)
{
// each value of G1 must be inside at least one value of G2
typedef typename boost::range_value<G1>::type V1;
typedef typename boost::range_const_iterator<G1>::type It;
for ( It it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
{
if ( !within_no_turns_multi_dispatch<V1, G2>::apply(*it, g2, s) )
return false;
}
return true;
}
};
template <typename G1, typename G2, typename S> inline
bool within_no_turns(G1 const& g1, G2 const& g2, S const& s)
{
return within_no_turns_multi_dispatch<G1, G2>::apply(g1, g2, s);
}
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -46,125 +49,11 @@
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within
{
template
<
typename Point,
typename Ring,
iterate_direction Direction,
closure_selector Closure,
typename Strategy
>
struct point_in_ring
{
BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal<Strategy>) );
static inline int apply(Point const& point, Ring const& ring,
Strategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
if (int(boost::size(ring))
< core_detail::closure::minimum_ring_size<Closure>::value)
{
return -1;
}
typedef typename reversible_view<Ring const, Direction>::type rev_view_type;
typedef typename closeable_view
<
rev_view_type const, Closure
>::type cl_view_type;
typedef typename boost::range_iterator<cl_view_type const>::type iterator_type;
rev_view_type rev_view(ring);
cl_view_type view(rev_view);
typename Strategy::state_type state;
iterator_type it = boost::begin(view);
iterator_type end = boost::end(view);
bool stop = false;
for (iterator_type previous = it++;
it != end && ! stop;
++previous, ++it)
{
if (! strategy.apply(point, *previous, *it, state))
{
stop = true;
}
}
return strategy.result(state);
}
};
// Polygon: in exterior ring, and if so, not within interior ring(s)
template
<
typename Point,
typename Polygon,
iterate_direction Direction,
closure_selector Closure,
typename Strategy
>
struct point_in_polygon
{
BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal<Strategy>) );
static inline int apply(Point const& point, Polygon const& poly,
Strategy const& strategy)
{
int const code = point_in_ring
<
Point,
typename ring_type<Polygon>::type,
Direction,
Closure,
Strategy
>::apply(point, exterior_ring(poly), strategy);
if (code == 1)
{
typename interior_return_type<Polygon const>::type rings
= interior_rings(poly);
for (BOOST_AUTO_TPL(it, boost::begin(rings));
it != boost::end(rings);
++it)
{
int const interior_code = point_in_ring
<
Point,
typename ring_type<Polygon>::type,
Direction,
Closure,
Strategy
>::apply(point, *it, strategy);
if (interior_code != -1)
{
// If 0, return 0 (touch)
// If 1 (inside hole) return -1 (outside polygon)
// If -1 (outside hole) check other holes if any
return -interior_code;
}
}
}
return code;
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
@@ -211,14 +100,7 @@ struct within<Point, Ring, point_tag, ring_tag>
template <typename Strategy>
static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy)
{
return detail::within::point_in_ring
<
Point,
Ring,
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value,
Strategy
>::apply(point, ring, strategy) == 1;
return detail::within::point_in_geometry(point, ring, strategy) == 1;
}
};
@@ -228,14 +110,7 @@ struct within<Point, Polygon, point_tag, polygon_tag>
template <typename Strategy>
static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy)
{
return detail::within::point_in_polygon
<
Point,
Polygon,
order_as_direction<geometry::point_order<Polygon>::value>::value,
geometry::closure<Polygon>::value,
Strategy
>::apply(point, polygon, strategy) == 1;
return detail::within::point_in_geometry(point, polygon, strategy) == 1;
}
};

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.

View File

@@ -0,0 +1,104 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
template <typename G>
struct point_in_geometry_dispatch<G, multi_polygon_tag>
{
template <typename P, typename S> static inline
int apply(P const& p, G const& g, S const& s)
{
// For invalid multipolygons
//int res = -1; // outside
typedef typename boost::range_value<G>::type polygon_type;
typedef typename boost::range_const_iterator<G>::type iterator;
for ( iterator it = boost::begin(g) ; it != boost::end(g) ; ++it )
{
int pip = detail::within::point_in_geometry_dispatch<polygon_type>::apply(p, *it, s);
if ( 1 == pip ) // inside polygon
return 1;
// Only for valid multi-polygons
if ( 0 == pip )
return 0;
// For invalid multi-polygons
//if ( res < pip ) // point must be inside at least one polygon
// res = pip;
}
//return res; // for invalid multipolygons
return -1; // for valid multipolygons
}
};
template <typename G>
struct point_in_geometry_dispatch<G, multi_linestring_tag>
{
template <typename P, typename S> static inline
int apply(P const& p, G const& g, S const& s)
{
int pip = -1; // outside
typedef typename boost::range_value<G>::type linestring_type;
typedef typename boost::range_value<linestring_type>::type point_type;
typedef typename boost::range_iterator<G const>::type iterator;
iterator it = boost::begin(g);
for ( ; it != boost::end(g) ; ++it )
{
pip = detail::within::point_in_geometry_dispatch<linestring_type>::apply(p, *it, s);
if ( 0 <= pip )
break;
}
// outside
if ( pip < 0 )
return -1;
unsigned boundaries = pip == 0 ? 1 : 0;
for ( ; it != boost::end(g) ; ++it )
{
if ( boost::size(*it) < 2 )
continue;
point_type const& front = *boost::begin(*it);
point_type const& back = *(--boost::end(*it));
// is closed_ring
if ( detail::equals::equals_point_point(front, back) )
continue;
if ( detail::equals::equals_point_point(p, front)
|| detail::equals::equals_point_point(p, back) )
++boundaries;
}
return boundaries % 2 ? 1 : 0;
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP

View File

@@ -49,6 +49,8 @@
#include <boost/geometry/multi/algorithms/unique.hpp>
#include <boost/geometry/multi/algorithms/within.hpp>
#include <boost/geometry/multi/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/multi/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp>
#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>