1 // Boost.Geometry 2 3 // Copyright (c) 2020, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 6 7 // Licensed under the Boost Software License version 1.0. 8 // http://www.boost.org/users/license.html 9 10 #ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP 11 #define BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP 12 13 14 // TEMP - move to strategy 15 #include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp> 16 #include <boost/geometry/strategies/cartesian/intersection.hpp> 17 #include <boost/geometry/strategies/cartesian/box_in_box.hpp> 18 #include <boost/geometry/strategies/cartesian/point_in_point.hpp> 19 #include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp> 20 #include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp> 21 #include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp> 22 #include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> 23 24 #include <boost/geometry/strategies/envelope/cartesian.hpp> 25 #include <boost/geometry/strategies/relate/services.hpp> 26 #include <boost/geometry/strategies/detail.hpp> 27 28 #include <boost/geometry/strategy/cartesian/area.hpp> 29 #include <boost/geometry/strategy/cartesian/side_robust.hpp> 30 #include <boost/geometry/strategy/cartesian/side_by_triangle.hpp> 31 #include <boost/geometry/strategy/cartesian/area_box.hpp> 32 33 #include <boost/geometry/util/type_traits.hpp> 34 35 36 namespace boost { namespace geometry 37 { 38 39 namespace strategies { namespace relate 40 { 41 42 template <typename CalculationType = void> 43 class cartesian 44 : public strategies::envelope::cartesian<CalculationType> 45 { 46 public: 47 //area 48 49 template <typename Geometry> area(Geometry const &,std::enable_if_t<!util::is_box<Geometry>::value> * =nullptr)50 static auto area(Geometry const&, 51 std::enable_if_t<! util::is_box<Geometry>::value> * = nullptr) 52 { 53 return strategy::area::cartesian<CalculationType>(); 54 } 55 56 template <typename Geometry> area(Geometry const &,std::enable_if_t<util::is_box<Geometry>::value> * =nullptr)57 static auto area(Geometry const&, 58 std::enable_if_t<util::is_box<Geometry>::value> * = nullptr) 59 { 60 return strategy::area::cartesian_box<CalculationType>(); 61 } 62 63 // covered_by 64 65 template <typename Geometry1, typename Geometry2> covered_by(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_pointlike<Geometry1>::value && util::is_box<Geometry2>::value> * =nullptr)66 static auto covered_by(Geometry1 const&, Geometry2 const&, 67 std::enable_if_t 68 < 69 util::is_pointlike<Geometry1>::value 70 && util::is_box<Geometry2>::value 71 > * = nullptr) 72 { 73 return strategy::covered_by::cartesian_point_box(); 74 } 75 76 template <typename Geometry1, typename Geometry2> covered_by(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_box<Geometry1>::value && util::is_box<Geometry2>::value> * =nullptr)77 static auto covered_by(Geometry1 const&, Geometry2 const&, 78 std::enable_if_t 79 < 80 util::is_box<Geometry1>::value 81 && util::is_box<Geometry2>::value 82 > * = nullptr) 83 { 84 return strategy::covered_by::cartesian_box_box(); 85 } 86 87 // disjoint 88 89 template <typename Geometry1, typename Geometry2> disjoint(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_box<Geometry1>::value && util::is_box<Geometry2>::value> * =nullptr)90 static auto disjoint(Geometry1 const&, Geometry2 const&, 91 std::enable_if_t 92 < 93 util::is_box<Geometry1>::value 94 && util::is_box<Geometry2>::value 95 > * = nullptr) 96 { 97 return strategy::disjoint::cartesian_box_box(); 98 } 99 100 template <typename Geometry1, typename Geometry2> disjoint(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_segment<Geometry1>::value && util::is_box<Geometry2>::value> * =nullptr)101 static auto disjoint(Geometry1 const&, Geometry2 const&, 102 std::enable_if_t 103 < 104 util::is_segment<Geometry1>::value 105 && util::is_box<Geometry2>::value 106 > * = nullptr) 107 { 108 // NOTE: Inconsistent name. 109 return strategy::disjoint::segment_box(); 110 } 111 112 // relate 113 114 template <typename Geometry1, typename Geometry2> relate(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_pointlike<Geometry1>::value && util::is_pointlike<Geometry2>::value> * =nullptr)115 static auto relate(Geometry1 const&, Geometry2 const&, 116 std::enable_if_t 117 < 118 util::is_pointlike<Geometry1>::value 119 && util::is_pointlike<Geometry2>::value 120 > * = nullptr) 121 { 122 return strategy::within::cartesian_point_point(); 123 } 124 125 template <typename Geometry1, typename Geometry2> relate(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_pointlike<Geometry1>::value && (util::is_linear<Geometry2>::value||util::is_polygonal<Geometry2>::value)> * =nullptr)126 static auto relate(Geometry1 const&, Geometry2 const&, 127 std::enable_if_t 128 < 129 util::is_pointlike<Geometry1>::value 130 && ( util::is_linear<Geometry2>::value 131 || util::is_polygonal<Geometry2>::value ) 132 > * = nullptr) 133 { 134 return strategy::within::cartesian_winding<void, void, CalculationType>(); 135 } 136 137 // The problem is that this strategy is often used with non-geometry ranges. 138 // So dispatching only by geometry categories is impossible. 139 // In the past it was taking two segments, now it takes 3-point sub-ranges. 140 // So dispatching by segments is impossible. 141 // It could be dispatched by (linear || polygonal || non-geometry point range). 142 // For now implement as 0-parameter, special case relate. 143 144 //template <typename Geometry1, typename Geometry2> relate()145 static auto relate(/*Geometry1 const&, Geometry2 const&, 146 std::enable_if_t 147 < 148 ( util::is_linear<Geometry1>::value 149 || util::is_polygonal<Geometry1>::value ) 150 && ( util::is_linear<Geometry2>::value 151 || util::is_polygonal<Geometry2>::value ) 152 > * = nullptr*/) 153 { 154 return strategy::intersection::cartesian_segments<CalculationType>(); 155 } 156 157 // side 158 side()159 static auto side() 160 { 161 using side_strategy_type 162 = typename strategy::side::services::default_strategy 163 <cartesian_tag, CalculationType>::type; 164 return side_strategy_type(); 165 } 166 167 // within 168 169 template <typename Geometry1, typename Geometry2> within(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_pointlike<Geometry1>::value && util::is_box<Geometry2>::value> * =nullptr)170 static auto within(Geometry1 const&, Geometry2 const&, 171 std::enable_if_t 172 < 173 util::is_pointlike<Geometry1>::value 174 && util::is_box<Geometry2>::value 175 > * = nullptr) 176 { 177 return strategy::within::cartesian_point_box(); 178 } 179 180 template <typename Geometry1, typename Geometry2> within(Geometry1 const &,Geometry2 const &,std::enable_if_t<util::is_box<Geometry1>::value && util::is_box<Geometry2>::value> * =nullptr)181 static auto within(Geometry1 const&, Geometry2 const&, 182 std::enable_if_t 183 < 184 util::is_box<Geometry1>::value 185 && util::is_box<Geometry2>::value 186 > * = nullptr) 187 { 188 return strategy::within::cartesian_box_box(); 189 } 190 }; 191 192 193 namespace services 194 { 195 196 template <typename Geometry1, typename Geometry2> 197 struct default_strategy<Geometry1, Geometry2, cartesian_tag, cartesian_tag> 198 { 199 using type = strategies::relate::cartesian<>; 200 }; 201 202 203 template <> 204 struct strategy_converter<strategy::within::cartesian_point_point> 205 { getboost::geometry::strategies::relate::services::strategy_converter206 static auto get(strategy::within::cartesian_point_point const& ) 207 { 208 return strategies::relate::cartesian<>(); 209 } 210 }; 211 212 template <> 213 struct strategy_converter<strategy::within::cartesian_point_box> 214 { getboost::geometry::strategies::relate::services::strategy_converter215 static auto get(strategy::within::cartesian_point_box const&) 216 { 217 return strategies::relate::cartesian<>(); 218 } 219 }; 220 221 template <> 222 struct strategy_converter<strategy::covered_by::cartesian_point_box> 223 { getboost::geometry::strategies::relate::services::strategy_converter224 static auto get(strategy::covered_by::cartesian_point_box const&) 225 { 226 return strategies::relate::cartesian<>(); 227 } 228 }; 229 230 template <> 231 struct strategy_converter<strategy::covered_by::cartesian_box_box> 232 { getboost::geometry::strategies::relate::services::strategy_converter233 static auto get(strategy::covered_by::cartesian_box_box const&) 234 { 235 return strategies::relate::cartesian<>(); 236 } 237 }; 238 239 template <> 240 struct strategy_converter<strategy::disjoint::cartesian_box_box> 241 { getboost::geometry::strategies::relate::services::strategy_converter242 static auto get(strategy::disjoint::cartesian_box_box const&) 243 { 244 return strategies::relate::cartesian<>(); 245 } 246 }; 247 248 template <> 249 struct strategy_converter<strategy::disjoint::segment_box> 250 { getboost::geometry::strategies::relate::services::strategy_converter251 static auto get(strategy::disjoint::segment_box const&) 252 { 253 return strategies::relate::cartesian<>(); 254 } 255 }; 256 257 template <> 258 struct strategy_converter<strategy::within::cartesian_box_box> 259 { getboost::geometry::strategies::relate::services::strategy_converter260 static auto get(strategy::within::cartesian_box_box const&) 261 { 262 return strategies::relate::cartesian<>(); 263 } 264 }; 265 266 template <typename P1, typename P2, typename CalculationType> 267 struct strategy_converter<strategy::within::cartesian_winding<P1, P2, CalculationType>> 268 { getboost::geometry::strategies::relate::services::strategy_converter269 static auto get(strategy::within::cartesian_winding<P1, P2, CalculationType> const& ) 270 { 271 return strategies::relate::cartesian<CalculationType>(); 272 } 273 }; 274 275 template <typename CalculationType> 276 struct strategy_converter<strategy::intersection::cartesian_segments<CalculationType>> 277 { getboost::geometry::strategies::relate::services::strategy_converter278 static auto get(strategy::intersection::cartesian_segments<CalculationType> const& ) 279 { 280 return strategies::relate::cartesian<CalculationType>(); 281 } 282 }; 283 284 template <typename CalculationType> 285 struct strategy_converter<strategy::within::cartesian_point_box_by_side<CalculationType>> 286 { 287 struct altered_strategy 288 : strategies::relate::cartesian<CalculationType> 289 { 290 template <typename Geometry1, typename Geometry2> covered_byboost::geometry::strategies::relate::services::strategy_converter::altered_strategy291 static auto covered_by(Geometry1 const&, Geometry2 const&, 292 std::enable_if_t 293 < 294 util::is_pointlike<Geometry1>::value 295 && util::is_box<Geometry2>::value 296 > * = nullptr) 297 { 298 return strategy::covered_by::cartesian_point_box_by_side<CalculationType>(); 299 } 300 301 template <typename Geometry1, typename Geometry2> withinboost::geometry::strategies::relate::services::strategy_converter::altered_strategy302 static auto within(Geometry1 const&, Geometry2 const&, 303 std::enable_if_t 304 < 305 util::is_pointlike<Geometry1>::value 306 && util::is_box<Geometry2>::value 307 > * = nullptr) 308 { 309 return strategy::within::cartesian_point_box_by_side<CalculationType>(); 310 } 311 }; 312 getboost::geometry::strategies::relate::services::strategy_converter313 static auto get(strategy::covered_by::cartesian_point_box_by_side<CalculationType> const&) 314 { 315 return altered_strategy(); 316 } 317 getboost::geometry::strategies::relate::services::strategy_converter318 static auto get(strategy::within::cartesian_point_box_by_side<CalculationType> const&) 319 { 320 return altered_strategy(); 321 } 322 }; 323 324 template <typename CalculationType> 325 struct strategy_converter<strategy::covered_by::cartesian_point_box_by_side<CalculationType>> 326 : strategy_converter<strategy::within::cartesian_point_box_by_side<CalculationType>> 327 {}; 328 329 template <typename P1, typename P2, typename CalculationType> 330 struct strategy_converter<strategy::within::franklin<P1, P2, CalculationType>> 331 { 332 struct altered_strategy 333 : strategies::relate::cartesian<CalculationType> 334 { 335 template <typename Geometry1, typename Geometry2> relateboost::geometry::strategies::relate::services::strategy_converter::altered_strategy336 static auto relate(Geometry1 const&, Geometry2 const&, 337 std::enable_if_t 338 < 339 util::is_pointlike<Geometry1>::value 340 && ( util::is_linear<Geometry2>::value 341 || util::is_polygonal<Geometry2>::value ) 342 > * = nullptr) 343 { 344 return strategy::within::franklin<void, void, CalculationType>(); 345 } 346 }; 347 getboost::geometry::strategies::relate::services::strategy_converter348 static auto get(strategy::within::franklin<P1, P2, CalculationType> const&) 349 { 350 return altered_strategy(); 351 } 352 }; 353 354 template <typename P1, typename P2, typename CalculationType> 355 struct strategy_converter<strategy::within::crossings_multiply<P1, P2, CalculationType>> 356 { 357 struct altered_strategy 358 : strategies::relate::cartesian<CalculationType> 359 { 360 template <typename Geometry1, typename Geometry2> relateboost::geometry::strategies::relate::services::strategy_converter::altered_strategy361 static auto relate(Geometry1 const&, Geometry2 const&, 362 std::enable_if_t 363 < 364 util::is_pointlike<Geometry1>::value 365 && ( util::is_linear<Geometry2>::value 366 || util::is_polygonal<Geometry2>::value ) 367 > * = nullptr) 368 { 369 return strategy::within::crossings_multiply<void, void, CalculationType>(); 370 } 371 }; 372 getboost::geometry::strategies::relate::services::strategy_converter373 static auto get(strategy::within::crossings_multiply<P1, P2, CalculationType> const&) 374 { 375 return altered_strategy(); 376 } 377 }; 378 379 // TEMP used in distance segment/box 380 template <typename CalculationType> 381 struct strategy_converter<strategy::side::side_by_triangle<CalculationType>> 382 { getboost::geometry::strategies::relate::services::strategy_converter383 static auto get(strategy::side::side_by_triangle<CalculationType> const&) 384 { 385 return strategies::relate::cartesian<CalculationType>(); 386 } 387 }; 388 389 template <typename CalculationType> 390 struct strategy_converter<strategy::side::side_robust<CalculationType>> 391 { getboost::geometry::strategies::relate::services::strategy_converter392 static auto get(strategy::side::side_robust<CalculationType> const&) 393 { 394 return strategies::relate::cartesian<CalculationType>(); 395 } 396 }; 397 398 399 } // namespace services 400 401 }} // namespace strategies::relate 402 403 }} // namespace boost::geometry 404 405 #endif // BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP 406