mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 20:42:10 +00:00
[geometry] added point_in_geometry() and used in within() and covered_by(), also added within_no_turns()
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user