1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492 |
- #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
- #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
- #include <boost/core/ignore_unused.hpp>
- #include <boost/range/size.hpp>
- #include <boost/geometry/algorithms/detail/point_on_border.hpp>
- #include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
- #include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
- #include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
- #include <boost/geometry/algorithms/detail/relate/turns.hpp>
- #include <boost/geometry/algorithms/detail/single_geometry.hpp>
- #include <boost/geometry/algorithms/detail/sub_range.hpp>
- #include <boost/geometry/algorithms/num_interior_rings.hpp>
- #include <boost/geometry/core/assert.hpp>
- #include <boost/geometry/core/topological_dimension.hpp>
- #include <boost/geometry/geometries/helper_geometry.hpp>
- #include <boost/geometry/util/constexpr.hpp>
- #include <boost/geometry/util/range.hpp>
- #include <boost/geometry/util/type_traits.hpp>
- #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
- namespace boost { namespace geometry
- {
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail { namespace relate {
- template
- <
- typename Geometry2,
- typename Result,
- typename Strategy,
- typename BoundaryChecker,
- bool TransposeResult
- >
- class no_turns_la_linestring_pred
- {
- public:
- no_turns_la_linestring_pred(Geometry2 const& geometry2,
- Result & res,
- Strategy const& strategy,
- BoundaryChecker const& boundary_checker)
- : m_geometry2(geometry2)
- , m_result(res)
- , m_strategy(strategy)
- , m_boundary_checker(boundary_checker)
- , m_interrupt_flags(0)
- {
- if ( ! may_update<interior, interior, '1', TransposeResult>(m_result) )
- {
- m_interrupt_flags |= 1;
- }
- if ( ! may_update<interior, exterior, '1', TransposeResult>(m_result) )
- {
- m_interrupt_flags |= 2;
- }
- if ( ! may_update<boundary, interior, '0', TransposeResult>(m_result) )
- {
- m_interrupt_flags |= 4;
- }
- if ( ! may_update<boundary, exterior, '0', TransposeResult>(m_result) )
- {
- m_interrupt_flags |= 8;
- }
- }
- template <typename Linestring>
- bool operator()(Linestring const& linestring)
- {
- std::size_t const count = boost::size(linestring);
-
- if ( count < 2 )
- {
-
-
- return true;
- }
-
- if ( m_interrupt_flags == 0xF )
- {
- return false;
- }
- int const pig = detail::within::point_in_geometry(range::front(linestring),
- m_geometry2,
- m_strategy);
-
- if ( pig > 0 )
- {
- update<interior, interior, '1', TransposeResult>(m_result);
- m_interrupt_flags |= 1;
- }
- else
- {
- update<interior, exterior, '1', TransposeResult>(m_result);
- m_interrupt_flags |= 2;
- }
-
- if ((m_interrupt_flags & 0xC) != 0xC
- && (m_boundary_checker.is_endpoint_boundary(range::front(linestring))
- || m_boundary_checker.is_endpoint_boundary(range::back(linestring))))
- {
- if ( pig > 0 )
- {
- update<boundary, interior, '0', TransposeResult>(m_result);
- m_interrupt_flags |= 4;
- }
- else
- {
- update<boundary, exterior, '0', TransposeResult>(m_result);
- m_interrupt_flags |= 8;
- }
- }
- return m_interrupt_flags != 0xF
- && ! m_result.interrupt;
- }
- private:
- Geometry2 const& m_geometry2;
- Result & m_result;
- Strategy const& m_strategy;
- BoundaryChecker const& m_boundary_checker;
- unsigned m_interrupt_flags;
- };
- template <typename Result, bool TransposeResult>
- class no_turns_la_areal_pred
- {
- public:
- no_turns_la_areal_pred(Result & res)
- : m_result(res)
- , interrupt(! may_update<interior, exterior, '2', TransposeResult>(m_result)
- && ! may_update<boundary, exterior, '1', TransposeResult>(m_result) )
- {}
- template <typename Areal>
- bool operator()(Areal const& areal)
- {
- if ( interrupt )
- {
- return false;
- }
-
-
- using point_type = typename geometry::point_type<Areal>::type;
- typename helper_geometry<point_type>::type pt;
- bool const ok = geometry::point_on_border(pt, areal);
-
- if ( !ok )
- {
- return true;
- }
- update<interior, exterior, '2', TransposeResult>(m_result);
- update<boundary, exterior, '1', TransposeResult>(m_result);
- return false;
- }
- private:
- Result & m_result;
- bool const interrupt;
- };
- template <typename It, typename Strategy>
- inline It find_next_non_duplicated(It first, It current, It last, Strategy const& strategy)
- {
- BOOST_GEOMETRY_ASSERT(current != last);
- It it = current;
- for (++it ; it != last ; ++it)
- {
- if (! equals::equals_point_point(*current, *it, strategy))
- {
- return it;
- }
- }
-
- for (it = first ; it != current ; ++it)
- {
- if (! equals::equals_point_point(*current, *it, strategy))
- {
- return it;
- }
- }
- return current;
- }
- template
- <
- typename Pi, typename Pj, typename Pk,
- typename Qi, typename Qj, typename Qk,
- typename Strategy
- >
- inline bool calculate_from_inside_sides(Pi const& pi, Pj const& pj, Pk const& pk,
- Qi const& , Qj const& qj, Qk const& qk,
- Strategy const& strategy)
- {
- auto const side_strategy = strategy.side();
- int const side_pk_p = side_strategy.apply(pi, pj, pk);
- int const side_qk_p = side_strategy.apply(pi, pj, qk);
-
- if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p))
- {
- int const side_pk_q2 = side_strategy.apply(qj, qk, pk);
- return side_pk_q2 == -1;
- }
- else
- {
- return side_pk_p == -1;
- }
- }
- template
- <
- std::size_t OpId,
- typename Geometry1, typename Geometry2,
- typename Turn, typename Strategy
- >
- inline bool calculate_from_inside(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Turn const& turn,
- Strategy const& strategy)
- {
- static const std::size_t op_id = OpId;
- static const std::size_t other_op_id = (OpId + 1) % 2;
- if (turn.operations[op_id].position == overlay::position_front)
- {
- return false;
- }
- auto const& range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
- using range2_view = detail::closed_clockwise_view<typename ring_type<Geometry2>::type const>;
- range2_view const range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
- BOOST_GEOMETRY_ASSERT(boost::size(range1));
- std::size_t const s2 = boost::size(range2);
- BOOST_GEOMETRY_ASSERT(s2 > 2);
- std::size_t const seg_count2 = s2 - 1;
- std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);
- std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);
- BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));
- BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);
- auto const& pi = range::at(range1, p_seg_ij);
- auto const& qi = range::at(range2, q_seg_ij);
- auto const& qj = range::at(range2, q_seg_ij + 1);
- bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy);
-
-
-
- if (is_ip_qj)
- {
- std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2;
-
-
- auto qk_it = find_next_non_duplicated(boost::begin(range2),
- range::pos(range2, q_seg_jk),
- boost::end(range2),
- strategy);
-
-
- return calculate_from_inside_sides(qi, turn.point, pi, qi, qj, *qk_it, strategy);
- }
- else
- {
-
- return calculate_from_inside_sides(qi, turn.point, pi, qi, turn.point, qj, strategy);
- }
- }
- template <typename Geometry1, typename Geometry2, bool TransposeResult = false>
- struct linear_areal
- {
-
- BOOST_STATIC_ASSERT(topological_dimension<Geometry1>::value == 1
- && topological_dimension<Geometry2>::value == 2);
- static const bool interruption_enabled = true;
- template <typename Geom1, typename Geom2, typename Strategy>
- struct multi_turn_info
- : turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
- {
- multi_turn_info() : priority(0) {}
- int priority;
- };
- template <typename Geom1, typename Geom2, typename Strategy>
- struct turn_info_type
- : std::conditional
- <
- util::is_multi<Geometry2>::value,
- multi_turn_info<Geom1, Geom2, Strategy>,
- typename turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
- >
- {};
- template <typename Result, typename Strategy>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Result & result,
- Strategy const& strategy)
- {
- boundary_checker<Geometry1, Strategy> boundary_checker1(geometry1, strategy);
- apply(geometry1, geometry2, boundary_checker1, result, strategy);
- }
- template <typename BoundaryChecker1, typename Result, typename Strategy>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
- BoundaryChecker1 const& boundary_checker1,
- Result & result,
- Strategy const& strategy)
- {
-
- update<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);
- if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
- {
- return;
- }
-
- using turn_type = typename turn_info_type<Geometry1, Geometry2, Strategy>::type;
- std::vector<turn_type> turns;
- interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
- turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, strategy);
- if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
- {
- return;
- }
- no_turns_la_linestring_pred
- <
- Geometry2,
- Result,
- Strategy,
- BoundaryChecker1,
- TransposeResult
- > pred1(geometry2,
- result,
- strategy,
- boundary_checker1);
- for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
- if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
- {
- return;
- }
- no_turns_la_areal_pred<Result, !TransposeResult> pred2(result);
- for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
- if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
- {
- return;
- }
- if ( turns.empty() )
- {
- return;
- }
-
-
- update<exterior, interior, '2', TransposeResult>(result);
- if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
- {
- return;
- }
- {
- sort_dispatch(turns.begin(), turns.end(), strategy, util::is_multi<Geometry2>());
- turns_analyser<turn_type> analyser;
- analyse_each_turn(result, analyser,
- turns.begin(), turns.end(),
- geometry1, geometry2,
- boundary_checker1,
- strategy);
- if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
- {
- return;
- }
- }
-
- if ( !interrupt_policy.is_boundary_found )
- {
- update<exterior, boundary, '1', TransposeResult>(result);
- }
-
- else if ( may_update<exterior, boundary, '1', TransposeResult>(result) )
- {
-
- std::sort(turns.begin(), turns.end(), less_ring());
- segment_identifier * prev_seg_id_ptr = NULL;
-
- for (auto it = turns.begin() ; it != turns.end() ; )
- {
-
- if ( prev_seg_id_ptr == NULL
- || prev_seg_id_ptr->multi_index != it->operations[1].seg_id.multi_index )
- {
-
- if ( it->operations[1].seg_id.ring_index > -1 )
- {
-
- update<exterior, boundary, '1', TransposeResult>(result);
- break;
- }
-
- if ( prev_seg_id_ptr != NULL )
- {
- signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
- BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);
-
- if ( static_cast<std::size_t>(next_ring_index)
- < geometry::num_interior_rings(
- single_geometry(geometry2, *prev_seg_id_ptr)) )
- {
-
- update<exterior, boundary, '1', TransposeResult>(result);
- break;
- }
- }
- }
-
- else
- {
-
- if ( prev_seg_id_ptr != NULL
- && prev_seg_id_ptr->ring_index + 1 < it->operations[1].seg_id.ring_index )
- {
-
- update<exterior, boundary, '1', TransposeResult>(result);
- break;
- }
- }
- prev_seg_id_ptr = boost::addressof(it->operations[1].seg_id);
-
- has_boundary_intersection has_boundary_inters;
- auto next = find_next_ring(it, turns.end(), has_boundary_inters);
-
- if ( !has_boundary_inters.result )
- {
-
- update<exterior, boundary, '1', TransposeResult>(result);
- break;
- }
-
- else
- {
-
- using less_t = turns::less<1, turns::less_op_areal_linear<1>, Strategy>;
- std::sort(it, next, less_t());
-
- areal_boundary_analyser<turn_type> analyser;
- for (auto rit = it ; rit != next ; ++rit)
- {
-
- if ( !analyser.apply(it, rit, next, strategy) )
- break;
- }
-
- if ( analyser.is_union_detected )
- {
-
- update<exterior, boundary, '1', TransposeResult>(result);
- break;
- }
- }
- it = next;
- }
-
- if ( prev_seg_id_ptr != NULL )
- {
- signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
- BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);
-
- if ( static_cast<std::size_t>(next_ring_index)
- < geometry::num_interior_rings(
- single_geometry(geometry2, *prev_seg_id_ptr)) )
- {
-
- update<exterior, boundary, '1', TransposeResult>(result);
- }
- }
- }
- }
- template <typename It, typename Pred, typename Comp>
- static void for_each_equal_range(It first, It last, Pred pred, Comp comp)
- {
- if ( first == last )
- {
- return;
- }
- It first_equal = first;
- It prev = first;
- for ( ++first ; ; ++first, ++prev )
- {
- if ( first == last || !comp(*prev, *first) )
- {
- pred(first_equal, first);
- first_equal = first;
- }
- if ( first == last )
- {
- break;
- }
- }
- }
- struct same_ip
- {
- template <typename Turn>
- bool operator()(Turn const& left, Turn const& right) const
- {
- return left.operations[0].seg_id == right.operations[0].seg_id
- && left.operations[0].fraction == right.operations[0].fraction;
- }
- };
- struct same_ip_and_multi_index
- {
- template <typename Turn>
- bool operator()(Turn const& left, Turn const& right) const
- {
- return same_ip()(left, right)
- && left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index;
- }
- };
- template <typename OpToPriority>
- struct set_turns_group_priority
- {
- template <typename TurnIt>
- void operator()(TurnIt first, TurnIt last) const
- {
- BOOST_GEOMETRY_ASSERT(first != last);
- static OpToPriority op_to_priority;
-
- int least_priority = op_to_priority(first->operations[0]);
- for ( TurnIt it = first + 1 ; it != last ; ++it )
- {
- int priority = op_to_priority(it->operations[0]);
- if ( priority < least_priority )
- least_priority = priority;
- }
-
- for ( TurnIt it = first ; it != last ; ++it )
- {
- it->priority = least_priority;
- }
- }
- };
- template <typename SingleLess>
- struct sort_turns_group
- {
- struct less
- {
- template <typename Turn>
- bool operator()(Turn const& left, Turn const& right) const
- {
- return left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index ?
- SingleLess()(left, right) :
- left.priority < right.priority;
- }
- };
- template <typename TurnIt>
- void operator()(TurnIt first, TurnIt last) const
- {
- std::sort(first, last, less());
- }
- };
- template <typename TurnIt, typename Strategy>
- static void sort_dispatch(TurnIt first, TurnIt last, Strategy const& ,
- std::true_type const& )
- {
-
- using less_t = turns::less<0, turns::less_other_multi_index<0>, Strategy>;
- std::sort(first, last, less_t());
-
-
-
- typedef turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
- for_each_equal_range(first, last,
- set_turns_group_priority<op_to_int_xuic>(),
- same_ip_and_multi_index());
-
-
-
- using single_less_t = turns::less<0, turns::less_op_linear_areal_single<0>, Strategy>;
- for_each_equal_range(first, last,
- sort_turns_group<single_less_t>(),
- same_ip());
- }
- template <typename TurnIt, typename Strategy>
- static void sort_dispatch(TurnIt first, TurnIt last, Strategy const& ,
- std::false_type const& )
- {
-
-
-
- using less_t = turns::less<0, turns::less_op_linear_areal_single<0>, Strategy>;
- std::sort(first, last, less_t());
- }
-
-
- template <typename Areal, typename Result>
- class interrupt_policy_linear_areal
- {
- public:
- static bool const enabled = true;
- interrupt_policy_linear_areal(Areal const& areal, Result & result)
- : m_result(result), m_areal(areal)
- , is_boundary_found(false)
- {}
- template <typename Range>
- inline bool apply(Range const& turns)
- {
- for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
- {
- if ( it->operations[0].operation == overlay::operation_intersection )
- {
- bool const no_interior_rings
- = geometry::num_interior_rings(
- single_geometry(m_areal, it->operations[1].seg_id)) == 0;
-
-
- if ( no_interior_rings )
- update<interior, interior, '1', TransposeResult>(m_result);
- }
- else if ( it->operations[0].operation == overlay::operation_continue )
- {
- update<interior, boundary, '1', TransposeResult>(m_result);
- is_boundary_found = true;
- }
- else if ( ( it->operations[0].operation == overlay::operation_union
- || it->operations[0].operation == overlay::operation_blocked )
- && it->operations[0].position == overlay::position_middle )
- {
- update<interior, boundary, '0', TransposeResult>(m_result);
- }
- }
- return m_result.interrupt;
- }
- private:
- Result & m_result;
- Areal const& m_areal;
- public:
- bool is_boundary_found;
- };
-
-
- template <typename TurnInfo>
- class turns_analyser
- {
- typedef typename TurnInfo::point_type turn_point_type;
- static const std::size_t op_id = 0;
- static const std::size_t other_op_id = 1;
- public:
- turns_analyser()
- : m_previous_turn_ptr(NULL)
- , m_previous_operation(overlay::operation_none)
- , m_boundary_counter(0)
- , m_interior_detected(false)
- , m_first_interior_other_id_ptr(NULL)
- , m_first_from_unknown(false)
- , m_first_from_unknown_boundary_detected(false)
- {}
- template <typename Result,
- typename TurnIt,
- typename Geometry,
- typename OtherGeometry,
- typename BoundaryChecker,
- typename Strategy>
- void apply(Result & res, TurnIt it,
- Geometry const& geometry,
- OtherGeometry const& other_geometry,
- BoundaryChecker const& boundary_checker,
- Strategy const& strategy)
- {
- overlay::operation_type op = it->operations[op_id].operation;
- if ( op != overlay::operation_union
- && op != overlay::operation_intersection
- && op != overlay::operation_blocked
- && op != overlay::operation_continue )
- {
- return;
- }
- segment_identifier const& seg_id = it->operations[op_id].seg_id;
- segment_identifier const& other_id = it->operations[other_op_id].seg_id;
- const bool first_in_range = m_seg_watcher.update(seg_id);
-
-
-
-
-
- bool fake_enter_detected = false;
- if ( m_exit_watcher.get_exit_operation() == overlay::operation_union )
- {
-
-
- if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
- strategy) )
- {
- m_exit_watcher.reset_detected_exit();
- update<interior, exterior, '1', TransposeResult>(res);
-
- if ( first_in_range && m_previous_turn_ptr )
- {
-
- segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = boundary_checker.is_endpoint_boundary(
- range::back(sub_range(geometry, prev_seg_id)));
-
- if ( prev_back_b )
- {
- update<boundary, exterior, '0', TransposeResult>(res);
- }
- }
- }
-
- else if ( op == overlay::operation_intersection
- || op == overlay::operation_continue )
- {
- m_exit_watcher.reset_detected_exit();
- fake_enter_detected = true;
- }
- }
- else if ( m_exit_watcher.get_exit_operation() == overlay::operation_blocked )
- {
-
- if ( op == overlay::operation_blocked
- && seg_id.multi_index == m_previous_turn_ptr->operations[op_id].seg_id.multi_index )
- {
- return;
- }
- if ( ( op == overlay::operation_intersection
- || op == overlay::operation_continue )
- && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it,
- strategy) )
- {
- fake_enter_detected = true;
- }
- m_exit_watcher.reset_detected_exit();
- }
- if BOOST_GEOMETRY_CONSTEXPR (util::is_multi<OtherGeometry>::value)
- {
- if (m_first_from_unknown)
- {
-
-
-
-
-
- if ((m_previous_operation == overlay::operation_blocked
- && (op != overlay::operation_blocked
- || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index))
- || (m_previous_operation == overlay::operation_union
- && ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, strategy)))
- {
- update<interior, exterior, '1', TransposeResult>(res);
- if ( m_first_from_unknown_boundary_detected )
- {
- update<boundary, exterior, '0', TransposeResult>(res);
- }
- m_first_from_unknown = false;
- m_first_from_unknown_boundary_detected = false;
- }
- }
- }
-
- if ( m_interior_detected )
- {
- BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected");
-
- if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it,
- strategy) )
- {
- update<interior, interior, '1', TransposeResult>(res);
- m_interior_detected = false;
-
- if ( first_in_range )
- {
- segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = boundary_checker.is_endpoint_boundary(
- range::back(sub_range(geometry, prev_seg_id)));
-
- if ( prev_back_b )
- {
- update<boundary, interior, '0', TransposeResult>(res);
- }
-
-
- }
- }
-
- else if ( op == overlay::operation_continue )
- {
- m_interior_detected = false;
- }
- else if ( op == overlay::operation_union )
- {
- if ( m_first_interior_other_id_ptr
- && m_first_interior_other_id_ptr->multi_index == other_id.multi_index )
- {
- m_interior_detected = false;
- }
- }
- }
-
- if ( first_in_range )
- {
- m_exit_watcher.reset();
- m_boundary_counter = 0;
- m_first_from_unknown = false;
- m_first_from_unknown_boundary_detected = false;
- }
-
- if ( op == overlay::operation_intersection
- || op == overlay::operation_continue )
- {
- bool const first_point = first_in_range || m_first_from_unknown;
- bool no_enters_detected = m_exit_watcher.is_outside();
- m_exit_watcher.enter(*it);
- if ( op == overlay::operation_intersection )
- {
- if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear )
- --m_boundary_counter;
- if ( m_boundary_counter == 0 )
- {
-
-
- if ( !m_interior_detected )
- {
-
-
- m_interior_detected = true;
- m_first_interior_other_id_ptr = boost::addressof(other_id);
- }
- }
- }
- else
- {
-
-
- if ( first_point || !it->operations[op_id].is_collinear )
- ++m_boundary_counter;
- update<interior, boundary, '1', TransposeResult>(res);
- }
- bool const this_b = is_ip_on_boundary(it->point, it->operations[op_id],
- boundary_checker);
-
- if ( this_b )
- {
- update<boundary, boundary, '0', TransposeResult>(res);
- }
-
- else
- {
- update<interior, boundary, '0', TransposeResult>(res);
-
- if ( no_enters_detected
- && ! fake_enter_detected
- && it->operations[op_id].position != overlay::position_front )
- {
- bool const from_inside =
- first_point && calculate_from_inside<op_id>(geometry,
- other_geometry,
- *it,
- strategy);
- if ( from_inside )
- update<interior, interior, '1', TransposeResult>(res);
- else
- update<interior, exterior, '1', TransposeResult>(res);
-
- if ( first_point )
- {
- bool const front_b = boundary_checker.is_endpoint_boundary(
- range::front(sub_range(geometry, seg_id)));
-
- if ( front_b )
- {
- if ( from_inside )
- update<boundary, interior, '0', TransposeResult>(res);
- else
- update<boundary, exterior, '0', TransposeResult>(res);
- }
- }
- }
- }
- if BOOST_GEOMETRY_CONSTEXPR (util::is_multi<OtherGeometry>::value)
- {
- m_first_from_unknown = false;
- m_first_from_unknown_boundary_detected = false;
- }
- }
-
- else if ( op == overlay::operation_union || op == overlay::operation_blocked )
- {
- bool const op_blocked = op == overlay::operation_blocked;
- bool const no_enters_detected = m_exit_watcher.is_outside()
- && m_exit_watcher.get_exit_operation() == overlay::operation_none;
- if ( op == overlay::operation_union )
- {
- if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear )
- --m_boundary_counter;
- }
- else
- {
- m_boundary_counter = 0;
- }
-
- if ( ! no_enters_detected )
- {
- if ( op_blocked
- && it->operations[op_id].position == overlay::position_back )
- {
-
-
- if (boundary_checker.is_endpoint_boundary(it->point))
- {
- update<boundary, boundary, '0', TransposeResult>(res);
- }
- }
-
-
-
- }
-
- else
- {
- bool const this_b = is_ip_on_boundary(it->point, it->operations[op_id],
- boundary_checker);
-
- if ( this_b )
- {
- update<boundary, boundary, '0', TransposeResult>(res);
- }
-
- else
- {
- update<interior, boundary, '0', TransposeResult>(res);
- }
-
- if ( it->operations[op_id].position != overlay::position_front )
- {
-
-
-
- bool const first_point = first_in_range || m_first_from_unknown;
- bool const first_from_inside =
- first_point && calculate_from_inside<op_id>(geometry,
- other_geometry,
- *it,
- strategy);
- if ( first_from_inside )
- {
- update<interior, interior, '1', TransposeResult>(res);
-
- m_exit_watcher.enter(*it);
-
- m_first_from_unknown = false;
- m_first_from_unknown_boundary_detected = false;
- }
- else
- {
- if BOOST_GEOMETRY_CONSTEXPR (util::is_multi<OtherGeometry>::value)
-
-
- {
- m_first_from_unknown = true;
- }
- else
- {
- update<interior, exterior, '1', TransposeResult>(res);
- }
- }
-
- if ( first_point && ( !this_b || op_blocked ) )
- {
- bool const front_b = boundary_checker.is_endpoint_boundary(
- range::front(sub_range(geometry, seg_id)));
-
- if ( front_b )
- {
- if ( first_from_inside )
- {
- update<boundary, interior, '0', TransposeResult>(res);
- }
- else
- {
- if BOOST_GEOMETRY_CONSTEXPR (util::is_multi<OtherGeometry>::value)
-
-
- {
- BOOST_GEOMETRY_ASSERT(m_first_from_unknown);
- m_first_from_unknown_boundary_detected = true;
- }
- else
- {
- update<boundary, exterior, '0', TransposeResult>(res);
- }
- }
- }
- }
- }
- }
-
- if ( m_boundary_counter == 0
- || it->operations[op_id].is_collinear )
- {
-
- m_exit_watcher.exit(*it);
- }
- }
-
- m_previous_turn_ptr = boost::addressof(*it);
-
- m_previous_operation = op;
- }
-
- template <typename Result,
- typename TurnIt,
- typename Geometry,
- typename OtherGeometry,
- typename BoundaryChecker>
- void apply(Result & res,
- TurnIt first, TurnIt last,
- Geometry const& geometry,
- OtherGeometry const& ,
- BoundaryChecker const& boundary_checker)
- {
- boost::ignore_unused(first, last);
-
-
-
-
- if BOOST_GEOMETRY_CONSTEXPR (util::is_multi<OtherGeometry>::value)
- {
- if (m_first_from_unknown)
- {
- update<interior, exterior, '1', TransposeResult>(res);
- if ( m_first_from_unknown_boundary_detected )
- {
- update<boundary, exterior, '0', TransposeResult>(res);
- }
-
-
-
- }
- }
-
-
- if (
- m_previous_operation == overlay::operation_union
- && !m_interior_detected )
- {
-
- update<interior, exterior, '1', TransposeResult>(res);
- BOOST_GEOMETRY_ASSERT(first != last);
- BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr);
- segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = boundary_checker.is_endpoint_boundary(
- range::back(sub_range(geometry, prev_seg_id)));
-
- if ( prev_back_b )
- {
- update<boundary, exterior, '0', TransposeResult>(res);
- }
- }
-
- else if ( m_previous_operation == overlay::operation_intersection
- || m_interior_detected )
- {
-
- update<interior, interior, '1', TransposeResult>(res);
- m_interior_detected = false;
- BOOST_GEOMETRY_ASSERT(first != last);
- BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr);
- segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = boundary_checker.is_endpoint_boundary(
- range::back(sub_range(geometry, prev_seg_id)));
-
- if ( prev_back_b )
- {
- update<boundary, interior, '0', TransposeResult>(res);
- }
- }
-
-
-
-
-
-
-
-
-
- if ( m_previous_operation == overlay::operation_continue )
- {
- update<interior, exterior, '1', TransposeResult>(res);
- segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = boundary_checker.is_endpoint_boundary(
- range::back(sub_range(geometry, prev_seg_id)));
-
- if ( prev_back_b )
- {
- update<boundary, exterior, '0', TransposeResult>(res);
- }
- }
-
- m_exit_watcher.reset();
- m_boundary_counter = 0;
- m_first_from_unknown = false;
- m_first_from_unknown_boundary_detected = false;
- }
- private:
- exit_watcher<TurnInfo, op_id> m_exit_watcher;
- segment_watcher<same_single> m_seg_watcher;
- TurnInfo * m_previous_turn_ptr;
- overlay::operation_type m_previous_operation;
- unsigned m_boundary_counter;
- bool m_interior_detected;
- const segment_identifier * m_first_interior_other_id_ptr;
- bool m_first_from_unknown;
- bool m_first_from_unknown_boundary_detected;
- };
-
-
- template <typename Result,
- typename TurnIt,
- typename Analyser,
- typename Geometry,
- typename OtherGeometry,
- typename BoundaryChecker,
- typename Strategy>
- static inline void analyse_each_turn(Result & res,
- Analyser & analyser,
- TurnIt first, TurnIt last,
- Geometry const& geometry,
- OtherGeometry const& other_geometry,
- BoundaryChecker const& boundary_checker,
- Strategy const& strategy)
- {
- if ( first == last )
- {
- return;
- }
- for ( TurnIt it = first ; it != last ; ++it )
- {
- analyser.apply(res, it,
- geometry, other_geometry,
- boundary_checker,
- strategy);
- if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
- {
- return;
- }
- }
- analyser.apply(res, first, last,
- geometry, other_geometry,
- boundary_checker);
- }
-
-
- struct less_ring
- {
- template <typename Turn>
- inline bool operator()(Turn const& left, Turn const& right) const
- {
- return left.operations[1].seg_id.multi_index < right.operations[1].seg_id.multi_index
- || ( left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index
- && left.operations[1].seg_id.ring_index < right.operations[1].seg_id.ring_index );
- }
- };
-
- struct has_boundary_intersection
- {
- has_boundary_intersection()
- : result(false) {}
- template <typename Turn>
- inline void operator()(Turn const& turn)
- {
- if ( turn.operations[1].operation == overlay::operation_continue )
- result = true;
- }
- bool result;
- };
-
-
- template <typename It, typename Fun>
- static inline It find_next_ring(It first, It last, Fun & fun)
- {
- if ( first == last )
- return last;
- signed_size_type const multi_index = first->operations[1].seg_id.multi_index;
- signed_size_type const ring_index = first->operations[1].seg_id.ring_index;
- fun(*first);
- ++first;
- for ( ; first != last ; ++first )
- {
- if ( multi_index != first->operations[1].seg_id.multi_index
- || ring_index != first->operations[1].seg_id.ring_index )
- {
- return first;
- }
- fun(*first);
- }
- return last;
- }
-
-
-
- template <typename TurnInfo>
- class areal_boundary_analyser
- {
- public:
- areal_boundary_analyser()
- : is_union_detected(false)
- , m_previous_turn_ptr(NULL)
- {}
- template <typename TurnIt, typename Strategy>
- bool apply(TurnIt , TurnIt it, TurnIt last,
- Strategy const& strategy)
- {
- overlay::operation_type op = it->operations[1].operation;
- if ( it != last )
- {
- if ( op != overlay::operation_union
- && op != overlay::operation_continue )
- {
- return true;
- }
- if ( is_union_detected )
- {
- BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL);
- if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point, strategy) )
- {
-
- return false;
- }
- else if ( op == overlay::operation_continue )
- {
- is_union_detected = false;
- }
- }
- if ( op == overlay::operation_union )
- {
- is_union_detected = true;
- m_previous_turn_ptr = boost::addressof(*it);
- }
- return true;
- }
- else
- {
- return false;
- }
- }
- bool is_union_detected;
- private:
- const TurnInfo * m_previous_turn_ptr;
- };
- };
- template <typename Geometry1, typename Geometry2>
- struct areal_linear
- {
- typedef linear_areal<Geometry2, Geometry1, true> linear_areal_type;
- static const bool interruption_enabled = linear_areal_type::interruption_enabled;
- template <typename Result, typename Strategy>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Result & result,
- Strategy const& strategy)
- {
- linear_areal_type::apply(geometry2, geometry1, result, strategy);
- }
- template <typename BoundaryChecker2, typename Result, typename Strategy>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
- BoundaryChecker2 const& boundary_checker2,
- Result & result,
- Strategy const& strategy)
- {
- linear_areal_type::apply(geometry2, geometry1, boundary_checker2, result, strategy);
- }
- };
- }}
- #endif
- }}
- #endif
|