mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-10 11:32:15 +00:00
Boost.Geometry Substantial progress on buffer
[SVN r77061]
This commit is contained in:
@@ -29,29 +29,15 @@ namespace detail { namespace buffer
|
||||
// Appends points to an output range (always a ring).
|
||||
// On the way, special points can be marked, and marked points
|
||||
// forming a hooklet, loop, curve, curl, or how you call it are checked on intersections.
|
||||
template
|
||||
<
|
||||
typename Range
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
>
|
||||
template<typename Range>
|
||||
class buffer_appender
|
||||
{
|
||||
public :
|
||||
typedef Range range_type;
|
||||
typedef typename geometry::point_type<Range>::type point_type;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
Mapper const& m_mapper;
|
||||
inline buffer_appender(Range& r, Mapper const& mapper)
|
||||
: m_range(r)
|
||||
, m_mapper(mapper)
|
||||
#else
|
||||
inline buffer_appender(Range& r)
|
||||
: m_range(r)
|
||||
#endif
|
||||
|
||||
{}
|
||||
|
||||
inline void append(point_type const& point)
|
||||
@@ -83,9 +69,6 @@ public :
|
||||
inline void append_begin_hooklet(point_type const& point)
|
||||
{
|
||||
DEBUG("begin hooklet");
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
const_cast<Mapper&>(m_mapper).map(point, "fill:rgb(0,0,192);", 3);
|
||||
#endif
|
||||
|
||||
check(point);
|
||||
|
||||
@@ -99,9 +82,6 @@ public :
|
||||
inline void append_end_hooklet(point_type const& point)
|
||||
{
|
||||
DEBUG("end hooklet");
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
const_cast<Mapper&>(m_mapper).map(point, "fill:rgb(0,0,255);", 4);
|
||||
#endif
|
||||
|
||||
do_append(point);
|
||||
}
|
||||
@@ -177,12 +157,6 @@ private :
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
if (! m_pieces.empty() && m_pieces.back().end > m_pieces.back().begin)
|
||||
{
|
||||
const_cast<Mapper&>(m_mapper).map(point, "fill:rgb(0,255,0);", 4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool calculate_ip(point_type const& point, piece const& the_piece)
|
||||
@@ -193,14 +167,6 @@ private :
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
const_cast<Mapper&>(m_mapper).map(point, "fill:rgb(255,0,0);", 4);
|
||||
for (int i = the_piece.begin; i <= the_piece.end && i < n; i++)
|
||||
{
|
||||
//const_cast<Mapper&>(m_mapper).map(m_range[i], "fill:rgb(0,255,255);", 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
segment_type segment1(m_previous_point, point);
|
||||
|
||||
// Walk backwards through list (chance is higher to have IP at the end)
|
||||
@@ -215,11 +181,6 @@ private :
|
||||
if (get_valid_split(is.intersections[0], i + 1, split_off))
|
||||
{
|
||||
add_ip(is.intersections[0], i + 1, the_piece, split_off);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
const_cast<Mapper&>(m_mapper).map(is.intersections[0], "fill:rgb(255,0,255);", 4);
|
||||
const_cast<Mapper&>(m_mapper).map(split_off, "fill:none;stroke:rgb(255,0,0);stroke-width:2");
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -253,11 +214,6 @@ private :
|
||||
|
||||
add_ip(is.intersections[0], the_piece.begin + 1, the_piece, split_off);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
const_cast<Mapper&>(m_mapper).map(is.intersections[0], "fill:rgb(255,255,0);", 4);
|
||||
const_cast<Mapper&>(m_mapper).map(m_range[the_piece.begin], "fill:rgb(255,192,0);", 4);
|
||||
const_cast<Mapper&>(m_mapper).map(split_off, "fill:none;stroke:rgb(255,192,0);stroke-width:2");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
// 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_BUFFER_BUFFER_INSERTER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/typeof/typeof.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffered_piece_collection.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/line_line_intersection.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RingOutput,
|
||||
typename Tag
|
||||
>
|
||||
struct buffer_range
|
||||
{
|
||||
typedef typename point_type<RingOutput>::type output_point_type;
|
||||
typedef typename coordinate_type<RingOutput>::type coordinate_type;
|
||||
typedef model::referring_segment<output_point_type const> segment_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Collection,
|
||||
typename Iterator,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
>
|
||||
static inline void iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy
|
||||
)
|
||||
{
|
||||
output_point_type previous_p1, previous_p2;
|
||||
output_point_type first_p1, first_p2;
|
||||
|
||||
bool first = true;
|
||||
|
||||
Iterator it = begin;
|
||||
for (Iterator prev = it++; it != end; ++it)
|
||||
{
|
||||
if (! detail::equals::equals_point_point(*prev, *it))
|
||||
{
|
||||
// Generate a block along (left or right of) the segment
|
||||
|
||||
// Simulate a vector d (dx,dy)
|
||||
coordinate_type dx = get<0>(*it) - get<0>(*prev);
|
||||
coordinate_type dy = get<1>(*it) - get<1>(*prev);
|
||||
|
||||
// For normalization [0,1] (=dot product d.d, sqrt)
|
||||
coordinate_type length = sqrt(dx * dx + dy * dy);
|
||||
|
||||
// Because coordinates are not equal, length should not be zero
|
||||
BOOST_ASSERT((! geometry::math::equals(length, 0)));
|
||||
|
||||
// Generate the normalized perpendicular p, to the left (ccw)
|
||||
coordinate_type px = -dy / length;
|
||||
coordinate_type py = dx / length;
|
||||
|
||||
output_point_type p1, p2;
|
||||
|
||||
coordinate_type d = distance.apply(*prev, *it, side);
|
||||
|
||||
set<0>(p2, get<0>(*it) + px * d);
|
||||
set<1>(p2, get<1>(*it) + py * d);
|
||||
|
||||
set<0>(p1, get<0>(*prev) + px * d);
|
||||
set<1>(p1, get<1>(*prev) + py * d);
|
||||
|
||||
std::vector<output_point_type> range_out;
|
||||
if (! first)
|
||||
{
|
||||
output_point_type p;
|
||||
segment_type s1(p1, p2);
|
||||
segment_type s2(previous_p1, previous_p2);
|
||||
|
||||
if (line_line_intersection<output_point_type, segment_type>::apply(s1, s2, p))
|
||||
{
|
||||
join_strategy.apply(p, *prev, previous_p2, p1,
|
||||
distance.apply(*prev, *it, side),
|
||||
range_out);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
first = false;
|
||||
first_p1 = p1;
|
||||
first_p2 = p2;
|
||||
}
|
||||
if (! range_out.empty())
|
||||
{
|
||||
collection.add_piece(*prev, range_out);
|
||||
range_out.clear();
|
||||
}
|
||||
collection.add_piece(*prev, *it, p1, p2);
|
||||
|
||||
previous_p1 = p1;
|
||||
previous_p2 = p2;
|
||||
prev = it;
|
||||
}
|
||||
}
|
||||
|
||||
// Might be replaced by specialization
|
||||
if(boost::is_same<Tag, ring_tag>::value)
|
||||
{
|
||||
// Generate closing corner
|
||||
output_point_type p;
|
||||
segment_type s1(previous_p1, previous_p2);
|
||||
segment_type s2(first_p1, first_p2);
|
||||
line_line_intersection<output_point_type, segment_type>::apply(s1, s2, p);
|
||||
|
||||
std::vector<output_point_type> range_out;
|
||||
join_strategy.apply(p, *begin, previous_p2, first_p1,
|
||||
distance.apply(*(end - 1), *begin, side),
|
||||
range_out);
|
||||
if (! range_out.empty())
|
||||
{
|
||||
collection.add_piece(*begin, range_out);
|
||||
}
|
||||
|
||||
// Buffer is closed automatically by last closing corner (NOT FOR OPEN POLYGONS - TODO)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Tag,
|
||||
typename RingInput,
|
||||
typename RingOutput
|
||||
>
|
||||
struct buffer_inserter
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RingInput,
|
||||
typename RingOutput
|
||||
>
|
||||
struct buffer_inserter<ring_tag, RingInput, RingOutput>
|
||||
: public detail::buffer::buffer_range
|
||||
<
|
||||
RingOutput,
|
||||
ring_tag
|
||||
>
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Collection, typename DistanceStrategy, typename JoinStrategy
|
||||
>
|
||||
static inline void apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy)
|
||||
{
|
||||
iterate(collection, boost::begin(ring), boost::end(ring),
|
||||
buffer_side_left,
|
||||
distance, join_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Linestring,
|
||||
typename Polygon
|
||||
>
|
||||
struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
: public detail::buffer::buffer_range
|
||||
<
|
||||
typename ring_type<Polygon>::type,
|
||||
linestring_tag
|
||||
>
|
||||
{
|
||||
|
||||
template<typename Collection, typename DistanceStrategy, typename JoinStrategy>
|
||||
static inline void apply(Linestring const& linestring, Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy)
|
||||
{
|
||||
collection.add_input();
|
||||
iterate(collection, boost::begin(linestring), boost::end(linestring),
|
||||
buffer_side_left,
|
||||
distance, join_strategy);
|
||||
|
||||
iterate(collection, boost::rbegin(linestring), boost::rend(linestring),
|
||||
buffer_side_right,
|
||||
distance, join_strategy);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename PolygonInput,
|
||||
typename PolygonOutput
|
||||
>
|
||||
struct buffer_inserter<polygon_tag, PolygonInput, PolygonOutput>
|
||||
{
|
||||
|
||||
template <typename Collection, typename DistanceStrategy, typename JoinStrategy>
|
||||
static inline void apply(PolygonInput const& polygon, Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy)
|
||||
{
|
||||
|
||||
typedef typename ring_type<PolygonInput>::type input_ring_type;
|
||||
typedef typename ring_type<PolygonOutput>::type output_ring_type;
|
||||
|
||||
typedef buffer_inserter<ring_tag, input_ring_type, output_ring_type> policy;
|
||||
|
||||
{
|
||||
collection.add_input();
|
||||
|
||||
policy::apply(exterior_ring(polygon), collection,
|
||||
distance, join_strategy);
|
||||
}
|
||||
|
||||
typename interior_return_type<PolygonInput const>::type rings
|
||||
= interior_rings(polygon);
|
||||
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
|
||||
{
|
||||
output_ring_type ring;
|
||||
|
||||
collection.add_input();
|
||||
|
||||
policy::apply(*it, collection, distance, join_strategy);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryOutput,
|
||||
typename GeometryInput,
|
||||
typename OutputIterator,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
>
|
||||
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
|
||||
DistanceStrategy const& distance_strategy, JoinStrategy const& join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
)
|
||||
{
|
||||
detail::buffer::buffered_piece_collection<typename geometry::ring_type<GeometryOutput>::type> collection;
|
||||
|
||||
dispatch::buffer_inserter
|
||||
<
|
||||
typename tag<GeometryInput>::type,
|
||||
GeometryInput,
|
||||
GeometryOutput
|
||||
>::apply(geometry_input, collection, distance_strategy, join_strategy);
|
||||
|
||||
collection.get_turns(geometry_input);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
collection.map_offsetted(mapper);
|
||||
#endif
|
||||
|
||||
collection.discard_points();
|
||||
collection.enrich();
|
||||
collection.traverse();
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
//collection.map<geometry::polygon_tag>(mapper);
|
||||
collection.map_turns(mapper);
|
||||
collection.map_traverse(mapper);
|
||||
#endif
|
||||
|
||||
collection.assign<GeometryOutput>(out);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP
|
||||
@@ -0,0 +1,657 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 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_BUFFER_BUFFERED_PIECE_COLLECTION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffered_ring.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
class backtrack_for_buffer
|
||||
{
|
||||
public :
|
||||
typedef detail::overlay::backtrack_state state_type;
|
||||
|
||||
template <typename Operation, typename Rings, typename Turns, typename Geometry>
|
||||
static inline void apply(std::size_t size_at_start,
|
||||
Rings& rings, typename boost::range_value<Rings>::type& ring,
|
||||
Turns& turns, Operation& operation,
|
||||
std::string const& reason,
|
||||
Geometry const& ,
|
||||
Geometry const& ,
|
||||
state_type& state
|
||||
)
|
||||
{
|
||||
std::cout << "WARNING " << reason << std::endl;
|
||||
|
||||
// TODO this is a copy of dissolve, check this for buffer
|
||||
state.m_good = false;
|
||||
|
||||
// Make bad output clean
|
||||
rings.resize(size_at_start);
|
||||
ring.clear();
|
||||
|
||||
// Reject this as a starting point
|
||||
operation.visited.set_rejected();
|
||||
|
||||
// And clear all visit info
|
||||
clear_visit_info(turns);
|
||||
}
|
||||
};
|
||||
|
||||
enum intersection_location_type
|
||||
{
|
||||
location_ok, inside_buffer, inside_original
|
||||
};
|
||||
|
||||
|
||||
// Shoould follow traversal-turn-concept (enrichment, visit structure)
|
||||
// and adds index in piece vector to find it back
|
||||
template <typename Point>
|
||||
struct buffer_turn_operation : public detail::overlay::traversal_turn_operation<Point>
|
||||
{
|
||||
int piece_index;
|
||||
|
||||
inline buffer_turn_operation()
|
||||
: piece_index(-1)
|
||||
{}
|
||||
};
|
||||
|
||||
// Add an "intersection_location_type" which gets true for all intersection points lying inside the buffer or original polygon
|
||||
template <typename Point>
|
||||
struct buffer_turn_info : public detail::overlay::turn_info<Point, buffer_turn_operation<Point> >
|
||||
{
|
||||
intersection_location_type location;
|
||||
|
||||
inline buffer_turn_info()
|
||||
: location(location_ok)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct buffered_piece_collection
|
||||
{
|
||||
typedef typename geometry::point_type<Ring>::type Point;
|
||||
typedef typename strategy::side::services::default_strategy<typename cs_tag<Point>::type>::type side;
|
||||
|
||||
enum piece_type
|
||||
{
|
||||
buffered_segment, buffered_join
|
||||
};
|
||||
|
||||
template <typename Turn>
|
||||
struct redundant_turn
|
||||
{
|
||||
inline bool operator()(Turn const& turn) const
|
||||
{
|
||||
return turn.location != location_ok;
|
||||
}
|
||||
};
|
||||
|
||||
struct piece
|
||||
{
|
||||
piece_type type;
|
||||
int index;
|
||||
segment_identifier seg_id;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// type=buffered_segment:
|
||||
|
||||
// This buffered_segment (2 points of the original)
|
||||
Point p1, p2;
|
||||
|
||||
// The buffered buffered_segment (offsetted with certain distance to left/right)
|
||||
Point b1, b2;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// type=buffered_join
|
||||
Point p;
|
||||
|
||||
// Corner next to this buffered_segment (so connected to p2 and b2).
|
||||
// In case p2 is a concave point, corner is empty
|
||||
Ring corner; // TODO redundant
|
||||
|
||||
// Filled for both:
|
||||
typedef geometry::model::linestring<Point> buffered_vector_type;
|
||||
|
||||
buffered_vector_type offseted_segment;
|
||||
};
|
||||
|
||||
typedef std::vector<piece> piece_vector;
|
||||
piece_vector all_pieces;
|
||||
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings;
|
||||
buffered_ring_collection<Ring> traversed_rings;
|
||||
segment_identifier current_segment_id;
|
||||
|
||||
typedef std::vector<buffer_turn_info<Point> > turn_vector_type;
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
Point, Point, buffer_turn_info<Point>,
|
||||
detail::overlay::calculate_distance_policy
|
||||
> turn_policy;
|
||||
turn_vector_type turn_vector;
|
||||
|
||||
|
||||
|
||||
inline buffered_piece_collection()
|
||||
{}
|
||||
|
||||
|
||||
inline bool within_piece(buffer_turn_info<Point> const& turn, piece const& pc) const
|
||||
{
|
||||
bool const collinear =
|
||||
turn.operations[0].operation == detail::overlay::operation_continue
|
||||
&& turn.operations[0].operation == detail::overlay::operation_continue;
|
||||
|
||||
// For now: use within, using built-up corner (which will be redundant later)
|
||||
|
||||
// Because pieces are always concave we only have to verify if it is left of all segments.
|
||||
// As soon as it is right of one, we can quit. This is faster than the normal within,
|
||||
// and we don't have to build up the polygon.
|
||||
if (collinear)
|
||||
{
|
||||
// ONLY for the outer-boundary: return within
|
||||
return geometry::within(turn.point, pc.corner);
|
||||
}
|
||||
|
||||
return geometry::covered_by(turn.point, pc.corner);
|
||||
}
|
||||
|
||||
// Checks if an intersection point is within one of all pieces
|
||||
// (but skip the pieces of which this intersection point is the result
|
||||
inline bool is_wrong(buffer_turn_info<Point> const& turn, piece const& piece1, piece const& piece2) const
|
||||
{
|
||||
// We might do this using partition.
|
||||
typename std::vector<piece>::const_iterator it;
|
||||
for (it = boost::begin(all_pieces);
|
||||
it != boost::end(all_pieces);
|
||||
++it)
|
||||
{
|
||||
if (it->index != piece1.index && it->index != piece2.index)
|
||||
{
|
||||
if (within_piece(turn, *it))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
inline bool is_neighbor(piece const& piece1, piece const& piece2) const
|
||||
{
|
||||
if (std::abs(piece1.index - piece2.index) == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int const b = boost::size(all_pieces) - 1; // back
|
||||
return (piece1.index == 0 && piece2.index == b)
|
||||
|| (piece1.index == b && piece2.index == 0)
|
||||
;
|
||||
}
|
||||
|
||||
inline bool skip_neighbor(piece const& piece1, piece const& piece2) const
|
||||
{
|
||||
return piece1.type != piece2.type && is_neighbor(piece1, piece2);
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
inline Point next_point(piece const& piece, Iterator it) const
|
||||
{
|
||||
// Next point in current offseted:
|
||||
Iterator next = it;
|
||||
++next;
|
||||
if (next != boost::end(piece.offseted_segment))
|
||||
{
|
||||
return *next;
|
||||
}
|
||||
|
||||
// TODO: check if there is a second point (there should be one)
|
||||
// Second point from next piece:
|
||||
int next_index = piece.index + 1;
|
||||
if (next_index >= boost::size(all_pieces))
|
||||
{
|
||||
next_index = 0;
|
||||
}
|
||||
return piece.offseted_segment[1];
|
||||
}
|
||||
|
||||
inline void calculate_turns(piece const& piece1, piece const& piece2)
|
||||
{
|
||||
buffer_turn_info<Point> the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
the_model.operations[0].seg_id = piece1.seg_id;
|
||||
|
||||
// TODO use partition
|
||||
typedef typename boost::range_iterator<typename piece::buffered_vector_type const>::type iterator;
|
||||
iterator it1 = boost::begin(piece1.offseted_segment);
|
||||
for (iterator prev1 = it1++;
|
||||
it1 != boost::end(piece1.offseted_segment);
|
||||
prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
|
||||
{
|
||||
the_model.operations[1].piece_index = piece2.index;
|
||||
the_model.operations[1].seg_id = piece2.seg_id;
|
||||
|
||||
iterator it2 = boost::begin(piece2.offseted_segment);
|
||||
for (iterator prev2 = it2++;
|
||||
it2 != boost::end(piece2.offseted_segment);
|
||||
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
|
||||
{
|
||||
// Revert (this is used more often - should be common function TODO)
|
||||
the_model.operations[0].other_id = the_model.operations[1].seg_id;
|
||||
the_model.operations[1].other_id = the_model.operations[0].seg_id;
|
||||
|
||||
|
||||
turn_vector_type turns; // TEMPORARY in the end we can add directly to turn_vector
|
||||
turn_policy::apply(*prev1, *it1, next_point(piece1, it1),
|
||||
*prev2, *it2, next_point(piece2, it2),
|
||||
the_model, std::back_inserter(turns));
|
||||
|
||||
// Add buffered_segment identifier info
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(turns); it != boost::end(turns); ++it)
|
||||
{
|
||||
// TODO: much later in partition.
|
||||
if (is_wrong(*it, piece1, piece2))
|
||||
{
|
||||
it->location = inside_buffer;
|
||||
}
|
||||
turn_vector.push_back(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
inline void check_remaining_points(Geometry const& input_geometry)
|
||||
{
|
||||
// TODO: this should be done as a collection-of-points, for performance
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(turn_vector); it != boost::end(turn_vector); ++it)
|
||||
{
|
||||
if (it->location == location_ok)
|
||||
{
|
||||
if (geometry::covered_by(it->point, input_geometry))
|
||||
{
|
||||
it->location = inside_original;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
inline void get_turns(Geometry const& input_geometry)
|
||||
{
|
||||
for(typename piece_vector::const_iterator it1 = boost::begin(all_pieces);
|
||||
it1 != boost::end(all_pieces);
|
||||
++it1)
|
||||
{
|
||||
for(typename piece_vector::const_iterator it2 = it1 + 1;
|
||||
it2 != boost::end(all_pieces);
|
||||
++it2)
|
||||
{
|
||||
if (! skip_neighbor(*it1, *it2))
|
||||
{
|
||||
calculate_turns(*it1, *it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (boost::is_same<typename tag_cast<typename tag<Geometry>::type, areal_tag>::type, areal_tag>())
|
||||
{
|
||||
check_remaining_points(input_geometry);
|
||||
}
|
||||
|
||||
calculate_discarded();
|
||||
}
|
||||
|
||||
inline void add_input()
|
||||
{
|
||||
int const n = offsetted_rings.size();
|
||||
current_segment_id.source_index = 0;
|
||||
current_segment_id.multi_index = n;
|
||||
current_segment_id.ring_index = -1;
|
||||
current_segment_id.segment_index = 0;
|
||||
|
||||
offsetted_rings.resize(n + 1);
|
||||
}
|
||||
|
||||
inline void add_point(Point const& p)
|
||||
{
|
||||
BOOST_ASSERT
|
||||
(
|
||||
boost::size(offsetted_rings) > 0
|
||||
);
|
||||
|
||||
current_segment_id.segment_index++;
|
||||
offsetted_rings.back().push_back(p);
|
||||
}
|
||||
|
||||
|
||||
inline piece& add_piece(piece_type type, bool decrease_by_one)
|
||||
{
|
||||
piece pc;
|
||||
pc.type = type;
|
||||
pc.index = boost::size(all_pieces);
|
||||
pc.seg_id = current_segment_id;
|
||||
|
||||
std::size_t const n = boost::size(offsetted_rings.back());
|
||||
|
||||
pc.seg_id.segment_index = decrease_by_one ? n - 1 : n;
|
||||
|
||||
all_pieces.push_back(pc);
|
||||
return all_pieces.back();
|
||||
}
|
||||
|
||||
|
||||
inline void add_piece(Point const& p1, Point const& p2,
|
||||
Point const& b1, Point const& b2)
|
||||
{
|
||||
bool const last_type_join = ! all_pieces.empty()
|
||||
&& all_pieces.back().type != buffered_segment;
|
||||
|
||||
piece& pc = add_piece(buffered_segment, last_type_join);
|
||||
|
||||
pc.p1 = p1;
|
||||
pc.p2 = p2;
|
||||
pc.b1 = b1;
|
||||
pc.b2 = b2;
|
||||
|
||||
// If it follows the same piece-type point both should be added.
|
||||
// There should be two intersections later and it should be discarded.
|
||||
// But for need it to calculate intersections
|
||||
if (! last_type_join)
|
||||
{
|
||||
add_point(b1);
|
||||
}
|
||||
add_point(b2);
|
||||
|
||||
// TEMPORARY
|
||||
pc.corner.push_back(p1);
|
||||
pc.corner.push_back(b1);
|
||||
pc.corner.push_back(b2);
|
||||
pc.corner.push_back(p2);
|
||||
pc.corner.push_back(p1);
|
||||
// END TEMPORARY
|
||||
|
||||
pc.offseted_segment.push_back(b1);
|
||||
pc.offseted_segment.push_back(b2);
|
||||
}
|
||||
|
||||
template <typename Corner>
|
||||
inline void add_piece(Point const& p, Corner const& corner)
|
||||
{
|
||||
piece& pc = add_piece(buffered_join, true);
|
||||
|
||||
pc.p = p;
|
||||
|
||||
pc.corner.push_back(p);// TEMPORARY
|
||||
bool first = true;
|
||||
for (typename Corner::const_iterator it = boost::begin(corner);
|
||||
it != boost::end(corner);
|
||||
++it)
|
||||
{
|
||||
bool add = true;
|
||||
if (first)
|
||||
{
|
||||
// Only for very first one, add first. In all other cases it is shared with previous.
|
||||
add = offsetted_rings.back().empty();
|
||||
first = false;
|
||||
}
|
||||
if (add)
|
||||
{
|
||||
add_point(*it);
|
||||
}
|
||||
pc.corner.push_back(*it); // TEMPORARY
|
||||
pc.offseted_segment.push_back(*it); // REDUNDANT
|
||||
}
|
||||
pc.corner.push_back(p);// TEMPORARY
|
||||
}
|
||||
|
||||
inline void enrich()
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Ring>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
enrich_intersection_points<false, false>(turn_vector,
|
||||
detail::overlay::operation_union,
|
||||
offsetted_rings, offsetted_rings,
|
||||
side_strategy_type());
|
||||
}
|
||||
|
||||
// Discards all rings which do have not-OK intersection points only.
|
||||
// Those can never be traversed and should not be part of the output.
|
||||
inline void calculate_discarded()
|
||||
{
|
||||
for (typename boost::range_iterator<turn_vector_type const>::type it =
|
||||
boost::begin(turn_vector); it != boost::end(turn_vector); ++it)
|
||||
{
|
||||
if (it->location != location_ok)
|
||||
{
|
||||
offsetted_rings[it->operations[0].seg_id.multi_index].has_discarded_intersections = true;
|
||||
offsetted_rings[it->operations[1].seg_id.multi_index].has_discarded_intersections = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetted_rings[it->operations[0].seg_id.multi_index].has_accepted_intersections = true;
|
||||
offsetted_rings[it->operations[1].seg_id.multi_index].has_accepted_intersections = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void discard_points()
|
||||
{
|
||||
// Erase all points being inside
|
||||
turn_vector.erase(
|
||||
std::remove_if(boost::begin(turn_vector), boost::end(turn_vector), redundant_turn<buffer_turn_info<Point> >()),
|
||||
boost::end(turn_vector));
|
||||
|
||||
}
|
||||
|
||||
inline void traverse()
|
||||
{
|
||||
typedef detail::overlay::traverse
|
||||
<
|
||||
false, false,
|
||||
buffered_ring_collection<buffered_ring<Ring > >, buffered_ring_collection<buffered_ring<Ring > >,
|
||||
backtrack_for_buffer
|
||||
> traverser;
|
||||
|
||||
traversed_rings.clear();
|
||||
traverser::apply(offsetted_rings, offsetted_rings,
|
||||
detail::overlay::operation_union,
|
||||
turn_vector, traversed_rings);
|
||||
}
|
||||
|
||||
template <typename GeometryOutput, typename OutputIterator>
|
||||
inline OutputIterator assign(OutputIterator out)
|
||||
{
|
||||
typedef detail::overlay::ring_properties<Point> properties;
|
||||
|
||||
std::map<ring_identifier, properties> selected;
|
||||
|
||||
// Select all rings which do not have any self-intersection (other ones should be traversed)
|
||||
int index = 0;
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
|
||||
it != boost::end(offsetted_rings);
|
||||
++it, ++index)
|
||||
{
|
||||
if (! it->has_intersections())
|
||||
{
|
||||
ring_identifier id(0, index, -1);
|
||||
selected[id] = properties(*it, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Select all created rings
|
||||
index = 0;
|
||||
for (typename boost::range_iterator<buffered_ring_collection<Ring> const>::type
|
||||
it = boost::begin(traversed_rings);
|
||||
it != boost::end(traversed_rings);
|
||||
++it, ++index)
|
||||
{
|
||||
ring_identifier id(2, index, -1);
|
||||
selected[id] = properties(*it, true);
|
||||
}
|
||||
|
||||
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_turns(Mapper& mapper)
|
||||
{
|
||||
int index = 0;
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(turn_vector); it != boost::end(turn_vector); ++it)
|
||||
{
|
||||
std::string fill = "fill:rgb(0,255,0);";
|
||||
switch(it->location)
|
||||
{
|
||||
case inside_buffer : fill = "fill:rgb(255,0,0);"; break;
|
||||
case inside_original : fill = "fill:rgb(0,0,255);"; break;
|
||||
}
|
||||
mapper.map(it->point, fill, 6);
|
||||
std::ostringstream out;
|
||||
//out << it->operations[0].piece_index << "/" << it->operations[1].piece_index;
|
||||
out << " " << all_pieces[it->operations[0].piece_index].seg_id.segment_index
|
||||
<< "+" << all_pieces[it->operations[1].piece_index].seg_id.segment_index;
|
||||
//out << " " << all_pieces[it->operations[0].piece_index].index_in_all_points
|
||||
// << "," << all_pieces[it->operations[1].piece_index].index_in_all_points;
|
||||
//out << " " << it->operations[0].seg_id.segment_index
|
||||
// << "|" << it->operations[1].seg_id.segment_index;
|
||||
out << ":" << operation_char(it->operations[0].operation);
|
||||
mapper.text(it->point, out.str(), "fill:rgb(0,0,0);font-family='Arial';", 5, 5);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tag, typename Mapper>
|
||||
inline void map(Mapper& mapper)
|
||||
{
|
||||
for(typename piece_vector::const_iterator it = boost::begin(all_pieces);
|
||||
it != boost::end(all_pieces);
|
||||
++it)
|
||||
{
|
||||
if (it->type == buffered_segment)
|
||||
{
|
||||
geometry::model::ring<Point> ring;
|
||||
ring.push_back(it->p1);
|
||||
ring.push_back(it->b1);
|
||||
ring.push_back(it->b2);
|
||||
ring.push_back(it->p2);
|
||||
ring.push_back(it->p1);
|
||||
|
||||
if(boost::is_same<Tag, ring_tag>::value || boost::is_same<Tag, polygon_tag>::value)
|
||||
{
|
||||
mapper.map(ring, "opacity:0.3;fill:rgb(255,128,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
else if(boost::is_same<Tag, linestring_tag>::value)
|
||||
{
|
||||
mapper.map(ring, "opacity:0.3;fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.map(it->corner, "opacity:0.3;fill:rgb(255,0,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
|
||||
|
||||
// Put starting segment_index in centroid
|
||||
Point centroid;
|
||||
geometry::centroid(it->corner, centroid);
|
||||
std::ostringstream out;
|
||||
out << it->seg_id.segment_index;
|
||||
mapper.text(centroid, out.str(), "fill:rgb(255,0,0);font-family='Arial';", 5, 5);
|
||||
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (typename boost::range_iterator<std::vector<Point> >::type it =
|
||||
boost::begin(offsetted_rings.front()); it != boost::end(offsetted_rings.front()); ++it)
|
||||
{
|
||||
mapper.map(*it, "fill:rgb(0,0,0);", 2);
|
||||
std::ostringstream out;
|
||||
out << index++;
|
||||
mapper.text(*it, out.str(), "fill:rgb(0,0,255);font-family='Arial';", -5, -5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_traverse(Mapper& mapper)
|
||||
{
|
||||
for(typename buffered_ring_collection<Ring>::const_iterator it = boost::begin(traversed_rings);
|
||||
it != boost::end(traversed_rings);
|
||||
++it)
|
||||
{
|
||||
mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,255,0);stroke-width:8");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_offsetted(Mapper& mapper)
|
||||
{
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
|
||||
it != boost::end(offsetted_rings);
|
||||
++it)
|
||||
{
|
||||
if (it->discarded())
|
||||
{
|
||||
mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(255,0,0);stroke-width:8");
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,0,255);stroke-width:8");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP
|
||||
@@ -0,0 +1,260 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 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_BUFFER_BUFFERED_RING
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
|
||||
#include <boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp>
|
||||
#include <boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp>
|
||||
#include <boost/geometry/multi/algorithms/within.hpp>
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
struct buffered_ring_collection_tag : polygonal_tag, multi_tag
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct buffered_ring : public Ring
|
||||
{
|
||||
bool has_discarded_intersections;
|
||||
bool has_accepted_intersections;
|
||||
inline buffered_ring()
|
||||
: has_accepted_intersections(false)
|
||||
, has_discarded_intersections(false)
|
||||
{}
|
||||
|
||||
inline bool discarded() const
|
||||
{
|
||||
return has_discarded_intersections && ! has_accepted_intersections;
|
||||
}
|
||||
inline bool has_intersections() const
|
||||
{
|
||||
return has_discarded_intersections || has_accepted_intersections;
|
||||
}
|
||||
};
|
||||
|
||||
// This is a collection now special for overlay (needs vector of rings)
|
||||
template <typename Ring>
|
||||
struct buffered_ring_collection : public std::vector<Ring>
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
// Register the types
|
||||
namespace traits
|
||||
{
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct tag<detail::buffer::buffered_ring<Ring> >
|
||||
{
|
||||
typedef ring_tag type;
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct point_order<detail::buffer::buffered_ring<Ring> >
|
||||
{
|
||||
static const order_selector value = geometry::point_order<Ring>::value;
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct closure<detail::buffer::buffered_ring<Ring> >
|
||||
{
|
||||
static const closure_selector value = geometry::closure<Ring>::value;
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct point_type<detail::buffer::buffered_ring_collection<Ring> >
|
||||
{
|
||||
typedef typename geometry::point_type<Ring>::type type;
|
||||
};
|
||||
|
||||
template <typename Ring>
|
||||
struct tag<detail::buffer::buffered_ring_collection<Ring> >
|
||||
{
|
||||
typedef detail::buffer::buffered_ring_collection_tag type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace traits
|
||||
|
||||
namespace core_dispatch
|
||||
{
|
||||
|
||||
template <typename Ring>
|
||||
struct ring_type
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
detail::buffer::buffered_ring_collection<Ring>
|
||||
>
|
||||
{
|
||||
typedef Ring type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiRing,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename PointOut
|
||||
>
|
||||
struct copy_segment_point
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
MultiRing,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
PointOut
|
||||
>
|
||||
: detail::copy_segments::copy_segment_point_multi
|
||||
<
|
||||
MultiRing,
|
||||
SegmentIdentifier,
|
||||
PointOut,
|
||||
detail::copy_segments::copy_segment_point_range
|
||||
<
|
||||
typename boost::range_value<MultiRing>::type,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
PointOut
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiRing,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
struct copy_segments
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
MultiRing,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>
|
||||
: detail::copy_segments::copy_segments_multi
|
||||
<
|
||||
MultiRing,
|
||||
SegmentIdentifier,
|
||||
RangeOut,
|
||||
detail::copy_segments::copy_segments_ring
|
||||
<
|
||||
typename boost::range_value<MultiRing>::type,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
template <typename Point, typename MultiGeometry>
|
||||
struct within
|
||||
<
|
||||
Point,
|
||||
MultiGeometry,
|
||||
point_tag,
|
||||
detail::buffer::buffered_ring_collection_tag
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point,
|
||||
MultiGeometry const& multi, Strategy const& strategy)
|
||||
{
|
||||
return detail::within::geometry_multi_within_code
|
||||
<
|
||||
Point,
|
||||
MultiGeometry,
|
||||
Strategy,
|
||||
detail::within::point_in_ring
|
||||
<
|
||||
Point,
|
||||
typename boost::range_value<MultiGeometry>::type,
|
||||
//iterate_forward,
|
||||
//closed,
|
||||
order_as_direction
|
||||
<
|
||||
geometry::point_order<MultiGeometry>::value
|
||||
>::value,
|
||||
geometry::closure<MultiGeometry>::value,
|
||||
Strategy
|
||||
>
|
||||
>::apply(point, multi, strategy) == 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template<>
|
||||
struct get_ring<detail::buffer::buffered_ring_collection_tag>
|
||||
{
|
||||
template<typename MultiGeometry>
|
||||
static inline typename ring_type<MultiGeometry>::type const& apply(
|
||||
ring_identifier const& id,
|
||||
MultiGeometry const& multi_ring)
|
||||
{
|
||||
BOOST_ASSERT
|
||||
(
|
||||
id.multi_index >= 0
|
||||
&& id.multi_index < boost::size(multi_ring)
|
||||
);
|
||||
return get_ring<ring_tag>::apply(id, multi_ring[id.multi_index]);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
|
||||
@@ -1,100 +0,0 @@
|
||||
// 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_BUFFER_LINESTRING_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINESTRING_BUFFER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffer_appender.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/range_buffer.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Linestring,
|
||||
typename Polygon,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
>
|
||||
struct linestring_buffer
|
||||
: public range_buffer
|
||||
<
|
||||
typename ring_type<Polygon>::type,
|
||||
DistanceStrategy,
|
||||
JoinStrategy,
|
||||
linestring_tag
|
||||
>
|
||||
{
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
template<typename Mapper>
|
||||
#endif
|
||||
static inline void apply(Linestring const& linestring, Polygon& buffered,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
)
|
||||
{
|
||||
buffer_appender
|
||||
<
|
||||
typename geometry::ring_type<Polygon>::type
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper
|
||||
#endif
|
||||
> appender
|
||||
(
|
||||
geometry::exterior_ring(buffered)
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
|
||||
iterate(appender, boost::begin(linestring), boost::end(linestring),
|
||||
buffer_side_left,
|
||||
distance, join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
|
||||
iterate(appender, boost::rbegin(linestring), boost::rend(linestring),
|
||||
buffer_side_right,
|
||||
distance, join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINESTRING_BUFFER_HPP
|
||||
@@ -1,159 +0,0 @@
|
||||
// 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_BUFFER_POLYGON_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_POLYGON_BUFFER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/typeof/typeof.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffer_appender.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/range_buffer.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RingInput,
|
||||
typename RingOutput,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
>
|
||||
struct ring_buffer
|
||||
: public range_buffer
|
||||
<
|
||||
RingOutput,
|
||||
DistanceStrategy,
|
||||
JoinStrategy,
|
||||
ring_tag
|
||||
>
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename BufferAppender
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
>
|
||||
static inline void apply(RingInput const& ring,
|
||||
BufferAppender& appender,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
)
|
||||
{
|
||||
iterate(appender, boost::begin(ring), boost::end(ring),
|
||||
buffer_side_left,
|
||||
distance, join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename PolygonInput,
|
||||
typename PolygonOutput,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
>
|
||||
struct polygon_buffer
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
template <typename Mapper>
|
||||
#endif
|
||||
static inline void apply(PolygonInput const& polygon, PolygonOutput& buffered,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
)
|
||||
{
|
||||
geometry::clear(buffered);
|
||||
|
||||
typedef typename ring_type<PolygonInput>::type input_ring_type;
|
||||
typedef typename ring_type<PolygonOutput>::type output_ring_type;
|
||||
|
||||
typedef buffer_appender
|
||||
<
|
||||
output_ring_type
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper
|
||||
#endif
|
||||
> appender_type;
|
||||
|
||||
typedef ring_buffer<input_ring_type, output_ring_type, DistanceStrategy, JoinStrategy> policy;
|
||||
|
||||
{
|
||||
appender_type appender(geometry::exterior_ring(buffered)
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
policy::apply(exterior_ring(polygon), appender,
|
||||
distance, join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
typename interior_return_type<PolygonInput const>::type rings
|
||||
= interior_rings(polygon);
|
||||
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
|
||||
{
|
||||
output_ring_type ring;
|
||||
|
||||
appender_type appender(ring
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
|
||||
policy::apply(*it, appender, distance, join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
);
|
||||
interior_rings(buffered).push_back(ring);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_POLYGON_BUFFER_HPP
|
||||
@@ -1,199 +0,0 @@
|
||||
// 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_BUFFER_RANGE_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_RANGE_BUFFER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/algorithms/buffer/line_line_intersection.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename RingOutput,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy,
|
||||
typename Tag
|
||||
>
|
||||
struct range_buffer
|
||||
{
|
||||
typedef typename point_type<RingOutput>::type output_point_type;
|
||||
typedef typename coordinate_type<RingOutput>::type coordinate_type;
|
||||
typedef model::referring_segment<output_point_type const> segment_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename BufferAppender,
|
||||
typename Iterator
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
>
|
||||
static inline void iterate(BufferAppender& appender,
|
||||
Iterator begin, Iterator end,
|
||||
buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
)
|
||||
{
|
||||
output_point_type previous_p1, previous_p2;
|
||||
output_point_type first_p1, first_p2;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
int index = 0;
|
||||
#endif
|
||||
|
||||
bool first = true;
|
||||
|
||||
Iterator it = begin;
|
||||
for (Iterator prev = it++; it != end; ++it)
|
||||
{
|
||||
if (! detail::equals::equals_point_point(*prev, *it))
|
||||
{
|
||||
// Generate a block along (left or right of) the segment
|
||||
|
||||
// Simulate a vector d (dx,dy)
|
||||
coordinate_type dx = get<0>(*it) - get<0>(*prev);
|
||||
coordinate_type dy = get<1>(*it) - get<1>(*prev);
|
||||
|
||||
// For normalization [0,1] (=dot product d.d, sqrt)
|
||||
coordinate_type length = sqrt(dx * dx + dy * dy);
|
||||
|
||||
// Because coordinates are not equal, length should not be zero
|
||||
BOOST_ASSERT((! geometry::math::equals(length, 0)));
|
||||
|
||||
// Generate the normalized perpendicular p, to the left (ccw)
|
||||
coordinate_type px = -dy / length;
|
||||
coordinate_type py = dx / length;
|
||||
|
||||
output_point_type p1, p2;
|
||||
|
||||
coordinate_type d = distance.apply(*prev, *it, side);
|
||||
|
||||
set<0>(p2, get<0>(*it) + px * d);
|
||||
set<1>(p2, get<1>(*it) + py * d);
|
||||
|
||||
set<0>(p1, get<0>(*prev) + px * d);
|
||||
set<1>(p1, get<1>(*prev) + py * d);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
{
|
||||
RingOutput block;
|
||||
block.push_back(*prev);
|
||||
block.push_back(*it);
|
||||
block.push_back(p2);
|
||||
block.push_back(p1);
|
||||
block.push_back(*prev);
|
||||
|
||||
if(boost::is_same<Tag, ring_tag>::value)
|
||||
{
|
||||
mapper.map(block, "opacity:0.4;fill:rgb(255,128,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
else if(boost::is_same<Tag, linestring_tag>::value)
|
||||
{
|
||||
mapper.map(block, "opacity:0.4;fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! first)
|
||||
{
|
||||
output_point_type p;
|
||||
segment_type s1(p1, p2);
|
||||
segment_type s2(previous_p1, previous_p2);
|
||||
if (line_line_intersection<output_point_type, segment_type>::apply(s1, s2, p))
|
||||
{
|
||||
join_strategy.apply(p, *prev, previous_p2, p1,
|
||||
distance.apply(*prev, *it, side),
|
||||
appender);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
{
|
||||
//mapper.map(p, "fill:rgb(0,0,0);", 3);
|
||||
|
||||
//std::ostringstream out;
|
||||
//out << index++;
|
||||
//mapper.text(p, out.str(), "fill:rgb(0,0,0);font-family='Arial';", 5, 5);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
first = false;
|
||||
first_p1 = p1;
|
||||
first_p2 = p2;
|
||||
|
||||
appender.append(p1);
|
||||
}
|
||||
|
||||
previous_p1 = p1;
|
||||
previous_p2 = p2;
|
||||
prev = it;
|
||||
}
|
||||
}
|
||||
|
||||
// Might be replaced by specialization
|
||||
if(boost::is_same<Tag, linestring_tag>::value)
|
||||
{
|
||||
appender.append(previous_p2);
|
||||
}
|
||||
else if(boost::is_same<Tag, ring_tag>::value)
|
||||
{
|
||||
// Generate closing corner
|
||||
output_point_type p;
|
||||
segment_type s1(previous_p1, previous_p2);
|
||||
segment_type s2(first_p1, first_p2);
|
||||
line_line_intersection<output_point_type, segment_type>::apply(s1, s2, p);
|
||||
|
||||
join_strategy.apply(p, *begin, previous_p2, first_p1,
|
||||
distance.apply(*(end - 1), *begin, side),
|
||||
appender);
|
||||
|
||||
// Buffer is closed automatically by last closing corner (NOT FOR OPEN POLYGONS - TODO)
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
{
|
||||
//mapper.map(p, "fill:rgb(0,0,0);", 3);
|
||||
//std::ostringstream out;
|
||||
//out << index++;
|
||||
//mapper.text(p, out.str(), "fill:rgb(0,0,0);font-family='Arial';", 5, 5);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_RANGE_BUFFER_HPP
|
||||
@@ -1,167 +0,0 @@
|
||||
// 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_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/extensions/strategies/buffer_side.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/detail/buffer/intersecting_inserter.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/detail/buffer/linestring_buffer.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/detail/buffer/line_line_intersection.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/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::detail::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;
|
||||
|
||||
TODO: UPDATE: get _ section IS OBSOLETE NOW AND DISCARDED.
|
||||
TAKE range_by_section AND ADD section.begin_index/section.end_index
|
||||
|
||||
geometry::get _ section(geometry, section, begin, end); // get_section is DISCARDED
|
||||
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
|
||||
@@ -1,350 +0,0 @@
|
||||
// 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_BUFFER_SEGMENTING_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SEGMENTING_BUFFER_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
#include <boost/geometry/extensions/strategies/buffer_join_round.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/extensions/algorithms/dissolve.hpp>
|
||||
|
||||
|
||||
// TEMPORARY do not use yet.
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename PointOut, typename DistanceType>
|
||||
inline bool calculate_parallels(Point const& point1, Point const& point2,
|
||||
PointOut& p1, PointOut& p2, DistanceType const& distance)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
// Simulate a vector d (dx,dy)
|
||||
coordinate_type dx = get<0>(point2) - get<0>(point1);
|
||||
coordinate_type dy = get<1>(point2) - get<1>(point1);
|
||||
|
||||
// For normalization [0,1] (=dot product d.d, sqrt)
|
||||
// TODO: promote to non-integer
|
||||
coordinate_type length = sqrt(dx * dx + dy * dy);
|
||||
|
||||
// Because coordinates are not equal, should been checked before, length should not be zero
|
||||
if(geometry::math::equals(length, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate the normalized perpendicular p, to the left (ccw)
|
||||
coordinate_type px = -dy / length;
|
||||
coordinate_type py = dx / length;
|
||||
|
||||
set<0>(p1, get<0>(point1) + px * distance);
|
||||
set<1>(p1, get<1>(point1) + py * distance);
|
||||
|
||||
set<0>(p2, get<0>(point2) + px * distance);
|
||||
set<1>(p2, get<1>(point2) + py * distance);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryOut, typename Range,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
>
|
||||
struct per_segment_buffer
|
||||
{
|
||||
typedef typename point_type<Range>::type input_point_type;
|
||||
typedef typename point_type<GeometryOut>::type point_type;
|
||||
typedef typename coordinate_type<point_type>::type coordinate_type;
|
||||
typedef coordinate_type distance_type; // TODO promote to FP
|
||||
typedef model::segment<point_type const> segment_type;
|
||||
typedef typename geometry::ring_type<GeometryOut>::type ring_type;
|
||||
typedef typename strategy::side::services::default_strategy<typename cs_tag<point_type>::type>::type side;
|
||||
|
||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
||||
|
||||
|
||||
static inline void calculate_tail(input_point_type const& tail, input_point_type const& head,
|
||||
point_type& tail_left, point_type& tail_right,
|
||||
distance_type& distance_left,
|
||||
distance_type& distance_right,
|
||||
distance_type& buffered_length)
|
||||
{
|
||||
coordinate_type ext_x = get<0>(head) - get<0>(tail);
|
||||
coordinate_type ext_y = get<1>(head) - get<1>(tail);
|
||||
distance_type segment_length = sqrt(ext_x * ext_x + ext_y * ext_y);
|
||||
|
||||
if (buffered_length < geometry::math::abs(distance_left))
|
||||
{
|
||||
distance_left = buffered_length * distance_left < 0 ? -1.0 : 1.0;
|
||||
}
|
||||
if (buffered_length < geometry::math::abs(distance_right))
|
||||
{
|
||||
distance_right = buffered_length * distance_right < 0 ? -1.0 : 1.0;
|
||||
}
|
||||
|
||||
distance_type prop_left = geometry::math::abs(distance_left) / segment_length;
|
||||
distance_type prop_right = geometry::math::abs(distance_right) / segment_length;
|
||||
|
||||
set<0>(tail_left, get<0>(tail) - ext_x * prop_left);
|
||||
set<1>(tail_left, get<1>(tail) - ext_y * prop_left);
|
||||
set<0>(tail_right, get<0>(tail) - ext_x * prop_right);
|
||||
set<1>(tail_right, get<1>(tail) - ext_y * prop_right);
|
||||
|
||||
buffered_length += segment_length;
|
||||
}
|
||||
|
||||
|
||||
static inline void calculate_head(input_point_type const& tail, input_point_type const& head,
|
||||
point_type& head_left, point_type& head_right,
|
||||
distance_type& distance_left,
|
||||
distance_type& distance_right,
|
||||
distance_type const& rest_length)
|
||||
{
|
||||
coordinate_type ext_x = get<0>(head) - get<0>(tail);
|
||||
coordinate_type ext_y = get<1>(head) - get<1>(tail);
|
||||
distance_type segment_length = sqrt(ext_x * ext_x + ext_y * ext_y);
|
||||
|
||||
if (rest_length < distance_left)
|
||||
{
|
||||
distance_left = rest_length;
|
||||
}
|
||||
if (rest_length < distance_right)
|
||||
{
|
||||
distance_right = rest_length;
|
||||
}
|
||||
|
||||
distance_type prop_left = distance_left / segment_length;
|
||||
distance_type prop_right = distance_right / segment_length;
|
||||
|
||||
set<0>(head_left, get<0>(head) + ext_x * prop_left);
|
||||
set<1>(head_left, get<1>(head) + ext_y * prop_left);
|
||||
set<0>(head_right, get<0>(head) + ext_x * prop_right);
|
||||
set<1>(head_right, get<1>(head) + ext_y * prop_right);
|
||||
}
|
||||
|
||||
static inline void apply(Range const& range,
|
||||
std::vector<GeometryOut>& buffered,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
JoinStrategy const& join_strategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Buffer all segments separately, and put them in a temporary vector
|
||||
std::vector<GeometryOut> buffered_pieces;
|
||||
|
||||
bool first = true;
|
||||
|
||||
strategy::buffer::join_round2<point_type> new_join;
|
||||
//strategy::buffer::join_none<point_type> new_join;
|
||||
|
||||
distance_type range_length = geometry::length(range);
|
||||
distance_type buffered_length = coordinate_type();
|
||||
|
||||
iterator_type it = boost::begin(range);
|
||||
//iterator_type it_c = boost::end(range);
|
||||
for (iterator_type previous = it++;
|
||||
it != boost::end(range);
|
||||
++it)
|
||||
{
|
||||
bool const last = it + 1 == boost::end(range);
|
||||
|
||||
distance_type distance_left = distance_strategy.apply(
|
||||
*previous, *it, buffer_side_left);
|
||||
distance_type distance_right = distance_strategy.apply(
|
||||
*previous, *it, buffer_side_right);
|
||||
|
||||
point_type left_ab_p1, left_ab_p2, right_ab_p1, right_ab_p2;
|
||||
|
||||
if (detail::disjoint::disjoint_point_point(*previous, *it)
|
||||
&& calculate_parallels(*previous, *it, left_ab_p1, left_ab_p2,
|
||||
distance_left)
|
||||
&& calculate_parallels(*previous, *it, right_ab_p1, right_ab_p2,
|
||||
-distance_right)
|
||||
)
|
||||
{
|
||||
{
|
||||
point_type tail_left, tail_right, head_left, head_right;
|
||||
|
||||
// For flat buffers, generate corners only if outside range of buffer_distance
|
||||
distance_type distance_tail_left = distance_left;
|
||||
distance_type distance_tail_right = distance_right;
|
||||
distance_type distance_head_left = distance_left;
|
||||
distance_type distance_head_right = distance_right;
|
||||
|
||||
calculate_tail(*previous, *it,
|
||||
tail_left, tail_right,
|
||||
distance_tail_left, distance_tail_right,
|
||||
buffered_length);
|
||||
|
||||
distance_type const rest_length = range_length - buffered_length;
|
||||
|
||||
calculate_head(*previous, *it,
|
||||
head_left, head_right,
|
||||
distance_head_left, distance_head_right,
|
||||
rest_length);
|
||||
|
||||
// Add non-axis aligned rectangle
|
||||
buffered_pieces.resize(buffered_pieces.size() + 1);
|
||||
ring_type& ring = exterior_ring(buffered_pieces.back());
|
||||
ring.push_back(left_ab_p1);
|
||||
ring.push_back(left_ab_p2);
|
||||
|
||||
if (! last)
|
||||
{
|
||||
new_join.apply(*it, left_ab_p2, left_ab_p2, head_left,
|
||||
distance_left, distance_head_left,
|
||||
std::back_inserter(ring));
|
||||
|
||||
ring.push_back(head_left);
|
||||
ring.push_back(head_right);
|
||||
|
||||
new_join.apply(*it, right_ab_p2, head_right, right_ab_p2,
|
||||
distance_right, distance_head_right,
|
||||
std::back_inserter(ring));
|
||||
}
|
||||
|
||||
ring.push_back(right_ab_p2);
|
||||
ring.push_back(right_ab_p1);
|
||||
|
||||
if (! first)
|
||||
{
|
||||
new_join.apply(*previous, right_ab_p1, right_ab_p1, tail_right,
|
||||
distance_right, distance_tail_right,
|
||||
std::back_inserter(ring));
|
||||
|
||||
ring.push_back(tail_right);
|
||||
ring.push_back(tail_left);
|
||||
|
||||
new_join.apply(*previous, left_ab_p1, tail_left, left_ab_p1,
|
||||
distance_left, distance_tail_left,
|
||||
std::back_inserter(ring));
|
||||
}
|
||||
|
||||
ring.push_back(left_ab_p1);
|
||||
}
|
||||
|
||||
previous = it;
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
// TEMP, uncomment to see what was actually generated
|
||||
//buffered.swap(buffered_pieces);
|
||||
//return;
|
||||
// END TEMP
|
||||
|
||||
|
||||
|
||||
BOOST_FOREACH(GeometryOut const& p, buffered_pieces)
|
||||
{
|
||||
if (buffered.empty())
|
||||
{
|
||||
buffered.push_back(p);
|
||||
}
|
||||
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);*/
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
std::vector<GeometryOut> dissolved;
|
||||
BOOST_FOREACH(GeometryOut const& p, buffered)
|
||||
{
|
||||
geometry::dissolve(p, dissolved);
|
||||
}
|
||||
dissolved.swap(buffered);
|
||||
***/
|
||||
|
||||
// Output
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryOut, typename Geometry,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
>
|
||||
inline void segmenting_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
|
||||
)
|
||||
{
|
||||
per_segment_buffer
|
||||
<
|
||||
GeometryOut, Geometry,
|
||||
DistanceStrategy, JoinStrategy
|
||||
>::apply(geometry, buffered, distance_strategy, join_strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SEGMENTING_BUFFER_HPP
|
||||
@@ -1,116 +0,0 @@
|
||||
// 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_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/extensions/strategies/buffer_side.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/detail/buffer/intersecting_inserter.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/detail/buffer/linestring_buffer.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/detail/buffer/line_line_intersection.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp>
|
||||
#include <boost/geometry/extensions/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 << geometry::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
|
||||
@@ -1,89 +0,0 @@
|
||||
// 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_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/extensions/strategies/buffer_side.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/intersecting_inserter.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/linestring_buffer.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/line_line_intersection.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/extensions/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
|
||||
@@ -59,65 +59,25 @@ namespace strategy { namespace buffer
|
||||
*/
|
||||
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
template
|
||||
<
|
||||
typename PointIn, typename Mapper
|
||||
>
|
||||
struct join_mapper
|
||||
{
|
||||
Mapper const& m_mapper;
|
||||
join_mapper(Mapper const& mapper)
|
||||
: m_mapper(mapper)
|
||||
{}
|
||||
|
||||
template <typename BufferAppender>
|
||||
inline void map(PointIn const& ip, PointIn const& vertex,
|
||||
PointIn const& perp1, PointIn const& perp2) const
|
||||
{
|
||||
typename BufferAppender::range_type corner;
|
||||
corner.push_back(vertex);
|
||||
corner.push_back(perp1);
|
||||
corner.push_back(ip);
|
||||
corner.push_back(perp2);
|
||||
corner.push_back(vertex);
|
||||
|
||||
const_cast<Mapper&>(m_mapper).map(corner,
|
||||
"opacity:0.4;fill:rgb(255,0,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// TODO: merge join_miter with join_round, lot of duplicate code
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
// Forget this, it will go
|
||||
template<typename PointIn, typename PointOut, bool AddHooklets, typename Mapper>
|
||||
struct join_miter : public join_mapper<PointIn, Mapper>
|
||||
{
|
||||
join_miter(Mapper const& mapper) : join_mapper(mapper) {}
|
||||
#else
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename PointIn,
|
||||
typename PointOut,
|
||||
bool AddHooklets = true
|
||||
typename PointOut
|
||||
>
|
||||
struct join_miter
|
||||
{
|
||||
|
||||
#endif
|
||||
typedef typename strategy::side::services::default_strategy<typename cs_tag<PointIn>::type>::type side;
|
||||
typedef typename coordinate_type<PointIn>::type coordinate_type;
|
||||
|
||||
|
||||
template <typename BufferAppender>
|
||||
template <typename RangeOut>
|
||||
inline void apply(PointIn const& ip, PointIn const& vertex,
|
||||
PointIn const& perp1, PointIn const& perp2,
|
||||
coordinate_type const& buffer_distance,
|
||||
BufferAppender& appender) const
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
coordinate_type zero = 0;
|
||||
int signum = buffer_distance > zero ? 1
|
||||
@@ -126,15 +86,6 @@ struct join_miter
|
||||
|
||||
if (side::apply(perp1, ip, perp2) == signum)
|
||||
{
|
||||
if (AddHooklets)
|
||||
{
|
||||
appender.append_begin_hooklet(perp1);
|
||||
appender.append_end_hooklet(perp2);
|
||||
}
|
||||
else
|
||||
{
|
||||
appender.append(ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -165,26 +116,15 @@ struct join_miter
|
||||
#endif
|
||||
}
|
||||
|
||||
appender.append_begin_join(p);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
map<BufferAppender>(ip, vertex, perp1, perp2);
|
||||
#endif
|
||||
range_out.push_back(perp1);
|
||||
range_out.push_back(p);
|
||||
range_out.push_back(perp2);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
// Forget this, it will go
|
||||
template<typename PointIn, typename PointOut, typename Mapper>
|
||||
struct join_bevel : public join_mapper<PointIn, Mapper>
|
||||
{
|
||||
join_bevel(Mapper const& mapper) : join_mapper(mapper) {}
|
||||
#else
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename PointIn,
|
||||
@@ -192,62 +132,39 @@ template
|
||||
>
|
||||
struct join_bevel
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
typedef typename coordinate_type<PointIn>::type coordinate_type;
|
||||
|
||||
template <typename BufferAppender>
|
||||
template <typename RangeOut>
|
||||
inline void apply(PointIn const& ip, PointIn const& vertex,
|
||||
PointIn const& perp1, PointIn const& perp2,
|
||||
coordinate_type const& buffer_distance,
|
||||
BufferAppender& appender) const
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
appender.append(perp1);
|
||||
appender.append(perp2);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
map<BufferAppender>(ip, vertex, perp1, perp2);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
// Forget this, it will go
|
||||
template<typename PointIn, typename PointOut, bool AddHooklets, typename Mapper>
|
||||
struct join_round : public join_mapper<PointIn, Mapper>
|
||||
{
|
||||
join_round(Mapper const& mapper, int max_level = 4)
|
||||
: join_mapper(mapper)
|
||||
, m_max_level(max_level)
|
||||
{}
|
||||
#else
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename PointIn,
|
||||
typename PointOut,
|
||||
bool AddHooklets = true
|
||||
typename PointOut
|
||||
>
|
||||
struct join_round
|
||||
{
|
||||
inline join_round(int max_level = 4)
|
||||
inline join_round(int max_level = 6)
|
||||
: m_max_level(max_level)
|
||||
{}
|
||||
#endif
|
||||
|
||||
typedef typename strategy::side::services::default_strategy<typename cs_tag<PointIn>::type>::type side;
|
||||
typedef typename coordinate_type<PointOut>::type coordinate_type;
|
||||
int m_max_level;
|
||||
|
||||
|
||||
template <typename BufferAppender>
|
||||
template <typename RangeOut>
|
||||
inline void mid_points(PointIn const& vertex,
|
||||
PointIn const& p1, PointIn const& p2,
|
||||
coordinate_type const& buffer_distance,
|
||||
BufferAppender& appender,
|
||||
RangeOut& range_out,
|
||||
int level = 1) const
|
||||
{
|
||||
// Generate 'vectors'
|
||||
@@ -272,22 +189,22 @@ struct join_round
|
||||
|
||||
if (level < m_max_level)
|
||||
{
|
||||
mid_points(vertex, p1, mid_point, buffer_distance, appender, level + 1);
|
||||
mid_points(vertex, p1, mid_point, buffer_distance, range_out, level + 1);
|
||||
}
|
||||
appender.append(mid_point);
|
||||
range_out.push_back(mid_point);
|
||||
if (level < m_max_level)
|
||||
{
|
||||
mid_points(vertex, mid_point, p2, buffer_distance, appender, level + 1);
|
||||
mid_points(vertex, mid_point, p2, buffer_distance, range_out, level + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename BufferAppender>
|
||||
template <typename RangeOut>
|
||||
inline void apply(PointIn const& ip, PointIn const& vertex,
|
||||
PointIn const& perp1, PointIn const& perp2,
|
||||
coordinate_type const& buffer_distance,
|
||||
BufferAppender& appender) const
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
coordinate_type zero = 0;
|
||||
int signum = buffer_distance > zero ? 1
|
||||
@@ -296,16 +213,6 @@ struct join_round
|
||||
|
||||
if (side::apply(perp1, ip, perp2) == signum)
|
||||
{
|
||||
// If it is concave (corner to left), add helperline
|
||||
if (AddHooklets)
|
||||
{
|
||||
appender.append_begin_hooklet(perp1);
|
||||
appender.append_end_hooklet(perp2);
|
||||
}
|
||||
else
|
||||
{
|
||||
appender.append(ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -323,25 +230,21 @@ struct join_round
|
||||
set<0>(bp, get<0>(vertex) + vix * prop);
|
||||
set<1>(bp, get<1>(vertex) + viy * prop);
|
||||
|
||||
appender.append_begin_join(perp1);
|
||||
range_out.push_back(perp1);
|
||||
if (m_max_level <= 1)
|
||||
{
|
||||
if (m_max_level == 1)
|
||||
{
|
||||
appender.append(bp);
|
||||
range_out.push_back(bp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mid_points(vertex, perp1, bp, bd, appender);
|
||||
appender.append(bp);
|
||||
mid_points(vertex, bp, perp2, bd, appender);
|
||||
mid_points(vertex, perp1, bp, bd, range_out);
|
||||
range_out.push_back(bp);
|
||||
mid_points(vertex, bp, perp2, bd, range_out);
|
||||
}
|
||||
appender.append_end_join(perp2);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
map<BufferAppender>(bp, vertex, perp1, perp2);
|
||||
#endif
|
||||
range_out.push_back(perp2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user