From 2fcbf1c7c95d4effd923dcbe57c16b1fea769e3e Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Thu, 3 Mar 2011 11:21:59 +0000 Subject: [PATCH] Refactored assemble.hpp, now three parts: select_rings, assign_parents, add_rings Rewritten ring_properties Obsoleted add_to_containment.hpp, assemble.hpp [SVN r69510] --- .../algorithms/detail/overlay/add_rings.hpp | 112 +++ .../detail/overlay/add_to_containment.hpp | 119 +-- .../algorithms/detail/overlay/assemble.hpp | 677 +----------------- .../detail/overlay/assign_parents.hpp | 182 +++++ .../detail/overlay/copy_segment_point.hpp | 1 + .../algorithms/detail/overlay/get_ring.hpp | 25 +- .../detail/overlay/handle_tangencies.hpp | 1 + .../algorithms/detail/overlay/overlay.hpp | 85 ++- .../detail/overlay/ring_properties.hpp | 265 ++----- .../detail/overlay/select_rings.hpp | 217 ++++++ .../algorithms/detail/overlay/within_util.hpp | 97 +++ .../algorithms/detail/ring_identifier.hpp | 8 +- .../detail/overlay/add_to_containment.hpp | 63 +- .../detail/overlay/select_rings.hpp | 61 ++ .../geometry/multi/algorithms/difference.hpp | 3 +- .../multi/algorithms/intersection.hpp | 2 +- .../boost/geometry/multi/algorithms/union.hpp | 3 +- include/boost/geometry/multi/multi.hpp | 1 - .../agnostic/point_in_poly_winding.hpp | 1 - 19 files changed, 815 insertions(+), 1108 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/overlay/add_rings.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/select_rings.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/within_util.hpp create mode 100644 include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp diff --git a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp new file mode 100644 index 000000000..fcdb52ad9 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp @@ -0,0 +1,112 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright Barend Gehrels 2011, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +< + typename GeometryOut, + typename Geometry1, + typename Geometry2, + typename RingCollection +> +inline void convert_and_add(GeometryOut& result, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RingCollection const& collection, + ring_identifier id, + bool reversed, bool append) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + typedef typename geometry::tag::type tag_out; + + if (id.source_index == 0) + { + convert_ring::apply(result, + get_ring::apply(id, geometry1), + append, reversed); + } + else if (id.source_index == 1) + { + convert_ring::apply(result, + get_ring::apply(id, geometry2), + append, reversed); + } + else if (id.source_index == 2) + { + convert_ring::apply(result, + get_ring::apply(id, collection), + append, reversed); + } +} + +template +< + typename GeometryOut, + typename SelectionMap, + typename Geometry1, + typename Geometry2, + typename RingCollection, + typename OutputIterator +> +inline OutputIterator add_rings(SelectionMap const& map, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RingCollection const& collection, + OutputIterator out) +{ + typedef typename SelectionMap::const_iterator iterator; + + for (iterator it = boost::begin(map); + it != boost::end(map); + ++it) + { + if (it->second.parent.source_index == -1) + { + GeometryOut result; + convert_and_add(result, geometry1, geometry2, collection, + it->first, it->second.reversed, false); + + // Add children + for (typename std::vector::const_iterator child_it + = it->second.children.begin(); + child_it != it->second.children.end(); + ++child_it) + { + iterator mit = map.find(*child_it); + if (mit != map.end()) + { + convert_and_add(result, geometry1, geometry2, collection, + *child_it, mit->second.reversed, true); + } + } + *out++ = result; + } + } + return out; +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/add_to_containment.hpp b/include/boost/geometry/algorithms/detail/overlay/add_to_containment.hpp index 990987663..30f569c92 100644 --- a/include/boost/geometry/algorithms/detail/overlay/add_to_containment.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/add_to_containment.hpp @@ -1,118 +1 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_TO_CONTAINMENT_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_TO_CONTAINMENT_HPP - - -#include -#include -#include - - -#include -#include -#include -#include - -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace overlay -{ - - -template -struct add_to_containment -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types) - ); -}; - -template -struct add_to_containment -{ - template - static inline void apply(ContainmentContainer& container, - ring_identifier const& id, Ring const& ring, Map const& map, - bool dissolve) - { - typedef typename range_value::type prop; - bool found = map.find(id) != map.end(); - if (! dissolve || ! found) - { - // For dissolve, do not add intersected rings - container.push_back(prop(id, ring, found)); - } - } -}; - -template -struct add_to_containment -{ - template - static inline void apply(ContainmentContainer& container, - ring_identifier const& id, Box const& box, Map const& map, - bool dissolve) - { - typedef typename range_value::type prop; - bool found = map.find(id) != map.end(); - if (! dissolve || ! found) - { - container.push_back(prop(id, box, found)); - } - } -}; - - -template -struct add_to_containment -{ - template - static inline void apply(ContainmentContainer& container, - ring_identifier const& id, Polygon const& polygon, Map const& map, - bool dissolve) - { - // Add exterior ring and interior rings - ring_identifier copy = id; - - typedef add_to_containment - < - ring_tag, - typename ring_type::type - > policy; - - policy::apply(container, copy, exterior_ring(polygon), map, dissolve); - copy.ring_index = 0; - - typename interior_return_type::type rings - = interior_rings(polygon); - for (BOOST_AUTO(it, boost::begin(rings)); it != boost::end(rings); - ++it, ++copy.ring_index) - { - policy::apply(container, copy, *it, map, dissolve); - } - } -}; - - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_TO_CONTAINMENT_HPP +//obsolete \ No newline at end of file diff --git a/include/boost/geometry/algorithms/detail/overlay/assemble.hpp b/include/boost/geometry/algorithms/detail/overlay/assemble.hpp index 47d44eecf..30f569c92 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assemble.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assemble.hpp @@ -1,676 +1 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSEMBLE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSEMBLE_HPP - - -#include -#include - -#include - -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -# define BOOST_GEOMETRY_DEBUG_IDENTIFIER -# include -#endif - - -#include -#include -#include -#include -#include -#include -//#include - - -#include -#include -#include - -#include - -#include -#include - - - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace overlay -{ - - -template -struct within_code -{}; - -template -struct within_code -{ - static inline int apply(Point const& point, Box const& box) - { - // 1. Check outside - if (get<0>(point) < get(box) - || get<0>(point) > get(box) - || get<1>(point) < get(box) - || get<1>(point) > get(box)) - { - return -1; - } - // 2. Check border - if (geometry::math::equals(get<0>(point), get(box)) - || geometry::math::equals(get<0>(point), get(box)) - || geometry::math::equals(get<1>(point), get(box)) - || geometry::math::equals(get<1>(point), get(box))) - { - return 0; - } - return 1; - } -}; -template -struct within_code -{ - static inline int apply(Point const& point, Ring const& ring) - { - // Same as point_in_ring but here ALWAYS with winding. - typedef strategy::within::winding strategy_type; - - return detail::within::point_in_ring - < - Point, - Ring, - order_as_direction::value>::value, - geometry::closure::value, - strategy_type - >::apply(point, ring, strategy_type()); - } -}; - - -template -inline int point_in_ring(Point const& point, Geometry const& geometry) -{ - return within_code::type, Point, Geometry> - ::apply(point, geometry); -} - -template -inline bool within_or_touch(Point const& point, Geometry const& geometry) -{ - return within_code::type, Point, Geometry> - ::apply(point, geometry) >= 0; -} - - -// Skip for assemble process -template -inline bool skip(TurnInfo const& turn_info) -{ - return (turn_info.discarded || turn_info.both(operation_union)) - && ! turn_info.any_blocked() - && ! turn_info.both(operation_intersection) - ; -} - - - -template -inline void map_turns(Map& map, TurnPoints const& turn_points) -{ - typedef typename boost::range_value::type turn_point_type; - typedef typename turn_point_type::container_type container_type; - - int index = 0; - for (typename boost::range_iterator::type - it = boost::begin(turn_points); - it != boost::end(turn_points); - ++it, ++index) - { - if (! skip(*it)) - { - int op_index = 0; - for (typename boost::range_iterator::type - op_it = boost::begin(it->operations); - op_it != boost::end(it->operations); - ++op_it, ++op_index) - { - ring_identifier ring_id - ( - op_it->seg_id.source_index, - op_it->seg_id.multi_index, - op_it->seg_id.ring_index - ); - map[ring_id]++; - } - } - } -} - - -template -< - typename Container, - typename Geometry1, - typename Geometry2, - typename RingCollection, - typename Box -> -struct enrich_containment -{ - - typedef typename boost::range_value::type item_type; - typedef typename geometry::tag::type tag1; - typedef typename geometry::tag::type tag2; - typedef void tag3; // For the ring-container - - - static inline void assign(item_type& larger, item_type& smaller, overlay_type direction) - { - typedef typename geometry::coordinate_type - < - Geometry1 - >::type coordinate_type; - - if (larger.signum != 0 && smaller.signum != 0) - { - if (larger.signum == 1) - { - smaller.push(larger, direction); - } - else if (larger.signum == -1) - { - smaller.pop(/*from*/larger); - } - } - } - - - // Creates a selection of pointers within the specified box - template - static inline void select_by_box(Collection& selection, - Collection const& collection, - Box const& box) - { - for (typename boost::range_iterator::type - it = boost::begin(collection); - it != boost::end(collection); - ++it) - { - if (! geometry::detail::disjoint::disjoint_box_box(box, (*it)->box)) - { - selection.push_back(*it); - } - } - } - - static inline bool contains(item_type const& item1, item_type const& item2, - Geometry1 const& geometry1, Geometry2 const& geometry2, - RingCollection const& collection) - { - int code = -1; - if (item1.ring_id.source_index == 0) - { - code = point_in_ring(item2.point, - get_ring::apply(item1.ring_id, geometry1)); - } - else if (item1.ring_id.source_index == 1) - { - code = point_in_ring(item2.point, - get_ring::apply(item1.ring_id, geometry2)); - } - else if (item1.ring_id.source_index == 2) - { - code = point_in_ring(item2.point, - get_ring::apply(item1.ring_id, collection)); - } - else - { - return false; - } - return code == 0 ? item1.area < 0 : code == 1; - } - - template - static inline void enrich(Selection& selection, Map& map, - Geometry1 const& geometry1, Geometry2 const& geometry2, - RingCollection const& collection, - overlay_type direction) - { - typedef typename boost::range_iterator::type iterator; - - for (iterator it1 = boost::begin(selection); - it1 != boost::end(selection); - ++it1) - { -//std::cout << "."; - item_type& item1 = **it1; - iterator it2 = it1; - for (it2++; it2 != boost::end(selection); ++it2) - { - std::pair p - = std::make_pair(*it1, *it2); - bool processed = map[p]; - if (! processed) - { - map[p] = true; - - item_type& item2 = **it2; - if (geometry::within(item2.point, item1.box) - && abs(item2.area) < abs(item1.area) - && contains(item1, item2, geometry1, geometry2, - collection) - ) - { - assign(item1, item2, direction); - } - } - } - } - } - - /*** - template - static inline void divide_and_conquer(Selection& selection, Map& map, - Geometry1 const& geometry1, Geometry2 const& geometry2, - RingCollection const& collection, - int direction, Box const& box, - std::size_t iteration = 0, std::size_t previous_count = 0) - { - std::size_t n = boost::size(selection); -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << "spatial divide n=" -<< n -<< " previous=" << previous_count -<< " iteration=" << iteration -<< " box: " << geometry::dsv(box) << std::endl; -#endif - - if (iteration > 3) - { - enrich(selection, map, geometry1, geometry2, collection, direction); - return; - } - - // Divide the complete box in two (alternating) halves - Box lower = box, upper = box; - typedef typename geometry::coordinate_type::type coordinate_type; - coordinate_type two = 2.0; - coordinate_type mid - = (geometry::get(box) - + geometry::get(box)) / two; - - geometry::set(lower, mid); - geometry::set(upper, mid); - - // select - std::vector lower_sel, upper_sel; - select_by_box(lower_sel, selection, lower); - select_by_box(upper_sel, selection, upper); - - divide_and_conquer<1 - Dimension>(lower_sel, map, geometry1, geometry2, - collection, direction, lower, iteration + 1, n); - divide_and_conquer<1 - Dimension>(upper_sel, map, geometry1, geometry2, - collection, direction, upper, iteration + 1, n); - } - ***/ - - static inline void enrich(Container& container, - Geometry1 const& geometry1, Geometry2 const& geometry2, - RingCollection const& collection, - overlay_type direction) - { - typedef typename boost::range_iterator::type iterator; - - int n = 0; - - for (iterator it1 = boost::begin(container); - it1 != boost::end(container); - ++it1) - { - item_type& item1 = *it1; -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << item1.ring_id << " area: " << item1.area << std::endl; -#endif - iterator it2 = it1; - for (it2++; it2 != boost::end(container); ++it2) - { - item_type& item2 = *it2; - if (within_or_touch(item2.point, item1.box) - && geometry::math::abs(item2.area) - < geometry::math::abs(item1.area) - && contains(item1, item2, geometry1, geometry2, collection) - ) - { -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << " -> contains " << item2.ring_id; -#endif - n++; - assign(item1, item2, direction); -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << std::endl; -#endif - } - } - } - //std::cout << "Enriched: " << n << std::endl; - } - - - - static inline void apply(Container& container, - Geometry1 const& geometry1, Geometry2 const& geometry2, - RingCollection const& collection, - overlay_type direction, Box const& ) - { - if (boost::size(container) == 0) - { - return; - } - enrich(container, geometry1, geometry2, collection, direction); - -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE - for (typename boost::range_iterator::type - it = boost::begin(container); - it != boost::end(container); - ++it) - { - std::cout << *it << std::endl; - } -#endif - - /*** - return; - - // Method using divide and conquer (does NOT work corretly!) - - std::vector selection; - selection.reserve(boost::size(container)); - for (typename boost::range_iterator::type - it = boost::begin(container); - it != boost::end(container); - ++it) - { - selection.push_back(&(*it)); - } - - std::map, bool> map; - divide_and_conquer<1>(selection, map, geometry1, geometry2, collection, - direction, box); - ***/ - } -}; - - -template -< - typename GeometryOut, - typename Container, - typename Geometry1, - typename Geometry2, - typename RingCollection, - typename OutputIterator -> -inline OutputIterator add_all_rings(Container& container, - Geometry1 const& geometry1, Geometry2 const& geometry2, - RingCollection const& collection, - overlay_type direction, - OutputIterator out) -{ - typedef typename boost::range_iterator::type iterator; - typedef typename geometry::tag::type tag_out; - typedef typename geometry::tag::type tag1; - typedef typename geometry::tag::type tag2; - typedef void tag3; // For the ring-container - - - bool result_filled = false; - GeometryOut result; - ring_identifier previous_id; - previous_id.source_index = -1; - - for (iterator it = boost::begin(container); - it != boost::end(container); - ++it) - { - - bool const include_as_interior = result_filled - && it->id(direction) == previous_id - && it->included(direction); - - bool include_and_reverse = direction == overlay_difference - && ! include_as_interior - && it->negative() - && it->included(direction); - - if (it->positive() || include_and_reverse) - { - // If it is an outer ring, it is included if there are no parents - // (union) or if there are parents (intersection) - // or for difference it is an exterior ring but becomes an interior ring - if (it->included(direction)) - { - if (result_filled && ! include_as_interior) - { - *out++ = result; - previous_id.source_index = -1; - result_filled = false; - geometry::clear(result); - } - - if (include_as_interior) - { - include_and_reverse = true; - } - - previous_id = it->ring_id; - result_filled = true; - if (it->ring_id.source_index == 0) - { - convert_ring::apply(result, - get_ring::apply(it->ring_id, geometry1), - include_as_interior, include_and_reverse); - } - else if (it->ring_id.source_index == 1) - { - convert_ring::apply(result, - get_ring::apply(it->ring_id, geometry2), - include_as_interior, include_and_reverse); - } - else if (it->ring_id.source_index == 2) - { - convert_ring::apply(result, - get_ring::apply(it->ring_id, collection), - include_as_interior, include_and_reverse); - } - } - } - else if (include_as_interior) - { - // If it is an interior ring, it is included if - // it's parent-id matches the id of the outputted exterior ring - if (it->ring_id.source_index == 0) - { - convert_ring::apply(result, - get_ring::apply(it->ring_id, - geometry1), true, false); - } - else if (it->ring_id.source_index == 1) - { - convert_ring::apply(result, - get_ring::apply(it->ring_id, - geometry2), true, false); - } - else if (it->ring_id.source_index == 2) - { - convert_ring::apply(result, - get_ring::apply(it->ring_id, - collection), true, false); - } - } - } - if (result_filled) - { - *out++ = result; - } - return out; -} - - -template -< - typename GeometryOut, - typename Rings, typename Map, - typename Geometry1, typename Geometry2, - typename OutputIterator -> -inline OutputIterator assemble(Rings const& rings, Map const& map, - Geometry1 const& geometry1, - Geometry2 const& geometry2, - overlay_type direction, bool , bool splitted, - OutputIterator out) -{ - typedef typename geometry::tag::type tag1; - typedef typename geometry::tag::type tag2; - typedef typename geometry::tag::type tag_out; - - typedef typename geometry::point_type::type point_type; - typedef typename boost::range_value::type ring_type; - -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << "assemble" << std::endl; -#endif - - typedef std::vector - < - ring_properties - > ring_properties_container_type; - ring_properties_container_type ring_properties_container; - - bool const dissolve = direction == overlay_dissolve; - - if (! splitted) - { - add_to_containment - < - tag1, - Geometry1 - >::apply(ring_properties_container, - ring_identifier(0, -1,-1), geometry1, - map, dissolve); - } - if (! dissolve) - { - add_to_containment - < - tag2, - Geometry2 - >::apply(ring_properties_container, - ring_identifier(1, -1,-1), geometry2, - map, false); - } - - // Add all produced rings using source index 2 - { - ring_identifier id(2, 0, -1); - for (typename boost::range_iterator::type - it = boost::begin(rings); - it != boost::end(rings); - ++it, ++id.multi_index) - { - ring_properties_container.push_back( - ring_properties(id, *it, false, true)); - } - } - - bool only_positive = true; - { - int pos=0, neg=0; - for (typename ring_properties_container_type::const_iterator - it = boost::begin(ring_properties_container); - it != boost::end(ring_properties_container); - ++it) - { - if (it->positive()) - { - pos++; - } - else - { - neg++; - only_positive = false; - } - } -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE - std::cout << "assemble, pos=" << pos << " neg=" << neg << std::endl; -#endif - } - - //if (! only_positive) - { - typedef model::box box_type; - box_type total = geometry::make_envelope(geometry1); - geometry::combine(total, - geometry::make_envelope(geometry2)); - - -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << "assemble.properties sort " - << boost::size(ring_properties_container) << std::endl; -#endif - std::sort(boost::begin(ring_properties_container), - boost::end(ring_properties_container)); - - - -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << "assemble.enrich containment" << std::endl; -#endif - enrich_containment - < - ring_properties_container_type, - Geometry1, - Geometry2, - Rings, - model::box - >::apply(ring_properties_container, - geometry1, geometry2, rings, direction, total); - - // Sort container on parent-id -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << "assemble.properties sort on parent-id " - << boost::size(ring_properties_container) << std::endl; -#endif - std::sort(boost::begin(ring_properties_container), - boost::end(ring_properties_container), - sort_on_id_or_parent_id - < - ring_properties - >(direction)); - } -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << "assemble.add rings" << std::endl; -#endif - return add_all_rings(ring_properties_container, - geometry1, geometry2, rings, direction, out); -} - - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSEMBLE_HPP +//obsolete \ No newline at end of file diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp new file mode 100644 index 000000000..8c6b5dd8c --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -0,0 +1,182 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright Barend Gehrels 2011, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + + +template +< + typename Item, + typename Geometry1, typename Geometry2, + typename RingCollection +> +static inline bool contains(ring_identifier ring_id, Item const& item1, Item const& item2, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RingCollection const& collection) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + + int code = -1; + switch (ring_id.source_index) + { + case 0 : + code = point_in_ring(item2.point, + get_ring::apply(ring_id, geometry1)); + break; + case 1 : + code = point_in_ring(item2.point, + get_ring::apply(ring_id, geometry2)); + break; + case 2 : + // Within if it is within one of the collection + for (BOOST_AUTO(it, boost::begin(collection)); it != boost::end(collection); ++it) + { + int subcode = point_in_ring(item2.point, + get_ring::apply(ring_id, *it)); + if (subcode > code) + { + code = subcode; + } + } + break; + } + return code == 0 ? item1.get_area() < 0 : code == 1; +} + + +template +struct ring_info_helper +{ + typedef typename geometry::area_result::type area_type; + + ring_identifier id; + area_type area; + model::box envelope; + + inline ring_info_helper(ring_identifier i, area_type a) + : id(i), area(a) + {} + + // To be sorted decending + inline bool operator<(ring_info_helper const& other) const + { + return abs(this->area) > abs(other.area); + } +}; + + +template +< + typename Geometry1, typename Geometry2, + typename RingCollection, + typename RingMap +> +inline void assign_parents(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RingCollection const& collection, + RingMap& ring_map) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + + typedef typename RingMap::mapped_type ring_info_type; + typedef typename ring_info_type::point_type point_type; + + typedef typename RingMap::iterator map_iterator_type; + + // A map is not sortable, so copy ring_id/area and added envelope to vector + { + typedef ring_info_helper helper; + typedef std::vector vector_type; + typedef typename boost::range_iterator::type vector_iterator_type; + + vector_type vector; + + for (map_iterator_type it = boost::begin(ring_map); it != boost::end(ring_map); ++it) + { + vector.push_back(helper(it->first, abs(it->second.area))); + switch(it->first.source_index) + { + case 0 : + geometry::envelope(get_ring::apply(it->first, geometry1), + vector.back().envelope); + break; + case 1 : + geometry::envelope(get_ring::apply(it->first, geometry2), + vector.back().envelope); + break; + case 2 : + geometry::envelope(get_ring::apply(it->first, collection), + vector.back().envelope); + break; + } + } + + std::sort(vector.begin(), vector.end()); + + // Assign parents + // Semi-quadratic loop over rings to compare them to each other (envelope first) + // Walks from largest abs(area) to smallest -> most direct parent comes last. + for (vector_iterator_type out_it = boost::begin(vector); out_it != boost::end(vector); ++out_it) + { + ring_info_type& outer = ring_map[out_it->id]; + + if (outer.get_area() > 0) + { + vector_iterator_type inn_it = out_it; + for (++inn_it; inn_it != boost::end(vector); ++inn_it) + { + ring_info_type& inner = ring_map[inn_it->id]; + + if (inner.get_area() < 0 + && geometry::within(inner.point, out_it->envelope) + && contains(out_it->id, outer, inner, geometry1, geometry2, collection)) + { + inner.parent = out_it->id; + } + } + } + } + } + + // Assign childlist + for (map_iterator_type it = boost::begin(ring_map); it != boost::end(ring_map); ++it) + { + if (it->second.parent.source_index >= 0) + { + ring_map[it->second.parent].children.push_back(it->first); + } + } + +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index f3acb23f5..0b8c0ef1a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -10,6 +10,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP +#include #include #include diff --git a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp index 33e535c6d..933ae67ff 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp @@ -32,17 +32,7 @@ template struct get_ring {}; -template<> -struct get_ring -{ - template - static inline Ring const& apply(ring_identifier const& , Ring const& ring) - { - return ring; - } -}; - - +// "void" is mapped to a container of rings (multi-ring but that does not exist) template<> struct get_ring { @@ -55,6 +45,19 @@ struct get_ring }; + + +template<> +struct get_ring +{ + template + static inline Ring const& apply(ring_identifier const& , Ring const& ring) + { + return ring; + } +}; + + template<> struct get_ring { diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp index 7442f32d3..764dcd86b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp @@ -13,6 +13,7 @@ #include #include +#include namespace boost { namespace geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 48bce0805..1d2cd49d1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -16,7 +16,6 @@ #include -#include #include #include #include @@ -31,6 +30,11 @@ #include +#include +#include +#include +#include + #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE # include @@ -46,13 +50,59 @@ namespace detail { namespace overlay { +// Skip for assemble process +template +inline bool skip(TurnInfo const& turn_info) +{ + return (turn_info.discarded || turn_info.both(operation_union)) + && ! turn_info.any_blocked() + && ! turn_info.both(operation_intersection) + ; +} + + + + +template +inline void map_turns(Map& map, TurnPoints const& turn_points) +{ + typedef typename boost::range_value::type turn_point_type; + typedef typename turn_point_type::container_type container_type; + + int index = 0; + for (typename boost::range_iterator::type + it = boost::begin(turn_points); + it != boost::end(turn_points); + ++it, ++index) + { + if (! skip(*it)) + { + int op_index = 0; + for (typename boost::range_iterator::type + op_it = boost::begin(it->operations); + op_it != boost::end(it->operations); + ++op_it, ++op_index) + { + ring_identifier ring_id + ( + op_it->seg_id.source_index, + op_it->seg_id.multi_index, + op_it->seg_id.ring_index + ); + map[ring_id]++; + } + } + } +} + + template < typename Geometry1, typename Geometry2, bool Reverse1, bool Reverse2, bool ReverseOut, typename OutputIterator, typename GeometryOut, - overlay_type Direction, + overlay_type Direction, typename Strategy > struct overlay @@ -88,8 +138,7 @@ struct overlay { std::map map; ring_container_type rings; - return assemble(rings, map, - geometry1, geometry2, Direction, false, false, out); + ////return assemble(rings, map, geometry1, geometry2, Direction, false, false, out); } return out; } @@ -110,7 +159,7 @@ std::cout << "get turns" << std::endl; std::cout << "enrich" << std::endl; #endif typename Strategy::side_strategy_type side_strategy; - geometry::enrich_intersection_points(turn_points, + geometry::enrich_intersection_points(turn_points, Direction == overlay_union ? boost::geometry::detail::overlay::operation_union : boost::geometry::detail::overlay::operation_intersection, @@ -142,8 +191,30 @@ std::cout << "traverse" << std::endl; std::map map; map_turns(map, turn_points); - return assemble(rings, map, - geometry1, geometry2, Direction, false, false, out); + //return assemble(rings, map, geometry1, geometry2, Direction, false, false, out); + + typedef ring_properties::type> info; + + std::map selected; + + select_rings(geometry1, geometry2, map, selected); + + // Add rings from container + { + ring_identifier id(2, 0, -1); + for (typename boost::range_iterator::type + it = boost::begin(rings); + it != boost::end(rings); + ++it) + { + selected[id] = info(*it); + id.multi_index++; + } + } + + assign_parents(geometry1, geometry2, rings, selected); + return add_rings(selected, geometry1, geometry2, rings, out); + } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp index 0fa253ad9..92df394cd 100644 --- a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // -// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands. +// Copyright Barend Gehrels 2011, Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -10,253 +10,68 @@ #include -#include -#include +#include #include -#include -#include - -#include namespace boost { namespace geometry { +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + template struct ring_properties { typedef Point point_type; - typedef model::box box_type; + typedef typename area_result::type area_type; - ring_identifier ring_id; - typename area_result::type area; - int signum; + // Filled by "select_rings" + Point point; + area_type area; - bool intersects; - bool produced; - bool diff_included; + int within_code; + bool reversed; - // "Stack"/counter of non-intersecting parent rings. - // This denotes if it a negative ring should be included, - int parent_count; + // Filled/used by "assign_rings" + ring_identifier parent; + std::vector children; - // ID of the parent - ring_identifier parent_ring_id; - - box_type box; - - point_type point; - bool has_point; - - // Default constructor (necessary for vector, but not called) inline ring_properties() - : intersects(false) - , produced(false) - , diff_included(false) - , parent_count(0) - , has_point(false) - { - parent_ring_id.source_index = -1; - } - - template - inline ring_properties(ring_identifier id, Geometry const& geometry, - bool i, bool p = false) - : ring_id(id) - , area(geometry::area(geometry)) - , intersects(i) - , produced(p) - , diff_included(false) - , parent_count(0) - , box(geometry::make_envelope(geometry)) - { - has_point = geometry::point_on_border(point, geometry, true); - typedef typename coordinate_type::type coordinate_type; - coordinate_type const zero = coordinate_type(); - signum = area > zero ? 1 : area < zero ? -1 : 0; - parent_ring_id.source_index = -1; - } - - inline bool positive() const { return signum == 1; } - inline bool negative() const { return signum == -1; } - - inline bool operator<(ring_properties const& other) const - { - // Normal sorting: in reverse order - return geometry::math::abs(area) > geometry::math::abs(other.area); - } - - inline ring_identifier const& id(overlay_type type) const - { - if (type == overlay_difference - && positive() - && parent_ring_id.source_index == 0 - && ring_id.source_index == 1) - { - return parent_ring_id; - } - - // Return the id of ifself, or of the parent - return positive() || parent_ring_id.source_index < 0 - ? ring_id - : parent_ring_id; - } - - - inline void push(ring_properties const& r, - overlay_type direction) - { - if (r.included(direction)) - { -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << " id.push " << r.ring_id; -#endif - parent_ring_id = r.ring_id; - } - else if (direction == overlay_difference - && r.ring_id.source_index == this->ring_id.source_index - && r.ring_id.source_index == 1) - { -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << " diff.parent " << r.ring_id << " of " << this->ring_id; -#endif - diff_included = true; - } - if (! r.produced || direction == overlay_dissolve) - { -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << " or.push " << r.ring_id; -#endif - parent_count++; - } - } - - - inline void pop(ring_properties const& r) - { - if (! r.produced && parent_count > 0) - { -#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE -std::cout << " or.pop"; -#endif - - parent_count--; - } - } - - - inline bool interior_included(overlay_type direction) const - { - if (negative()) - { - // Original inner rings are included if there - // are two untouched parents (intersection) or one (union); - // Produced ones are included if there is a parent found (should be!) - return (produced && parent_count > 0) - || (direction == overlay_union && parent_count == 1) - || (direction == overlay_dissolve && parent_count == 1) - || (direction == overlay_intersection && parent_count > 1) - || (direction == overlay_difference - && parent_count > 1 - && ring_id.source_index == 2 // produced - ) - ; - } - return false; - } - - inline bool included(overlay_type direction) const - { - if (produced && direction != overlay_dissolve) - { - // Traversed rings are included in all operations, - // because traversal was direction-dependant. - // On dissolve, this is not the case. - return true; - } - if (intersects) - { - // Original rings which have intersections should - // always be skipped - return false; - } - - if (positive()) - { - // Outer rings are included if they don't have parents - // (union,dissolve,difference if source=0) or have parents (intersection) - return (produced && parent_count == 0) - || (direction == overlay_union && parent_count == 0) - || (direction == overlay_dissolve && parent_count == 0) - || (direction == overlay_difference - && parent_count == 0 - && ring_id.source_index == 0) - || (direction == overlay_difference - && parent_count > 0 - && ring_id.source_index == 1) - || (direction == overlay_intersection && parent_count > 0) - ; - } - else if (negative()) - { - // Inner rings are included if the last encountered parent - // matches the operation - return interior_included(direction) - || (direction == overlay_difference && diff_included); - } - return false; - } - - inline bool untouched() const - { - // It should be in comparisons on parent/child if: - // it is produced - // it is not produced, and not intersecting - return ! produced && ! intersects; - } - - -#if defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER) - friend std::ostream& operator<<(std::ostream &os, ring_properties const& prop) - { - os << "prop: " << prop.ring_id << " " << prop.area; - os << " count: " << prop.parent_count; - std::cout << " parent: " << prop.parent_ring_id; - if (prop.produced) std::cout << " produced"; - if (prop.intersects) std::cout << " intersects"; - if (prop.included(overlay_union)) std::cout << " @union"; - if (prop.included(overlay_dissolve)) std::cout << " @dissolve"; - if (prop.included(overlay_intersection)) std::cout << " @intersection"; - if (prop.included(overlay_difference)) std::cout << " @difference"; - return os; - } -#endif - -}; - - -template -struct sort_on_id_or_parent_id -{ - overlay_type m_type; -public : - inline sort_on_id_or_parent_id(overlay_type type) - : m_type(type) + : area(area_type()) + , within_code(0) + , reversed(false) {} - inline bool operator()(Prop const& left, Prop const& right) const + template + inline ring_properties(RingOrBox const& ring_or_box) + : within_code(0) + , reversed(false) { - ring_identifier const& left_id = left.id(m_type); - ring_identifier const& right_id = right.id(m_type); + this->area = geometry::area(ring_or_box); + geometry::point_on_border(this->point, ring_or_box, true); + } - // If it is the same, sort on size descending - return left_id == right_id - ? geometry::math::abs(left.area) > geometry::math::abs(right.area) - : left_id < right_id; + template + inline ring_properties(RingOrBox const& ring_or_box, Geometry const& geometry) + : reversed(false) + { + this->area = geometry::area(ring_or_box); + geometry::point_on_border(this->point, ring_or_box, true); + this->within_code = geometry::within(this->point, geometry) ? 1 : -1; + } + + area_type get_area() const + { + return reversed ? -area : area; } }; +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp new file mode 100644 index 000000000..b1f1b57da --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -0,0 +1,217 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP + + +#include + +#include + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + + +namespace dispatch +{ + + template + struct select_rings + {}; + + template + struct select_rings + { + template + static inline void apply(Box const& box, Geometry const& geometry, ring_identifier const& id, Map& map) + { + typedef typename Map::mapped_type info; + map[id] = info(box, geometry); + } + }; + + template + struct select_rings + { + template + static inline void apply(Ring const& ring, Geometry const& geometry, ring_identifier const& id, Map& map) + { + // MAYBE use within-code algorithm (but not important - all these rings should be untouched) + + typedef typename Map::mapped_type info; + map[id] = info(ring, geometry); + } + }; + + + template + struct select_rings + { + template + static inline void apply(Polygon const& polygon, Geometry const& geometry, ring_identifier id, Map& map) + { + typedef typename geometry::ring_type::type ring_type; + typedef select_rings per_ring; + + per_ring::apply(exterior_ring(polygon), geometry, id, map); + + typename interior_return_type::type rings + = interior_rings(polygon); + for (BOOST_AUTO(it, boost::begin(rings)); it != boost::end(rings); ++it) + { + id.ring_index++; + per_ring::apply(*it, geometry, id, map); + } + } + }; +} + + +template +struct decide +{}; + +template<> +struct decide +{ + template + static bool include(ring_identifier const& id, Code const& code) + { + return code.within_code * -1 == 1; + } + template + static bool reversed(ring_identifier const& , Code const& ) + { + return false; + } + template + static std::string reverse(ring_identifier const& , Code const& ) + { + return ""; + } +}; + +template<> +struct decide +{ + template + static bool include(ring_identifier const& id, Code const& code) + { + bool is_first = id.source_index == 0; + return code.within_code * -1 * (is_first ? 1 : -1) == 1; + } + template + static bool reversed(ring_identifier const& id, Code const& code) + { + return include(id, code) && id.source_index == 1; + } + template + static std::string reverse(ring_identifier const& id, Code const& code) + { + if (include(id, code) && id.source_index == 1) + { + return " REV"; + } + return ""; + } +}; + +template<> +struct decide +{ + template + static bool include(ring_identifier const& id, Code const& code) + { + return code.within_code * 1 == 1; + } + template + static bool reversed(ring_identifier const& , Code const& ) + { + return false; + } + template + static std::string reverse(ring_identifier const& , Code const& ) + { + return ""; + } +}; + + +/*! +\brief The function select_rings select rings based on the overlay-type (union,intersection) +*/ +template +< + overlay_type OverlayType, + typename Geometry1, typename Geometry2, + typename IntersectionMap, typename SelectionMap +> +inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2, + IntersectionMap const& intersection_map, SelectionMap& selection_map) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + + // geometry1 and 2 is a ring, or a (multi)polygon -> dispatch on that + SelectionMap map_with_all; + dispatch::select_rings::apply(geometry1, geometry2, ring_identifier(0, -1, -1), map_with_all); + dispatch::select_rings::apply(geometry2, geometry1, ring_identifier(1, -1, -1), map_with_all); + + selection_map.clear(); + + for (BOOST_AUTO(it, boost::begin(map_with_all)); it != boost::end(map_with_all); ++it) + { + /* + int union_code = it->second.within_code * -1; + bool is_first = it->first.source_index == 0; + std::cout << it->first << " " << it->second.area + << ": " << it->second.within_code + << " union: " << union_code + << " intersection: " << (it->second.within_code * 1) + << " G1-G2: " << (union_code * (is_first ? 1 : -1)) + << " G2-G1: " << (union_code * (is_first ? -1 : 1)) + << " -> " << (decide::include(it->first, it->second) ? "INC" : "") + << decide::reverse(it->first, it->second) + << std::endl; + */ + + bool found = intersection_map.find(it->first) != intersection_map.end(); + if (! found) + { + if (decide::include(it->first, it->second)) + { + selection_map[it->first] = it->second; + selection_map[it->first].reversed = decide::reversed(it->first, it->second); + } + } + } +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/within_util.hpp b/include/boost/geometry/algorithms/detail/overlay/within_util.hpp new file mode 100644 index 000000000..7cd816b15 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/within_util.hpp @@ -0,0 +1,97 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP + + + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +struct within_code +{}; + +template +struct within_code +{ + static inline int apply(Point const& point, Box const& box) + { + // 1. Check outside + if (get<0>(point) < get(box) + || get<0>(point) > get(box) + || get<1>(point) < get(box) + || get<1>(point) > get(box)) + { + return -1; + } + // 2. Check border + if (geometry::math::equals(get<0>(point), get(box)) + || geometry::math::equals(get<0>(point), get(box)) + || geometry::math::equals(get<1>(point), get(box)) + || geometry::math::equals(get<1>(point), get(box))) + { + return 0; + } + return 1; + } +}; +template +struct within_code +{ + static inline int apply(Point const& point, Ring const& ring) + { + // Same as point_in_ring but here ALWAYS with winding. + typedef strategy::within::winding strategy_type; + + return detail::within::point_in_ring + < + Point, + Ring, + order_as_direction::value>::value, + geometry::closure::value, + strategy_type + >::apply(point, ring, strategy_type()); + } +}; + + +template +inline int point_in_ring(Point const& point, Geometry const& geometry) +{ + return within_code::type, Point, Geometry> + ::apply(point, geometry); +} + +template +inline bool within_or_touch(Point const& point, Geometry const& geometry) +{ + return within_code::type, Point, Geometry> + ::apply(point, geometry) >= 0; +} + + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP diff --git a/include/boost/geometry/algorithms/detail/ring_identifier.hpp b/include/boost/geometry/algorithms/detail/ring_identifier.hpp index 8de42e92e..d5a9b411d 100644 --- a/include/boost/geometry/algorithms/detail/ring_identifier.hpp +++ b/include/boost/geometry/algorithms/detail/ring_identifier.hpp @@ -46,11 +46,11 @@ struct ring_identifier } #if defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER) - friend std::ostream& operator<<(std::ostream &os, ring_identifier const& seg_id) + friend std::ostream& operator<<(std::ostream &os, ring_identifier const& ring_id) { - os << "(s:" << seg_id.source_index; - if (seg_id.ring_index >= 0) os << ", r:" << seg_id.ring_index; - if (seg_id.multi_index >= 0) os << ", m:" << seg_id.multi_index; + os << "(s:" << ring_id.source_index; + if (ring_id.ring_index >= 0) os << ", r:" << ring_id.ring_index; + if (ring_id.multi_index >= 0) os << ", m:" << ring_id.multi_index; os << ")"; return os; } diff --git a/include/boost/geometry/multi/algorithms/detail/overlay/add_to_containment.hpp b/include/boost/geometry/multi/algorithms/detail/overlay/add_to_containment.hpp index fbb7a46dd..30f569c92 100644 --- a/include/boost/geometry/multi/algorithms/detail/overlay/add_to_containment.hpp +++ b/include/boost/geometry/multi/algorithms/detail/overlay/add_to_containment.hpp @@ -1,62 +1 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// -// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_ADD_TO_CONTAINMENT_HPP -#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_ADD_TO_CONTAINMENT_HPP - - -#include - -#include -#include -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace overlay -{ - - -template -struct add_to_containment -{ - template - static inline void apply(ContainmentContainer& container, - ring_identifier const& id, MultiPolygon const& multi_polygon, - Map const& map, bool dissolve) - { - ring_identifier copy = id; - copy.multi_index = 0; - - // Add all rings with the updated index - for (typename boost::range_iterator::type it - = boost::begin(multi_polygon); - it != boost::end(multi_polygon); - ++it, ++copy.multi_index) - { - add_to_containment - < - polygon_tag, - typename boost::range_value::type - >::apply(container, copy, *it, map, dissolve); - } - } -}; - - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_ADD_TO_CONTAINMENT_HPP +//obsolete \ No newline at end of file diff --git a/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp new file mode 100644 index 000000000..50db4a670 --- /dev/null +++ b/include/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp @@ -0,0 +1,61 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP +#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP + + + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +namespace dispatch +{ + + template + struct select_rings + { + template + static inline void apply(Multi const& multi, Geometry const& geometry, ring_identifier id, Map& map) + { + typedef typename boost::range_iterator + < + Multi const + >::type iterator_type; + + typedef select_rings::type> per_polygon; + + id.multi_index = 0; + for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it) + { + id.ring_index = -1; + per_polygon::apply(*it, geometry, id, map); + id.multi_index++; + } + } + }; +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP diff --git a/include/boost/geometry/multi/algorithms/difference.hpp b/include/boost/geometry/multi/algorithms/difference.hpp index 912c5799e..51859eca4 100644 --- a/include/boost/geometry/multi/algorithms/difference.hpp +++ b/include/boost/geometry/multi/algorithms/difference.hpp @@ -16,11 +16,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include diff --git a/include/boost/geometry/multi/algorithms/intersection.hpp b/include/boost/geometry/multi/algorithms/intersection.hpp index 676900300..33d85c23b 100644 --- a/include/boost/geometry/multi/algorithms/intersection.hpp +++ b/include/boost/geometry/multi/algorithms/intersection.hpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/geometry/multi/algorithms/union.hpp b/include/boost/geometry/multi/algorithms/union.hpp index c416a7519..9ab8f62fc 100644 --- a/include/boost/geometry/multi/algorithms/union.hpp +++ b/include/boost/geometry/multi/algorithms/union.hpp @@ -16,11 +16,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include diff --git a/include/boost/geometry/multi/multi.hpp b/include/boost/geometry/multi/multi.hpp index 6f017a7c4..6f6ced5ef 100644 --- a/include/boost/geometry/multi/multi.hpp +++ b/include/boost/geometry/multi/multi.hpp @@ -50,7 +50,6 @@ #include #include -#include #include #include #include diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index 426087353..bfd99fe64 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -9,7 +9,6 @@ #ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP #define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP -#include #include #include