File indexing completed on 2025-09-17 08:30:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
0020 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
0021
0022
0023 #include <boost/core/ignore_unused.hpp>
0024 #include <boost/range/begin.hpp>
0025 #include <boost/range/end.hpp>
0026 #include <boost/range/size.hpp>
0027 #include <boost/range/value_type.hpp>
0028
0029 #include <boost/geometry/core/assert.hpp>
0030
0031 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
0032 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
0033
0034 #include <boost/geometry/geometries/concepts/check.hpp>
0035 #include <boost/geometry/strategies/concepts/within_concept.hpp>
0036
0037 #include <boost/geometry/util/range.hpp>
0038 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0039
0040 namespace boost { namespace geometry {
0041
0042 #ifndef DOXYGEN_NO_DETAIL
0043 namespace detail { namespace within {
0044
0045
0046 template <typename Point, typename Range, typename Strategy> inline
0047 int point_in_range(Point const& point, Range const& range, Strategy const& strategy)
0048 {
0049 typename Strategy::state_type state;
0050
0051 auto it = boost::begin(range);
0052 auto const end = boost::end(range);
0053
0054 for (auto previous = it++; it != end; ++previous, ++it)
0055 {
0056 if (! strategy.apply(point, *previous, *it, state))
0057 {
0058 break;
0059 }
0060 }
0061
0062 return strategy.result(state);
0063 }
0064
0065 }}
0066
0067 namespace detail_dispatch { namespace within {
0068
0069
0070
0071
0072
0073
0074 template <typename Geometry, typename Tag = geometry::tag_t<Geometry>>
0075 struct point_in_geometry
0076 : not_implemented<Tag>
0077 {};
0078
0079 template <typename Point2>
0080 struct point_in_geometry<Point2, point_tag>
0081 {
0082 template <typename Point1, typename Strategy> static inline
0083 int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
0084 {
0085 typedef decltype(strategy.relate(point1, point2)) strategy_type;
0086 return strategy_type::apply(point1, point2) ? 1 : -1;
0087 }
0088 };
0089
0090 template <typename Segment>
0091 struct point_in_geometry<Segment, segment_tag>
0092 {
0093 template <typename Point, typename Strategy> static inline
0094 int apply(Point const& point, Segment const& segment, Strategy const& strategy)
0095 {
0096 using point_type = geometry::point_type_t<Segment>;
0097 point_type p0, p1;
0098
0099 detail::assign_point_from_index<0>(segment, p0);
0100 detail::assign_point_from_index<1>(segment, p1);
0101
0102 auto const s = strategy.relate(point, segment);
0103 typename decltype(s)::state_type state;
0104 s.apply(point, p0, p1, state);
0105 int r = s.result(state);
0106
0107 if ( r != 0 )
0108 return -1;
0109
0110
0111 if ( detail::equals::equals_point_point(point, p0, strategy)
0112 || detail::equals::equals_point_point(point, p1, strategy) )
0113 return 0;
0114 else
0115 return 1;
0116 }
0117 };
0118
0119
0120 template <typename Linestring>
0121 struct point_in_geometry<Linestring, linestring_tag>
0122 {
0123 template <typename Point, typename Strategy> static inline
0124 int apply(Point const& point, Linestring const& linestring, Strategy const& strategy)
0125 {
0126 std::size_t count = boost::size(linestring);
0127 if ( count > 1 )
0128 {
0129 if ( detail::within::point_in_range(point, linestring,
0130 strategy.relate(point, linestring)) != 0 )
0131 {
0132 return -1;
0133 }
0134
0135 typedef typename boost::range_value<Linestring>::type point_type;
0136 point_type const& front = range::front(linestring);
0137 point_type const& back = range::back(linestring);
0138
0139
0140 if ( detail::equals::equals_point_point(front, back, strategy) )
0141 {
0142 return 1;
0143 }
0144
0145 else if ( detail::equals::equals_point_point(point, front, strategy)
0146 || detail::equals::equals_point_point(point, back, strategy) )
0147 {
0148 return 0;
0149 }
0150 else
0151 {
0152 return 1;
0153 }
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163 return -1;
0164 }
0165 };
0166
0167 template <typename Ring>
0168 struct point_in_geometry<Ring, ring_tag>
0169 {
0170 template <typename Point, typename Strategy> static inline
0171 int apply(Point const& point, Ring const& ring, Strategy const& strategy)
0172 {
0173 if ( boost::size(ring) < core_detail::closure::minimum_ring_size
0174 <
0175 geometry::closure<Ring>::value
0176 >::value )
0177 {
0178 return -1;
0179 }
0180
0181 detail::closed_clockwise_view<Ring const> view(ring);
0182 return detail::within::point_in_range(point, view,
0183 strategy.relate(point, ring));
0184 }
0185 };
0186
0187
0188 template <typename Polygon>
0189 struct point_in_geometry<Polygon, polygon_tag>
0190 {
0191 template <typename Point, typename Strategy>
0192 static inline int apply(Point const& point, Polygon const& polygon,
0193 Strategy const& strategy)
0194 {
0195 int const code = point_in_geometry
0196 <
0197 ring_type_t<Polygon>
0198 >::apply(point, exterior_ring(polygon), strategy);
0199
0200 if (code == 1)
0201 {
0202 auto const& rings = interior_rings(polygon);
0203 for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
0204 {
0205 int const interior_code = point_in_geometry
0206 <
0207 ring_type_t<Polygon>
0208 >::apply(point, *it, strategy);
0209
0210 if (interior_code != -1)
0211 {
0212
0213
0214
0215 return -interior_code;
0216 }
0217 }
0218 }
0219 return code;
0220 }
0221 };
0222
0223 template <typename Geometry>
0224 struct point_in_geometry<Geometry, multi_point_tag>
0225 {
0226 template <typename Point, typename Strategy> static inline
0227 int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
0228 {
0229 typedef typename boost::range_value<Geometry>::type point_type;
0230 for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
0231 {
0232 int pip = point_in_geometry<point_type>::apply(point, *it, strategy);
0233
0234
0235 if (pip > 0)
0236 {
0237
0238 return 1;
0239 }
0240 }
0241
0242 return -1;
0243 }
0244 };
0245
0246 template <typename Geometry>
0247 struct point_in_geometry<Geometry, multi_linestring_tag>
0248 {
0249 template <typename Point, typename Strategy> static inline
0250 int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
0251 {
0252 int pip = -1;
0253
0254 typedef typename boost::range_value<Geometry>::type linestring_type;
0255 typedef typename boost::range_value<linestring_type>::type point_type;
0256 auto it = boost::begin(geometry);
0257 for ( ; it != boost::end(geometry); ++it)
0258 {
0259 pip = point_in_geometry<linestring_type>::apply(point, *it, strategy);
0260
0261
0262 if (pip >= 0)
0263 {
0264 ++it;
0265 break;
0266 }
0267 }
0268
0269
0270 if (pip < 0)
0271 {
0272 return -1;
0273 }
0274
0275
0276
0277 unsigned boundaries = pip == 0 ? 1 : 0;
0278
0279 for (; it != boost::end(geometry); ++it)
0280 {
0281 if (boost::size(*it) < 2)
0282 {
0283 continue;
0284 }
0285
0286 point_type const& front = range::front(*it);
0287 point_type const& back = range::back(*it);
0288
0289
0290 if (detail::equals::equals_point_point(front, back, strategy))
0291 {
0292 continue;
0293 }
0294
0295
0296 if ( detail::equals::equals_point_point(point, front, strategy)
0297 || detail::equals::equals_point_point(point, back, strategy) )
0298 {
0299 ++boundaries;
0300 }
0301 }
0302
0303
0304 return boundaries % 2 ? 0 : 1;
0305 }
0306 };
0307
0308 template <typename Geometry>
0309 struct point_in_geometry<Geometry, multi_polygon_tag>
0310 {
0311 template <typename Point, typename Strategy> static inline
0312 int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
0313 {
0314
0315
0316
0317 typedef typename boost::range_value<Geometry>::type polygon_type;
0318 for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
0319 {
0320 int pip = point_in_geometry<polygon_type>::apply(point, *it, strategy);
0321
0322
0323 if (pip >= 0)
0324 {
0325 return pip;
0326 }
0327
0328
0329
0330
0331
0332
0333 }
0334
0335 return -1;
0336
0337 }
0338 };
0339
0340 }}
0341
0342 namespace detail { namespace within {
0343
0344
0345
0346
0347 template <typename Point, typename Geometry, typename Strategy>
0348 inline int point_in_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy)
0349 {
0350 concepts::within::check<Point, Geometry, Strategy>();
0351
0352 return detail_dispatch::within::point_in_geometry<Geometry>::apply(point, geometry, strategy);
0353 }
0354
0355 template <typename Point, typename Geometry, typename Strategy>
0356 inline bool within_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy)
0357 {
0358 return point_in_geometry(point, geometry, strategy) > 0;
0359 }
0360
0361 template <typename Point, typename Geometry, typename Strategy>
0362 inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy)
0363 {
0364 return point_in_geometry(point, geometry, strategy) >= 0;
0365 }
0366
0367 }}
0368 #endif
0369
0370 }}
0371
0372 #endif