Changed area behaviour (now using reversible view to support ccw poylgons)

Added some buffer alternatives (all not perfect)

[SVN r61701]
This commit is contained in:
Barend Gehrels
2010-04-30 09:11:07 +00:00
parent 8218ce445c
commit 64f3bdb447
5 changed files with 431 additions and 37 deletions

View File

@@ -31,6 +31,9 @@
#include <boost/geometry/strategies/concepts/area_concept.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/util/reversible_view.hpp>
/*!
\defgroup area area: calculate area of a geometry
@@ -84,24 +87,8 @@ struct box_area
};
/*!
\brief Calculate area of a ring, specialized per order
*/
template
<
typename Ring,
order_selector Order,
// closing_selector Closed -- for now assuming CLOSED, p(0) == p(n-1)
typename Strategy
>
template<typename Ring, iterate_direction Direction, typename Strategy>
struct ring_area
{};
template<typename Ring, typename Strategy>
struct ring_area<Ring, clockwise, Strategy>
{
BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) );
@@ -114,7 +101,6 @@ struct ring_area<Ring, clockwise, Strategy>
// Ignore warning (because using static method sometimes) on strategy
boost::ignore_unused_variable_warning(strategy);
// A closed linear_ring has at least four points,
// if not, there is no (zero) area
if (boost::size(ring) < 4)
@@ -122,39 +108,32 @@ struct ring_area<Ring, clockwise, Strategy>
return type();
}
typedef typename boost::range_iterator<Ring const>::type iterator_type;
typedef reversible_view<Ring const, Direction> view_type;
typedef typename boost::range_iterator<view_type const>::type iterator_type;
view_type view(ring);
typename Strategy::state_type state;
iterator_type it = boost::begin(view);
iterator_type it = boost::begin(ring);
for (iterator_type previous = it++;
it != boost::end(ring);
it != boost::end(view);
previous = it++)
{
strategy.apply(*previous, *it, state);
}
return strategy.result(state);
}
};
template<typename Ring, typename Strategy>
struct ring_area<Ring, counterclockwise, Strategy>
{
typedef typename Strategy::return_type type;
static inline type apply(Ring const& ring, Strategy const& strategy)
{
// Counter clockwise rings negate the area result
return -ring_area<Ring, clockwise, Strategy>::apply(ring, strategy);
}
};
}} // namespace detail::area
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
@@ -181,13 +160,17 @@ struct area<box_tag, Geometry, Order, Strategy>
{};
// Area of ring currently returns area of closed rings but it might be argued
// that it is 0.0, because a ring is just a line.
template <typename Geometry, order_selector Order, typename Strategy>
struct area<ring_tag, Geometry, Order, Strategy>
: detail::area::ring_area<Geometry, Order, Strategy>
: detail::area::ring_area
<
Geometry,
order_as_direction<Order>::value,
Strategy
>
{};
template <typename Polygon, order_selector Order, typename Strategy>
struct area<polygon_tag, Polygon, Order, Strategy>
: detail::calculate_polygon_sum
@@ -198,7 +181,7 @@ struct area<polygon_tag, Polygon, Order, Strategy>
detail::area::ring_area
<
typename ring_type<Polygon>::type,
Order,
order_as_direction<Order>::value,
Strategy
>
>
@@ -261,6 +244,8 @@ inline typename Strategy::return_type area(
>::apply(geometry, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP

View File

@@ -0,0 +1,162 @@
// 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_ALGORITHMS_DETAIL_BUFFER_SECTIONALIZING_BUFFER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SECTIONALIZING_BUFFER_HPP
#include <cstddef>
#include <boost/foreach.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/buffer_side.hpp>
#include <boost/geometry/algorithms/detail/buffer/intersecting_inserter.hpp>
#include <boost/geometry/algorithms/detail/buffer/linestring_buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
#include <boost/geometry/algorithms/detail/sections/get_section.hpp>
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
#include <boost/geometry/algorithms/dissolve.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
template
<
typename GeometryOut, typename Geometry,
typename DistanceStrategy,
typename JoinStrategy
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
, typename Mapper
#endif
>
void sectionalizing_buffer(Geometry const& geometry,
std::vector<GeometryOut>& buffered,
DistanceStrategy const& distance_strategy,
JoinStrategy const& join_strategy
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
, Mapper& mapper
#endif
)
{
typedef typename point_type<Geometry>::type point_type;
typedef geometry::box<point_type> box_type;
typedef geometry::sections<box_type, 2> sections_type;
typedef typename geometry::ring_type<GeometryOut>::type ring_type;
// TEMPORARY
typedef intersecting_inserter
<
std::vector<GeometryOut>
> inserter_type;
sections_type sections;
geometry::sectionalize(geometry, sections);
// Buffer all sections separately, and put them in a temporary vector
std::vector<GeometryOut> buffered_sections;
BOOST_FOREACH(typename sections_type::value_type const& section, sections)
{
if (! section.duplicate)
{
typedef typename boost::range_iterator
<
typename geometry::range_type<Geometry>::type const
>::type iterator_type;
inserter_type inserter(buffered_sections);
iterator_type begin, end;
typedef std::pair<iterator_type, iterator_type> section_range;
geometry::get_section(geometry, section, begin, end);
geometry::detail::buffer::linestring_buffer
<
section_range, ring_type, DistanceStrategy, JoinStrategy
>::apply(std::make_pair(begin, end), inserter,
distance_strategy,
join_strategy
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
, mapper
#endif
);
}
}
// IF there are bowl-like shapes, there can still be self-intersections
std::vector<GeometryOut> dissolved;
BOOST_FOREACH(GeometryOut const& p, buffered_sections)
{
geometry::dissolve(p, dissolved);
}
/*BOOST_FOREACH(GeometryOut const& p, buffered_sections)
{
if (geometry::intersects(p))
{
//std::cout << ".";
}
}*/
// TEMP
//buffered.swap(dissolved);
//return;
// END TEMP
BOOST_FOREACH(GeometryOut const& p, dissolved)
{
if (buffered.empty())
{
buffered.push_back(p);
//geometry::union_inserter<GeometryOut>(geometry, p, std::back_inserter(buffered));
}
else if (boost::size(buffered) == 1)
{
std::vector<GeometryOut> unioned;
geometry::union_inserter<GeometryOut>(buffered.front(), p, std::back_inserter(unioned));
buffered.swap(unioned);
}
else
{
std::cerr << " D " << buffered.size();
/*std::vector<GeometryOut> dissolved;
dissolved.push_back(p);
geometry::dissolver(buffered, dissolved);
dissolved.swap(buffered);*/
}
}
// Output
}
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SECTIONALIZING_BUFFER_HPP

View File

@@ -0,0 +1,115 @@
// 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_ALGORITHMS_DETAIL_BUFFER_SPLITTING_BUFFER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SPLITTING_BUFFER_HPP
#include <cstddef>
#include <boost/foreach.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/buffer_side.hpp>
#include <boost/geometry/algorithms/detail/buffer/intersecting_inserter.hpp>
#include <boost/geometry/algorithms/detail/buffer/linestring_buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
#include <boost/geometry/algorithms/detail/overlay/dissolver.hpp>
#include <boost/geometry/algorithms/detail/overlay/split_rings.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
template
<
typename GeometryOut, typename Geometry,
typename DistanceStrategy,
typename JoinStrategy
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
, typename Mapper
#endif
>
inline void splitting_buffer(Geometry const& geometry,
std::vector<GeometryOut>& buffered,
DistanceStrategy const& distance_strategy,
JoinStrategy const& join_strategy
, int option
)
{
typedef typename ring_type<GeometryOut>::type ring_type;
typedef detail::buffer::intersecting_inserter
<
std::vector<GeometryOut>
> inserter_type;
inserter_type inserter(buffered);
detail::buffer::linestring_buffer
<
Geometry, GeometryOut, DistanceStrategy, JoinStrategy
>::apply(geometry, inserter, distance_strategy, join_strategy);
if (option == 0)
{
return;
}
std::vector<ring_type> rings;
BOOST_FOREACH(GeometryOut const& polygon, buffered)
{
//std::cout << bg::wkt(polygon) << " ; POLYGON" << std::endl;
geometry::split_rings(polygon, rings);
}
if (option == 1)
{
buffered.resize(rings.size());
int i = 0;
BOOST_FOREACH(ring_type const& ring, rings)
{
exterior_ring(buffered[i++]) = ring;
}
return;
}
std::vector<GeometryOut> buffered_and_unioned;
geometry::dissolver(rings, buffered_and_unioned);
std::vector<GeometryOut> buffered_and_assembled;
detail::overlay::assemble<GeometryOut>(buffered_and_unioned,
std::map<ring_identifier, int>(),
buffered_and_unioned[0], buffered_and_unioned[0], 1, true, true,
std::back_inserter(buffered_and_assembled));
buffered = buffered_and_assembled;
}
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SPLITTING_BUFFER_HPP

View File

@@ -0,0 +1,90 @@
// 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_ALGORITHMS_DETAIL_BUFFER_TRAVERSING_BUFFER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TRAVERSING_BUFFER_HPP
#include <cstddef>
#include <boost/foreach.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/buffer_side.hpp>
#include <boost/geometry/algorithms/detail/buffer/intersecting_inserter.hpp>
#include <boost/geometry/algorithms/detail/buffer/linestring_buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
#include <boost/geometry/algorithms/detail/sections/get_section.hpp>
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
#include <boost/geometry/algorithms/dissolve.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
template
<
typename GeometryOut, typename Geometry,
typename DistanceStrategy,
typename JoinStrategy
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
, typename Mapper
#endif
>
inline void traversing_buffer(Geometry const& geometry,
std::vector<GeometryOut>& buffered,
DistanceStrategy const& distance_strategy,
JoinStrategy const& join_strategy
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
, Mapper& mapper
#endif
)
{
typedef typename ring_type<GeometryOut>::type ring_type;
typedef detail::buffer::intersecting_inserter
<
std::vector<GeometryOut>
> inserter_type;
inserter_type inserter(buffered);
detail::buffer::linestring_buffer
<
Geometry, GeometryOut, DistanceStrategy, JoinStrategy
>::apply(geometry, inserter, distance_strategy, join_strategy);
std::vector<GeometryOut> buffered_and_assembled;
detail::overlay::assemble<GeometryOut>(buffered,
std::map<ring_identifier, int>(),
buffered[0], buffered[0], 1, true, true,
std::back_inserter(buffered_and_assembled));
buffered = buffered_and_assembled;
}
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TRAVERSING_BUFFER_HPP

View File

@@ -0,0 +1,42 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
// Copyright Bruno Lalande 2008, 2009
// 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_UTIL_ORDER_AS_DIRECTION_HPP
#define BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/util/reversible_view.hpp>
namespace boost { namespace geometry
{
template<order_selector Order>
struct order_as_direction
{};
template<>
struct order_as_direction<clockwise>
{
static const iterate_direction value = iterate_forward;
};
template<>
struct order_as_direction<counterclockwise>
{
static const iterate_direction value = iterate_reverse;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP