1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
15 #include <boost/geometry/algorithms/area.hpp>
16 #include <boost/geometry/algorithms/within.hpp>
17 #include <boost/geometry/algorithms/detail/point_on_border.hpp>
18 #include <boost/geometry/algorithms/detail/ring_identifier.hpp>
19 #include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
20 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
23 namespace boost { namespace geometry
27 #ifndef DOXYGEN_NO_DETAIL
28 namespace detail { namespace overlay
35 template <typename Tag, typename Geometry>
39 template <typename Box>
40 struct select_rings<box_tag, Box>
42 template <typename Geometry, typename Map>
43 static inline void apply(Box const& box, Geometry const& ,
44 ring_identifier const& id, Map& map, bool midpoint)
46 map[id] = typename Map::mapped_type(box, midpoint);
49 template <typename Map>
50 static inline void apply(Box const& box,
51 ring_identifier const& id, Map& map, bool midpoint)
53 map[id] = typename Map::mapped_type(box, midpoint);
57 template <typename Ring>
58 struct select_rings<ring_tag, Ring>
60 template <typename Geometry, typename Map>
61 static inline void apply(Ring const& ring, Geometry const& ,
62 ring_identifier const& id, Map& map, bool midpoint)
64 if (boost::size(ring) > 0)
66 map[id] = typename Map::mapped_type(ring, midpoint);
70 template <typename Map>
71 static inline void apply(Ring const& ring,
72 ring_identifier const& id, Map& map, bool midpoint)
74 if (boost::size(ring) > 0)
76 map[id] = typename Map::mapped_type(ring, midpoint);
82 template <typename Polygon>
83 struct select_rings<polygon_tag, Polygon>
85 template <typename Geometry, typename Map>
86 static inline void apply(Polygon const& polygon, Geometry const& geometry,
87 ring_identifier id, Map& map, bool midpoint)
89 typedef typename geometry::ring_type<Polygon>::type ring_type;
90 typedef select_rings<ring_tag, ring_type> per_ring;
92 per_ring::apply(exterior_ring(polygon), geometry, id, map, midpoint);
94 typename interior_return_type<Polygon const>::type rings
95 = interior_rings(polygon);
96 for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
99 per_ring::apply(*it, geometry, id, map, midpoint);
103 template <typename Map>
104 static inline void apply(Polygon const& polygon,
105 ring_identifier id, Map& map, bool midpoint)
107 typedef typename geometry::ring_type<Polygon>::type ring_type;
108 typedef select_rings<ring_tag, ring_type> per_ring;
110 per_ring::apply(exterior_ring(polygon), id, map, midpoint);
112 typename interior_return_type<Polygon const>::type rings
113 = interior_rings(polygon);
114 for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
117 per_ring::apply(*it, id, map, midpoint);
124 template<overlay_type OverlayType>
129 struct decide<overlay_union>
131 template <typename Code>
132 static bool include(ring_identifier const& , Code const& code)
134 return code.within_code * -1 == 1;
137 template <typename Code>
138 static bool reversed(ring_identifier const& , Code const& )
145 struct decide<overlay_difference>
147 template <typename Code>
148 static bool include(ring_identifier const& id, Code const& code)
150 bool is_first = id.source_index == 0;
151 return code.within_code * -1 * (is_first ? 1 : -1) == 1;
154 template <typename Code>
155 static bool reversed(ring_identifier const& id, Code const& code)
157 return include(id, code) && id.source_index == 1;
162 struct decide<overlay_intersection>
164 template <typename Code>
165 static bool include(ring_identifier const& , Code const& code)
167 return code.within_code * 1 == 1;
170 template <typename Code>
171 static bool reversed(ring_identifier const& , Code const& )
180 overlay_type OverlayType,
181 typename Geometry1, typename Geometry2,
182 typename IntersectionMap, typename SelectionMap
184 inline void update_selection_map(Geometry1 const& geometry1,
185 Geometry2 const& geometry2,
186 IntersectionMap const& intersection_map,
187 SelectionMap const& map_with_all, SelectionMap& selection_map)
189 selection_map.clear();
191 for (typename SelectionMap::const_iterator it = boost::begin(map_with_all);
192 it != boost::end(map_with_all);
196 int union_code = it->second.within_code * -1;
197 bool is_first = it->first.source_index == 0;
198 std::cout << it->first << " " << it->second.area
199 << ": " << it->second.within_code
200 << " union: " << union_code
201 << " intersection: " << (it->second.within_code * 1)
202 << " G1-G2: " << (union_code * (is_first ? 1 : -1))
203 << " G2-G1: " << (union_code * (is_first ? -1 : 1))
204 << " -> " << (decide<OverlayType>::include(it->first, it->second) ? "INC" : "")
205 << decide<OverlayType>::reverse(it->first, it->second)
209 bool found = intersection_map.find(it->first) != intersection_map.end();
212 ring_identifier const id = it->first;
213 typename SelectionMap::mapped_type properties = it->second; // Copy by value
215 // Calculate the "within code" (previously this was done earlier but is
216 // must efficienter here - it can be even more efficient doing it all at once,
217 // using partition, TODO)
218 // So though this is less elegant than before, it avoids many unused point-in-poly calculations
219 switch(id.source_index)
222 properties.within_code
223 = geometry::within(properties.point, geometry2) ? 1 : -1;
226 properties.within_code
227 = geometry::within(properties.point, geometry1) ? 1 : -1;
231 if (decide<OverlayType>::include(id, properties))
233 properties.reversed = decide<OverlayType>::reversed(id, properties);
234 selection_map[id] = properties;
242 \brief The function select_rings select rings based on the overlay-type (union,intersection)
246 overlay_type OverlayType,
247 typename Geometry1, typename Geometry2,
248 typename IntersectionMap, typename SelectionMap
250 inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
251 IntersectionMap const& intersection_map,
252 SelectionMap& selection_map, bool midpoint)
254 typedef typename geometry::tag<Geometry1>::type tag1;
255 typedef typename geometry::tag<Geometry2>::type tag2;
257 SelectionMap map_with_all;
258 dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
259 ring_identifier(0, -1, -1), map_with_all, midpoint);
260 dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
261 ring_identifier(1, -1, -1), map_with_all, midpoint);
263 update_selection_map<OverlayType>(geometry1, geometry2, intersection_map,
264 map_with_all, selection_map);
269 overlay_type OverlayType,
271 typename IntersectionMap, typename SelectionMap
273 inline void select_rings(Geometry const& geometry,
274 IntersectionMap const& intersection_map,
275 SelectionMap& selection_map, bool midpoint)
277 typedef typename geometry::tag<Geometry>::type tag;
279 SelectionMap map_with_all;
280 dispatch::select_rings<tag, Geometry>::apply(geometry,
281 ring_identifier(0, -1, -1), map_with_all, midpoint);
283 update_selection_map<OverlayType>(geometry, geometry, intersection_map,
284 map_with_all, selection_map);
288 }} // namespace detail::overlay
289 #endif // DOXYGEN_NO_DETAIL
292 }} // namespace boost::geometry
295 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP