blob: 5ff0b57d6ef860518dfda872aae757ef4450c659 [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, 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 <boost/geometry/core/closure.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
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<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
typedef typename geometry::tag<GeometryOut>::type tag_out;
if (id.source_index == 0)
{
convert_ring<tag_out>::apply(result,
get_ring<tag1>::apply(id, geometry1),
append, reversed);
}
else if (id.source_index == 1)
{
convert_ring<tag_out>::apply(result,
get_ring<tag2>::apply(id, geometry2),
append, reversed);
}
else if (id.source_index == 2)
{
convert_ring<tag_out>::apply(result,
get_ring<void>::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;
typedef typename SelectionMap::mapped_type property_type;
typedef typename property_type::area_type area_type;
area_type const zero = 0;
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
<
geometry::closure
<
typename boost::range_value
<
RingCollection const
>::type
>::value
>::value;
for (iterator it = boost::begin(map);
it != boost::end(map);
++it)
{
if (! it->second.discarded
&& 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<ring_identifier>::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()
&& ! mit->second.discarded)
{
convert_and_add(result, geometry1, geometry2, collection,
*child_it, mit->second.reversed, true);
}
}
// Only add rings if they satisfy minimal requirements.
// This cannot be done earlier (during traversal), not
// everything is figured out yet (sum of positive/negative rings)
if (geometry::num_points(result) >= min_num_points
&& math::larger(geometry::area(result), zero))
{
*out++ = result;
}
}
}
return out;
}
template
<
typename GeometryOut,
typename SelectionMap,
typename Geometry,
typename RingCollection,
typename OutputIterator
>
inline OutputIterator add_rings(SelectionMap const& map,
Geometry const& geometry,
RingCollection const& collection,
OutputIterator out)
{
Geometry empty;
return add_rings<GeometryOut>(map, geometry, empty, collection, out);
}
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP