File indexing completed on 2025-09-17 08:30:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_MULTI_POINT_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_MULTI_POINT_HPP
0016
0017
0018 #include <algorithm>
0019 #include <vector>
0020
0021 #include <boost/range/begin.hpp>
0022 #include <boost/range/end.hpp>
0023 #include <boost/range/size.hpp>
0024 #include <boost/range/value_type.hpp>
0025
0026 #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
0027 #include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
0028 #include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
0029 #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
0030 #include <boost/geometry/algorithms/envelope.hpp>
0031 #include <boost/geometry/algorithms/detail/partition.hpp>
0032 #include <boost/geometry/core/tag.hpp>
0033 #include <boost/geometry/core/tags.hpp>
0034
0035 #include <boost/geometry/geometries/box.hpp>
0036
0037 #include <boost/geometry/index/rtree.hpp>
0038
0039 #include <boost/geometry/policies/compare.hpp>
0040
0041 #include <boost/geometry/strategies/covered_by.hpp>
0042 #include <boost/geometry/strategies/disjoint.hpp>
0043
0044 #include <boost/geometry/util/constexpr.hpp>
0045 #include <boost/geometry/util/type_traits.hpp>
0046
0047
0048 namespace boost { namespace geometry {
0049
0050 #ifndef DOXYGEN_NO_DETAIL
0051 namespace detail { namespace within {
0052
0053 struct multi_point_point
0054 {
0055 template <typename MultiPoint, typename Point, typename Strategy>
0056 static inline bool apply(MultiPoint const& multi_point,
0057 Point const& point,
0058 Strategy const& strategy)
0059 {
0060 auto const s = strategy.relate(multi_point, point);
0061
0062 for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
0063 {
0064 if (! s.apply(*it, point))
0065 {
0066 return false;
0067 }
0068 }
0069
0070
0071 return true;
0072 }
0073 };
0074
0075
0076 struct multi_point_multi_point
0077 {
0078 template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
0079 static inline bool apply(MultiPoint1 const& multi_point1,
0080 MultiPoint2 const& multi_point2,
0081 Strategy const& )
0082 {
0083 typedef typename boost::range_value<MultiPoint2>::type point2_type;
0084 typedef geometry::less<void, -1, Strategy> less_type;
0085
0086 less_type const less = less_type();
0087
0088 std::vector<point2_type> points2(boost::begin(multi_point2), boost::end(multi_point2));
0089 std::sort(points2.begin(), points2.end(), less);
0090
0091 bool result = false;
0092
0093 for (auto it = boost::begin(multi_point1); it != boost::end(multi_point1); ++it)
0094 {
0095 if (! std::binary_search(points2.begin(), points2.end(), *it, less))
0096 {
0097 return false;
0098 }
0099 else
0100 {
0101 result = true;
0102 }
0103 }
0104
0105 return result;
0106 }
0107 };
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 template <bool Within>
0118 struct multi_point_single_geometry
0119 {
0120 template <typename MultiPoint, typename LinearOrAreal, typename Strategy>
0121 static inline bool apply(MultiPoint const& multi_point,
0122 LinearOrAreal const& linear_or_areal,
0123 Strategy const& strategy)
0124 {
0125
0126 model::box<point_type_t<LinearOrAreal>> box;
0127 geometry::envelope(linear_or_areal, box, strategy);
0128 geometry::detail::expand_by_epsilon(box);
0129
0130
0131
0132 bool result = false;
0133
0134 for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it )
0135 {
0136 typedef decltype(strategy.covered_by(*it, box)) point_in_box_type;
0137
0138 int in_val = 0;
0139
0140
0141 if (! point_in_box_type::apply(*it, box)
0142 || (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0)
0143 {
0144 result = false;
0145 break;
0146 }
0147
0148
0149 if (Within ? in_val > 0 : in_val >= 0)
0150 {
0151 result = true;
0152 }
0153 }
0154
0155 return result;
0156 }
0157 };
0158
0159
0160
0161 template <bool Within>
0162 struct multi_point_multi_geometry
0163 {
0164 template <typename MultiPoint, typename LinearOrAreal, typename Strategy>
0165 static inline bool apply(MultiPoint const& multi_point,
0166 LinearOrAreal const& linear_or_areal,
0167 Strategy const& strategy)
0168 {
0169 using point2_type = point_type_t<LinearOrAreal>;
0170 using box2_type = model::box<point2_type>;
0171 using box_pair_type = std::pair<box2_type, std::size_t>;
0172 using box_pair_vector = std::vector<box_pair_type>;
0173
0174 static const bool is_linear = util::is_linear<LinearOrAreal>::value;
0175
0176
0177
0178
0179 std::size_t count2 = boost::size(linear_or_areal);
0180 box_pair_vector boxes(count2);
0181 for (std::size_t i = 0 ; i < count2 ; ++i)
0182 {
0183 geometry::envelope(linear_or_areal, boxes[i].first, strategy);
0184 geometry::detail::expand_by_epsilon(boxes[i].first);
0185 boxes[i].second = i;
0186 }
0187
0188
0189 typedef index::parameters<index::rstar<4>, Strategy> index_parameters_type;
0190 index::rtree<box_pair_type, index_parameters_type>
0191 rtree(boxes.begin(), boxes.end(),
0192 index_parameters_type(index::rstar<4>(), strategy));
0193
0194
0195
0196 bool result = false;
0197
0198 for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
0199 {
0200
0201
0202 box_pair_vector inters_boxes;
0203 rtree.query(index::intersects(*it), std::back_inserter(inters_boxes));
0204
0205 bool found_interior = false;
0206 bool found_boundary = false;
0207 int boundaries = 0;
0208
0209 typedef typename box_pair_vector::const_iterator box_iterator;
0210 for (box_iterator box_it = inters_boxes.begin() ;
0211 box_it != inters_boxes.end() ; ++box_it )
0212 {
0213 int const in_val = point_in_geometry(*it,
0214 range::at(linear_or_areal, box_it->second), strategy);
0215
0216 if (in_val > 0)
0217 {
0218 found_interior = true;
0219 }
0220 else if (in_val == 0)
0221 {
0222 ++boundaries;
0223 }
0224
0225
0226
0227
0228
0229 if (result && in_val >= 0)
0230 {
0231 break;
0232 }
0233 }
0234
0235 if (boundaries > 0)
0236 {
0237 if BOOST_GEOMETRY_CONSTEXPR (is_linear)
0238 {
0239 if (boundaries % 2 == 0)
0240 {
0241 found_interior = true;
0242 }
0243 else
0244 {
0245 found_boundary = true;
0246 }
0247 }
0248 else
0249 {
0250 found_boundary = true;
0251 }
0252 }
0253
0254
0255 if (! found_interior && ! found_boundary)
0256 {
0257 result = false;
0258 break;
0259 }
0260
0261
0262 if (Within ? found_interior : (found_interior || found_boundary))
0263 {
0264 result = true;
0265 }
0266 }
0267
0268 return result;
0269 }
0270 };
0271
0272 }}
0273 #endif
0274
0275 }}
0276
0277
0278 #endif