File indexing completed on 2025-12-16 09:50:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_GC_HPP
0013 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_GC_HPP
0014
0015
0016 #include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
0017 #include <boost/geometry/algorithms/detail/relate/interface.hpp>
0018 #include <boost/geometry/algorithms/difference.hpp>
0019 #include <boost/geometry/algorithms/intersection.hpp>
0020 #include <boost/geometry/algorithms/is_empty.hpp>
0021 #include <boost/geometry/algorithms/union.hpp>
0022 #include <boost/geometry/geometries/linestring.hpp>
0023 #include <boost/geometry/geometries/multi_linestring.hpp>
0024 #include <boost/geometry/geometries/multi_point.hpp>
0025 #include <boost/geometry/geometries/multi_polygon.hpp>
0026 #include <boost/geometry/geometries/polygon.hpp>
0027 #include <boost/geometry/util/condition.hpp>
0028 #include <boost/geometry/views/detail/geometry_collection_view.hpp>
0029
0030
0031 namespace boost { namespace geometry
0032 {
0033
0034 #ifndef DOXYGEN_NO_DETAIL
0035 namespace detail { namespace relate
0036 {
0037
0038
0039
0040
0041
0042
0043
0044
0045 template <typename Handler>
0046 struct aa_handler_wrapper
0047 {
0048 bool interrupt = false;
0049
0050 explicit aa_handler_wrapper(Handler& handler)
0051 : m_handler(handler)
0052 , m_overwrite_ii(! handler.template may_update<interior, interior, '2'>())
0053 , m_overwrite_ie(! handler.template may_update<interior, exterior, '2'>())
0054 , m_overwrite_ei(! handler.template may_update<exterior, interior, '2'>())
0055 {}
0056
0057 template <field F1, field F2, char D>
0058 inline bool may_update() const
0059 {
0060 if ((BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == interior) && m_overwrite_ii)
0061 || (BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == exterior) && m_overwrite_ie)
0062 || (BOOST_GEOMETRY_CONDITION(F1 == exterior && F2 == interior) && m_overwrite_ei))
0063 {
0064 char const c = m_handler.template get<F1, F2>();
0065 return D > c || c > '9';
0066 }
0067 else
0068 {
0069 return m_handler.template may_update<F1, F2, D>();
0070 }
0071 }
0072
0073 template <field F1, field F2, char V>
0074 inline void update()
0075 {
0076 if ((BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == interior) && m_overwrite_ii)
0077 || (BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == exterior) && m_overwrite_ie)
0078 || (BOOST_GEOMETRY_CONDITION(F1 == exterior && F2 == interior) && m_overwrite_ei))
0079 {
0080
0081
0082 char const c = m_handler.template get<F1, F2>();
0083
0084 if (V > c || c > '9')
0085 {
0086
0087 m_handler.template set<F1, F2, V>();
0088 }
0089 }
0090 else
0091 {
0092 m_handler.template update<F1, F2, V>();
0093 }
0094 interrupt = interrupt || m_handler.interrupt;
0095 }
0096
0097 private:
0098 Handler & m_handler;
0099 bool const m_overwrite_ii;
0100 bool const m_overwrite_ie;
0101 bool const m_overwrite_ei;
0102 };
0103
0104
0105 template <typename Geometry1, typename Geometry2>
0106 struct gc_gc
0107 {
0108 static const bool interruption_enabled = true;
0109
0110 using mpt1_found_t = typename util::sequence_find_if
0111 <
0112 typename traits::geometry_types<Geometry1>::type,
0113 util::is_multi_point
0114 >::type;
0115 using mls1_found_t = typename util::sequence_find_if
0116 <
0117 typename traits::geometry_types<Geometry1>::type,
0118 util::is_multi_linestring
0119 >::type;
0120 using mpo1_found_t = typename util::sequence_find_if
0121 <
0122 typename traits::geometry_types<Geometry1>::type,
0123 util::is_multi_polygon
0124 >::type;
0125 using pt1_t = geometry::point_type_t<Geometry1>;
0126 using mpt1_t = std::conditional_t
0127 <
0128 std::is_void<mpt1_found_t>::value,
0129 geometry::model::multi_point<pt1_t>,
0130 mpt1_found_t
0131 >;
0132 using mls1_t = std::conditional_t
0133 <
0134 std::is_void<mls1_found_t>::value,
0135 geometry::model::multi_linestring<geometry::model::linestring<pt1_t>>,
0136 mls1_found_t
0137 >;
0138 using mpo1_t = std::conditional_t
0139 <
0140 std::is_void<mpo1_found_t>::value,
0141 geometry::model::multi_polygon<geometry::model::polygon<pt1_t>>,
0142 mpo1_found_t
0143 >;
0144 using tuple1_t = boost::tuple<mpt1_t, mls1_t, mpo1_t>;
0145
0146 using mpt2_found_t = typename util::sequence_find_if
0147 <
0148 typename traits::geometry_types<Geometry2>::type,
0149 util::is_multi_point
0150 >::type;
0151 using mls2_found_t = typename util::sequence_find_if
0152 <
0153 typename traits::geometry_types<Geometry2>::type,
0154 util::is_multi_linestring
0155 >::type;
0156 using mpo2_found_t = typename util::sequence_find_if
0157 <
0158 typename traits::geometry_types<Geometry2>::type,
0159 util::is_multi_polygon
0160 >::type;
0161 using pt2_t = geometry::point_type_t<Geometry2>;
0162 using mpt2_t = std::conditional_t
0163 <
0164 std::is_void<mpt2_found_t>::value,
0165 geometry::model::multi_point<pt2_t>,
0166 mpt2_found_t
0167 >;
0168 using mls2_t = std::conditional_t
0169 <
0170 std::is_void<mls2_found_t>::value,
0171 geometry::model::multi_linestring<geometry::model::linestring<pt2_t>>,
0172 mls2_found_t
0173 >;
0174 using mpo2_t = std::conditional_t
0175 <
0176 std::is_void<mpo2_found_t>::value,
0177 geometry::model::multi_polygon<geometry::model::polygon<pt2_t>>,
0178 mpo2_found_t
0179 >;
0180 using tuple2_t = boost::tuple<mpt2_t, mls2_t, mpo2_t>;
0181
0182 template <typename Geometry>
0183 using kind_id = util::index_constant
0184 <
0185 util::is_areal<Geometry>::value ? 2
0186 : util::is_linear<Geometry>::value ? 1
0187 : 0
0188 >;
0189
0190 template <typename Result, typename Strategy>
0191 static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0192 Result & result,
0193 Strategy const& strategy)
0194 {
0195 using gc1_view_t = random_access_view<Geometry1 const>;
0196 using gc2_view_t = random_access_view<Geometry2 const>;
0197 gc1_view_t const gc1_view(geometry1);
0198 gc2_view_t const gc2_view(geometry2);
0199
0200 bool inters_found[2][3] = {{false, false, false}, {false, false, false}};
0201 bool disjoint_found[2][3] = {{false, false, false}, {false, false, false}};
0202 bool disjoint_linear_boundary_found[2] = {false, false};
0203 bool has_disjoint = false;
0204
0205 gc_group_elements(gc1_view, gc2_view, strategy,
0206 [&](auto const& inters_group)
0207 {
0208 tuple1_t tuple1;
0209 tuple2_t tuple2;
0210
0211
0212
0213 for (auto const& id : inters_group)
0214 {
0215 BOOST_GEOMETRY_ASSERT(id.source_id == 0 || id.source_id == 1);
0216 if (id.source_id == 0)
0217 {
0218 traits::iter_visit<gc1_view_t>::apply([&](auto const& g1)
0219 {
0220 merge_geometry(tuple1, g1, strategy);
0221 }, boost::begin(gc1_view) + id.gc_id);
0222 }
0223 else
0224 {
0225 traits::iter_visit<gc2_view_t>::apply([&](auto const& g2)
0226 {
0227 merge_geometry(tuple2, g2, strategy);
0228 }, boost::begin(gc2_view) + id.gc_id);
0229 }
0230 }
0231
0232
0233
0234 subtract_elements(tuple1, strategy);
0235 subtract_elements(tuple2, strategy);
0236
0237
0238 auto const& mpt1 = boost::get<0>(tuple1);
0239 auto const& mls1 = boost::get<1>(tuple1);
0240 auto const& mpo1 = boost::get<2>(tuple1);
0241 auto const& mpt2 = boost::get<0>(tuple2);
0242 auto const& mls2 = boost::get<1>(tuple2);
0243 auto const& mpo2 = boost::get<2>(tuple2);
0244
0245
0246 if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mpo2))
0247 {
0248 inters_found[0][2] = true;
0249 inters_found[1][2] = true;
0250 aa_handler_wrapper<Result> wrapper(result);
0251 call_relate(mpo1, mpo2, wrapper, strategy);
0252 }
0253
0254 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0255 {
0256 return false;
0257 }
0258
0259 bool is_aa_ii = result.template get<interior, interior>() != 'F';
0260 bool is_aa_ie = result.template get<interior, exterior>() != 'F';
0261 bool is_aa_ei = result.template get<exterior, interior>() != 'F';
0262
0263 bool are_aa_equal = is_aa_ii && ! is_aa_ie && ! is_aa_ei;
0264
0265
0266 boundary_checker<mls1_t, Strategy> mls1_boundary(mls1, strategy);
0267 boundary_checker<mls2_t, Strategy> mls2_boundary(mls2, strategy);
0268
0269
0270
0271
0272 mls2_t mls2_diff_mpo1, mls2_inters_mpo1;
0273 bool is_mls2_divided = false;
0274 mls1_t mls1_diff_mpo2, mls1_inters_mpo2;
0275 bool is_mls1_divided = false;
0276
0277 if (! are_aa_equal && ! geometry::is_empty(mls1) && ! geometry::is_empty(mls2))
0278 {
0279
0280 if (! geometry::is_empty(mpo1))
0281 {
0282 geometry::difference(mls2, mpo1, mls2_diff_mpo1);
0283 geometry::intersection(mls2, mpo1, mls2_inters_mpo1);
0284 is_mls2_divided = true;
0285 }
0286
0287 if (! geometry::is_empty(mpo2))
0288 {
0289 geometry::difference(mls1, mpo2, mls1_diff_mpo2);
0290 geometry::intersection(mls1, mpo2, mls1_inters_mpo2);
0291 is_mls1_divided = true;
0292 }
0293 }
0294
0295
0296 if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mls2))
0297 {
0298 inters_found[0][2] = true;
0299 inters_found[1][1] = true;
0300 if (is_aa_ii && ! is_aa_ie && ! is_aa_ei && ! geometry::is_empty(mls1))
0301 {
0302
0303 }
0304 else if (is_aa_ii && ! is_aa_ie && geometry::is_empty(mls1))
0305 {
0306
0307 mpo1_t empty;
0308 call_relate_al(empty, mls2, mls2_boundary, result, strategy);
0309 }
0310 else
0311 {
0312 if (is_mls2_divided)
0313 {
0314 if (! geometry::is_empty(mls2_inters_mpo1))
0315 {
0316 call_relate_al(mpo1, mls2_inters_mpo1, mls2_boundary, result, strategy);
0317 }
0318 }
0319 else
0320 {
0321 call_relate_al(mpo1, mls2, mls2_boundary, result, strategy);
0322 }
0323 }
0324 }
0325
0326 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0327 {
0328 return false;
0329 }
0330
0331
0332 if (! geometry::is_empty(mls1) && ! geometry::is_empty(mpo2))
0333 {
0334 inters_found[0][1] = true;
0335 inters_found[1][2] = true;
0336 if (is_aa_ii && ! is_aa_ei && ! is_aa_ie && ! geometry::is_empty(mls2))
0337 {
0338
0339 }
0340 else if (is_aa_ii && ! is_aa_ei && geometry::is_empty(mls2))
0341 {
0342
0343 mpo2_t empty;
0344 call_relate_la(mls1, empty, mls1_boundary, result, strategy);
0345 }
0346 else
0347 {
0348 if (is_mls1_divided)
0349 {
0350 if (! geometry::is_empty(mls1_inters_mpo2))
0351 {
0352 call_relate_la(mls1_inters_mpo2, mpo2, mls1_boundary, result, strategy);
0353 }
0354 }
0355 else
0356 {
0357 call_relate_la(mls1, mpo2, mls1_boundary, result, strategy);
0358 }
0359 }
0360 }
0361
0362 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0363 {
0364 return false;
0365 }
0366
0367
0368 if (! geometry::is_empty(mls1) && ! geometry::is_empty(mls2))
0369 {
0370 inters_found[0][1] = true;
0371 inters_found[1][1] = true;
0372 if (is_mls1_divided && is_mls2_divided)
0373 {
0374 if (! geometry::is_empty(mls1_diff_mpo2) && ! geometry::is_empty(mls2_diff_mpo1))
0375 {
0376 call_relate_ll(mls1_diff_mpo2, mls2_diff_mpo1, mls1_boundary, mls2_boundary, result, strategy);
0377 }
0378 }
0379 else if (is_mls1_divided)
0380 {
0381 if (! geometry::is_empty(mls1_diff_mpo2))
0382 {
0383 call_relate_ll(mls1_diff_mpo2, mls2, mls1_boundary, mls2_boundary, result, strategy);
0384 }
0385 }
0386 else if (is_mls2_divided)
0387 {
0388 if (! geometry::is_empty(mls2_diff_mpo1))
0389 {
0390 call_relate_ll(mls1, mls2_diff_mpo1, mls1_boundary, mls2_boundary, result, strategy);
0391 }
0392 }
0393 else
0394 {
0395 call_relate_ll(mls1, mls2, mls1_boundary, mls2_boundary, result, strategy);
0396 }
0397 }
0398
0399 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0400 {
0401 return false;
0402 }
0403
0404
0405 if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mpt2))
0406 {
0407 inters_found[0][2] = true;
0408 inters_found[1][0] = true;
0409 call_relate(mpo1, mpt2, result, strategy);
0410 }
0411
0412 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0413 {
0414 return false;
0415 }
0416
0417
0418 if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mpo2))
0419 {
0420 inters_found[0][0] = true;
0421 inters_found[1][2] = true;
0422 call_relate(mpt1, mpo2, result, strategy);
0423 }
0424
0425 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0426 {
0427 return false;
0428 }
0429
0430
0431 if (! geometry::is_empty(mls1) && ! geometry::is_empty(mpt2))
0432 {
0433 inters_found[0][1] = true;
0434 inters_found[1][0] = true;
0435 call_relate(mls1, mpt2, result, strategy);
0436 }
0437
0438 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0439 {
0440 return false;
0441 }
0442
0443
0444 if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mls2))
0445 {
0446 inters_found[0][0] = true;
0447 inters_found[1][1] = true;
0448 call_relate(mpt1, mls2, result, strategy);
0449 }
0450
0451 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0452 {
0453 return false;
0454 }
0455
0456
0457 if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mpt2))
0458 {
0459 inters_found[0][0] = true;
0460 inters_found[1][0] = true;
0461 call_relate(mpt1, mpt2, result, strategy);
0462 }
0463
0464 if (BOOST_GEOMETRY_CONDITION(result.interrupt))
0465 {
0466 return false;
0467 }
0468
0469 return true;
0470 },
0471 [&](auto const& disjoint_group)
0472 {
0473 for (auto const& id : disjoint_group)
0474 {
0475 BOOST_GEOMETRY_ASSERT(id.source_id == 0 || id.source_id == 1);
0476 if (id.source_id == 0)
0477 {
0478 traits::iter_visit<gc1_view_t>::apply([&](auto const& g1)
0479 {
0480 if (! geometry::is_empty(g1))
0481 {
0482 static const std::size_t index = kind_id<util::remove_cref_t<decltype(g1)>>::value;
0483 disjoint_found[0][index] = true;
0484 disjoint_linear_boundary_found[0] = has_linear_boundary(g1, strategy);
0485 has_disjoint = true;
0486 }
0487 }, boost::begin(gc1_view) + id.gc_id);
0488 }
0489 else
0490 {
0491 traits::iter_visit<gc2_view_t>::apply([&](auto const& g2)
0492 {
0493 if (! geometry::is_empty(g2))
0494 {
0495 static const std::size_t index = kind_id<util::remove_cref_t<decltype(g2)>>::value;
0496 disjoint_found[1][index] = true;
0497 disjoint_linear_boundary_found[1] = has_linear_boundary(g2, strategy);
0498 has_disjoint = true;
0499 }
0500 }, boost::begin(gc2_view) + id.gc_id);
0501 }
0502 }
0503 }, true);
0504
0505
0506 if (has_disjoint)
0507 {
0508 if (disjoint_found[0][2] == true)
0509 {
0510 update<interior, exterior, '2'>(result);
0511 update<boundary, exterior, '1'>(result);
0512 }
0513 else if (disjoint_found[0][1] == true)
0514 {
0515 update<interior, exterior, '1'>(result);
0516 if (disjoint_linear_boundary_found[0])
0517 {
0518 update<boundary, exterior, '0'>(result);
0519 }
0520 }
0521 else if (disjoint_found[0][0] == true)
0522 {
0523 update<interior, exterior, '0'>(result);
0524 }
0525
0526 if (disjoint_found[1][2] == true)
0527 {
0528 update<exterior, interior, '2'>(result);
0529 update<exterior, boundary, '1'>(result);
0530 }
0531 else if (disjoint_found[1][1] == true)
0532 {
0533 update<exterior, interior, '1'>(result);
0534 if (disjoint_linear_boundary_found[1])
0535 {
0536 update<exterior, boundary, '0'>(result);
0537 }
0538 }
0539 else if (disjoint_found[1][0] == true)
0540 {
0541 update<exterior, interior, '0'>(result);
0542 }
0543 }
0544 }
0545
0546 private:
0547 template <typename Tuple, typename Geometry, typename Strategy>
0548 static inline void merge_geometry(Tuple& tuple, Geometry const& geometry, Strategy const& strategy)
0549 {
0550 static const std::size_t index = kind_id<Geometry>::value;
0551 typename boost::tuples::element<index, Tuple>::type temp_out;
0552 geometry::union_(boost::get<index>(tuple), geometry, temp_out, strategy);
0553 boost::get<index>(tuple) = std::move(temp_out);
0554 }
0555
0556 template <typename Tuple, typename Strategy>
0557 static inline void subtract_elements(Tuple& tuple, Strategy const& strategy)
0558 {
0559 if (! geometry::is_empty(boost::get<1>(tuple)))
0560 {
0561 if (! geometry::is_empty(boost::get<2>(tuple)))
0562 {
0563 typename boost::tuples::element<1, Tuple>::type mls;
0564 geometry::difference(boost::get<1>(tuple), boost::get<2>(tuple), mls, strategy);
0565 boost::get<1>(tuple) = std::move(mls);
0566 }
0567 }
0568 if (! geometry::is_empty(boost::get<0>(tuple)))
0569 {
0570 if (! geometry::is_empty(boost::get<2>(tuple)))
0571 {
0572 typename boost::tuples::element<0, Tuple>::type mpt;
0573 geometry::difference(boost::get<0>(tuple), boost::get<2>(tuple), mpt, strategy);
0574 boost::get<0>(tuple) = std::move(mpt);
0575 }
0576 if (! geometry::is_empty(boost::get<1>(tuple)))
0577 {
0578 typename boost::tuples::element<0, Tuple>::type mpt;
0579 geometry::difference(boost::get<0>(tuple), boost::get<1>(tuple), mpt, strategy);
0580 boost::get<0>(tuple) = std::move(mpt);
0581 }
0582 }
0583 }
0584
0585 template
0586 <
0587 typename Geometry, typename Strategy,
0588 std::enable_if_t<util::is_linear<Geometry>::value, int> = 0
0589 >
0590 static inline bool has_linear_boundary(Geometry const& geometry, Strategy const& strategy)
0591 {
0592 topology_check<Geometry, Strategy> tc(geometry, strategy);
0593 return tc.has_boundary();
0594 }
0595
0596 template
0597 <
0598 typename Geometry, typename Strategy,
0599 std::enable_if_t<! util::is_linear<Geometry>::value, int> = 0
0600 >
0601 static inline bool has_linear_boundary(Geometry const& , Strategy const& )
0602 {
0603 return false;
0604 }
0605
0606
0607 template <typename Multi1, typename Multi2, typename Result, typename Strategy>
0608 static inline void call_relate(Multi1 const& multi1, Multi2 const& multi2,
0609 Result& result, Strategy const& strategy)
0610 {
0611 dispatch::relate
0612 <
0613 Multi1, Multi2
0614 >::apply(multi1, multi2, result, strategy);
0615 }
0616
0617 template <typename MLs, typename MPo, typename MLsBoundary, typename Result, typename Strategy>
0618 static inline void call_relate_la(MLs const& mls, MPo const& mpo,
0619 MLsBoundary const& mls_boundary,
0620 Result& result, Strategy const& strategy)
0621 {
0622 linear_areal<MLs, MPo>::apply(mls, mpo, mls_boundary, result, strategy);
0623 }
0624
0625 template <typename MPo, typename MLs, typename MLsBoundary, typename Result, typename Strategy>
0626 static inline void call_relate_al(MPo const& mls, MLs const& mpo,
0627 MLsBoundary const& mls_boundary,
0628 Result& result, Strategy const& strategy)
0629 {
0630 areal_linear<MPo, MLs>::apply(mls, mpo, mls_boundary, result, strategy);
0631 }
0632
0633 template <typename MLs1, typename MLs2, typename MLs1Boundary, typename MLs2Boundary, typename Result, typename Strategy>
0634 static inline void call_relate_ll(MLs1 const& mls1, MLs2 const& mls2,
0635 MLs1Boundary const& mls1_boundary,
0636 MLs2Boundary const& mls2_boundary,
0637 Result& result, Strategy const& strategy)
0638 {
0639 linear_linear<MLs1, MLs2>::apply(mls1, mls2, mls1_boundary, mls2_boundary,
0640 result, strategy);
0641 }
0642
0643
0644 };
0645
0646
0647 }}
0648 #endif
0649
0650
0651 #ifndef DOXYGEN_NO_DISPATCH
0652 namespace dispatch {
0653
0654 template <typename Geometry1, typename Geometry2>
0655 struct relate<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag, -1, -1, false>
0656 : detail::relate::gc_gc<Geometry1, Geometry2>
0657 {};
0658
0659
0660 template <typename Geometry1, typename Geometry2, typename Tag1, int TopDim1>
0661 struct relate<Geometry1, Geometry2, Tag1, geometry_collection_tag, TopDim1, -1, false>
0662 {
0663 static const bool interruption_enabled = true;
0664
0665 template <typename Result, typename Strategy>
0666 static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0667 Result & result,
0668 Strategy const& strategy)
0669 {
0670 using gc1_view_t = detail::geometry_collection_view<Geometry1>;
0671 relate<gc1_view_t, Geometry2>::apply(gc1_view_t(geometry1), geometry2, result, strategy);
0672 }
0673 };
0674
0675 template <typename Geometry1, typename Geometry2, typename Tag2, int TopDim2>
0676 struct relate<Geometry1, Geometry2, geometry_collection_tag, Tag2, -1, TopDim2, false>
0677 {
0678 static const bool interruption_enabled = true;
0679
0680 template <typename Result, typename Strategy>
0681 static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0682 Result & result,
0683 Strategy const& strategy)
0684 {
0685 using gc2_view_t = detail::geometry_collection_view<Geometry2>;
0686 relate<Geometry1, gc2_view_t>::apply(geometry1, gc2_view_t(geometry2), result, strategy);
0687 }
0688 };
0689
0690 }
0691 #endif
0692
0693
0694 }}
0695
0696 #endif