mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-14 00:42:09 +00:00
Boost.Geometry buffer update
[SVN r77171]
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// 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
|
||||
@@ -23,6 +23,10 @@
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffered_piece_collection.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/line_line_intersection.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
# include <boost/geometry/extensions/algorithms/buffer/buffered_piece_collection_with_mapper.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -90,7 +94,7 @@ struct buffer_range
|
||||
Iterator begin, Iterator end,
|
||||
buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy)
|
||||
JoinStrategy const& join_strategy, bool close = false)
|
||||
{
|
||||
output_point_type previous_p1, previous_p2;
|
||||
output_point_type first_p1, first_p2;
|
||||
@@ -135,10 +139,10 @@ struct buffer_range
|
||||
}
|
||||
if (! range_out.empty())
|
||||
{
|
||||
collection.add_piece(*prev, range_out);
|
||||
collection.add_piece(buffered_join, *prev, range_out);
|
||||
range_out.clear();
|
||||
}
|
||||
collection.add_piece(*prev, *it, p1, p2);
|
||||
collection.add_piece(buffered_segment, *prev, *it, p1, p2);
|
||||
|
||||
previous_p1 = p1;
|
||||
previous_p2 = p2;
|
||||
@@ -161,7 +165,7 @@ struct buffer_range
|
||||
range_out);
|
||||
if (! range_out.empty())
|
||||
{
|
||||
collection.add_piece(*begin, range_out);
|
||||
collection.add_piece(buffered_join, *begin, range_out);
|
||||
}
|
||||
|
||||
// Buffer is closed automatically by last closing corner (NOT FOR OPEN POLYGONS - TODO)
|
||||
@@ -169,6 +173,7 @@ struct buffer_range
|
||||
else if (boost::is_same<Tag, linestring_tag>::value)
|
||||
{
|
||||
// Assume flat-end-strategy for now
|
||||
// TODO fix this (approach) for one-side buffer (1.5 - -1.0)
|
||||
output_point_type rp1, rp2;
|
||||
generate_side(last_ip2, last_ip1,
|
||||
side == buffer_side_left
|
||||
@@ -176,12 +181,14 @@ struct buffer_range
|
||||
: buffer_side_left,
|
||||
distance, rp2, rp1);
|
||||
|
||||
// For flat end:
|
||||
std::vector<output_point_type> range_out;
|
||||
range_out.push_back(previous_p2);
|
||||
range_out.push_back(*(end - 1));
|
||||
range_out.push_back(rp2);
|
||||
// For flat:
|
||||
collection.add_piece(last_ip2, range_out);
|
||||
if (close)
|
||||
{
|
||||
range_out.push_back(rp2);
|
||||
}
|
||||
collection.add_piece(buffered_flat_end, range_out);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -251,14 +258,14 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy)
|
||||
{
|
||||
collection.add_input();
|
||||
collection.start_new_ring();
|
||||
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);
|
||||
distance, join_strategy, true);
|
||||
|
||||
}
|
||||
};
|
||||
@@ -284,8 +291,7 @@ struct buffer_inserter<polygon_tag, PolygonInput, PolygonOutput>
|
||||
typedef buffer_inserter<ring_tag, input_ring_type, output_ring_type> policy;
|
||||
|
||||
{
|
||||
collection.add_input();
|
||||
|
||||
collection.start_new_ring();
|
||||
policy::apply(exterior_ring(polygon), collection,
|
||||
distance, join_strategy);
|
||||
}
|
||||
@@ -294,10 +300,7 @@ struct buffer_inserter<polygon_tag, PolygonInput, PolygonOutput>
|
||||
= interior_rings(polygon);
|
||||
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
|
||||
{
|
||||
output_ring_type ring;
|
||||
|
||||
collection.add_input();
|
||||
|
||||
collection.start_new_ring();
|
||||
policy::apply(*it, collection, distance, join_strategy);
|
||||
}
|
||||
|
||||
@@ -327,7 +330,14 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
#endif
|
||||
)
|
||||
{
|
||||
detail::buffer::buffered_piece_collection<typename geometry::ring_type<GeometryOutput>::type> collection;
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
detail::buffer::buffered_piece_collection_with_mapper
|
||||
#else
|
||||
detail::buffer::buffered_piece_collection
|
||||
#endif
|
||||
<
|
||||
typename geometry::ring_type<GeometryOutput>::type
|
||||
> collection;
|
||||
|
||||
dispatch::buffer_inserter
|
||||
<
|
||||
@@ -336,20 +346,23 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
GeometryOutput
|
||||
>::apply(geometry_input, collection, distance_strategy, join_strategy);
|
||||
|
||||
collection.get_turns(geometry_input);
|
||||
collection.get_turns(geometry_input, distance_strategy.factor());
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
collection.map_offsetted(mapper);
|
||||
//collection.map_offsetted(mapper);
|
||||
collection.map_turns(mapper);
|
||||
//collection.map_opposite_locations(mapper);
|
||||
#endif
|
||||
|
||||
collection.discard_points();
|
||||
collection.discard_rings();
|
||||
collection.discard_turns();
|
||||
collection.enrich();
|
||||
collection.traverse();
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
//collection.map<geometry::polygon_tag>(mapper);
|
||||
collection.map_turns(mapper);
|
||||
collection.map_traverse(mapper);
|
||||
//collection.map_turns(mapper);
|
||||
collection.map_pieces<geometry::polygon_tag>(mapper); //, false, true);
|
||||
//collection.map_traverse(mapper);
|
||||
#endif
|
||||
|
||||
collection.assign<GeometryOutput>(out);
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
// 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_BUFFER_POLICIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_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/covered_by.hpp>
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
enum intersection_location_type
|
||||
{
|
||||
location_ok, inside_buffer, inside_original
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
struct turn_assign_for_buffer
|
||||
{
|
||||
static bool const include_no_turn = false;
|
||||
static bool const include_degenerate = false;
|
||||
static bool const include_opposite = true;
|
||||
|
||||
template <typename Point1, typename Point2, typename Turn, typename IntersectionInfo, typename DirInfo>
|
||||
static inline void apply(Turn& turn, Point1 const& p1, Point2 const& p2, IntersectionInfo const& intersection_info, DirInfo const& dir_info)
|
||||
{
|
||||
detail::overlay::calculate_distance_policy::apply(turn, p1, p2,
|
||||
intersection_info, dir_info);
|
||||
if (dir_info.opposite && intersection_info.count == 2)
|
||||
{
|
||||
turn.is_opposite = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Should 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)
|
||||
{}
|
||||
};
|
||||
|
||||
// Version for buffer including type of location, is_opposite, and helper variables
|
||||
template <typename Point>
|
||||
struct buffer_turn_info : public detail::overlay::turn_info<Point, buffer_turn_operation<Point> >
|
||||
{
|
||||
bool is_opposite;
|
||||
|
||||
intersection_location_type location;
|
||||
|
||||
int count_within, count_on_helper, count_on_offsetted, count_on_corner;
|
||||
int count_on_opposite, count_on_closed;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
std::string debug_string;
|
||||
#endif
|
||||
|
||||
inline buffer_turn_info()
|
||||
: is_opposite(false)
|
||||
, location(location_ok)
|
||||
, count_within(0)
|
||||
, count_on_helper(0)
|
||||
, count_on_offsetted(0)
|
||||
, count_on_corner(0)
|
||||
, count_on_opposite(0)
|
||||
, count_on_closed(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,276 @@
|
||||
// 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_WM_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_WM_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffered_piece_collection.hpp>
|
||||
#include <boost/geometry/algorithms/unique.hpp>
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
|
||||
template <typename Ring>
|
||||
struct buffered_piece_collection_with_mapper
|
||||
: public buffered_piece_collection<Ring>
|
||||
{
|
||||
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_opposite_locations(Mapper& mapper)
|
||||
{
|
||||
for (typename boost::range_iterator<clustered_location_type const>::type it =
|
||||
boost::begin(clustered_turn_locations);
|
||||
it != boost::end(clustered_turn_locations); ++it)
|
||||
{
|
||||
mapper.map(it->first, "fill:rgb(0,128,0);", 3);
|
||||
|
||||
std::ostringstream out;
|
||||
out << it->second.angles.size();
|
||||
for (std::set<int>::const_iterator sit = it->second.turn_indices.begin(); sit != it->second.turn_indices.end(); ++sit)
|
||||
{
|
||||
out << "," << *sit;
|
||||
}
|
||||
mapper.text(it->first, out.str(), "fill:rgb(0,128,0);font-family='Arial';font-size:8px", 6, 8);
|
||||
|
||||
for (unsigned int i = 0; i < it->second.angles.size(); i++)
|
||||
{
|
||||
geometry::model::linestring<point_type> line;
|
||||
angle_info const& tp = it->second.angles[i];
|
||||
point_type p1, p2;
|
||||
geometry::set<0>(p1, geometry::get<0>(it->first) + cos(tp.angle) * 0.1);
|
||||
geometry::set<1>(p1, geometry::get<1>(it->first) + sin(tp.angle) * 0.1);
|
||||
geometry::set<0>(p2, geometry::get<0>(it->first) + cos(tp.angle) * 0.4);
|
||||
geometry::set<1>(p2, geometry::get<1>(it->first) + sin(tp.angle) * 0.4);
|
||||
std::ostringstream out;
|
||||
//out << tp.angle << " " << int(tp.incoming);
|
||||
out << (tp.incoming ? "i" : "o") << " " << i;
|
||||
if (tp.incoming)
|
||||
{
|
||||
int offset = 7;
|
||||
if (tp.debug) offset += 5;
|
||||
out << " " << tp.debug_info;
|
||||
line.push_back(p1);
|
||||
line.push_back(p2);
|
||||
mapper.map(line, "stroke:rgb(0,0,255);stroke-width:1", 1);
|
||||
mapper.map(p1, "fill:rgb(0,0,0);", 2);
|
||||
mapper.text(p2, out.str(), "fill:rgb(0,0,255);font-family='Arial';font-size:8px", 2, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
line.push_back(p1);
|
||||
line.push_back(p2);
|
||||
mapper.map(line, "stroke:rgb(255,0,0);stroke-width:1", 1);
|
||||
mapper.map(p2, "fill:rgb(0,0,0);", 2);
|
||||
mapper.text(p2, out.str(), "fill:rgb(0,0,255);font-family='Arial';font-size:8px", 2, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_turns(Mapper& mapper)
|
||||
{
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
std::map<std::pair<coordinate_type, coordinate_type>, int> offsets;
|
||||
|
||||
|
||||
int index = 0;
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
{
|
||||
if (! it->opposite())
|
||||
{
|
||||
std::pair<coordinate_type, coordinate_type> p
|
||||
= std::make_pair(geometry::get<0>(it->point), geometry::get<1>(it->point));
|
||||
|
||||
char color = 'g';
|
||||
std::string fill = "fill:rgb(0,255,0);";
|
||||
switch(it->location)
|
||||
{
|
||||
case inside_buffer : fill = "fill:rgb(255,0,0);"; color = 'r'; break;
|
||||
case inside_original : fill = "fill:rgb(0,0,255);"; color = 'b'; break;
|
||||
}
|
||||
std::ostringstream out;
|
||||
out << it->operations[0].piece_index << "/" << it->operations[1].piece_index << std::endl;
|
||||
//out << " " << m_pieces[it->operations[0].piece_index].first_seg_id.segment_index
|
||||
// << "+" << m_pieces[it->operations[1].piece_index].first_seg_id.segment_index;
|
||||
//out << " " << m_pieces[it->operations[0].piece_index].index
|
||||
// << "," << m_pieces[it->operations[1].piece_index].index << std::endl;
|
||||
//out << " " << it->operations[0].seg_id.segment_index
|
||||
// << "|" << it->operations[1].seg_id.segment_index;
|
||||
out << " " << method_char(it->method)
|
||||
<< ":" << operation_char(it->operations[0].operation)
|
||||
<< "/" << operation_char(it->operations[1].operation);
|
||||
out << " " << it->count_within
|
||||
<< "-" << it->count_on_helper
|
||||
<< "-" << it->count_on_corner
|
||||
<< "-" << it->count_on_offsetted
|
||||
<< "-" << it->count_on_closed
|
||||
//|| it->count_on_opposite > 0
|
||||
//<< it->debug_string
|
||||
;
|
||||
out << color << std::endl;
|
||||
|
||||
out << " " << it->operations[0].seg_id.segment_index
|
||||
<< "|" << it->operations[1].seg_id.segment_index;
|
||||
//out << it->operations[0].enriched.travels_to_vertex_index
|
||||
// << "/" << it->operations[1].enriched.travels_to_vertex_index;
|
||||
|
||||
offsets[p] += 10;
|
||||
int offset = offsets[p];
|
||||
|
||||
mapper.map(it->point, fill, 6);
|
||||
mapper.text(it->point, out.str(), "fill:rgb(0,0,0);font-family='Arial';font-size:9px;", 5, offset);
|
||||
|
||||
offsets[p] += 25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tag, typename Mapper>
|
||||
inline void map_pieces(Mapper& mapper, bool pieces = true, bool indices = true)
|
||||
{
|
||||
for(typename piece_vector::const_iterator it = boost::begin(m_pieces);
|
||||
it != boost::end(m_pieces);
|
||||
++it)
|
||||
{
|
||||
Ring corner;
|
||||
|
||||
segment_identifier seg_id = it->first_seg_id;
|
||||
|
||||
buffered_ring<Ring> const& ring = offsetted_rings[seg_id.multi_index];
|
||||
|
||||
std::copy(boost::begin(ring) + seg_id.segment_index,
|
||||
boost::begin(ring) + it->last_segment_index,
|
||||
std::back_inserter(corner));
|
||||
std::copy(boost::begin(it->helper_segments),
|
||||
boost::end(it->helper_segments),
|
||||
std::back_inserter(corner));
|
||||
|
||||
{
|
||||
// Corners of onesided buffers are empty.
|
||||
// Mapping this might result (for buffer_line_two_bends_right_d_r) in a
|
||||
// "unknown location(0): fatal error in "test_main_caller( argc, argv )":
|
||||
// class boost::numeric::positive_overflow: bad numeric conversion: positive overflow"
|
||||
// This is only in release-mode of MSVC, only for the pieces (mapping of rings)
|
||||
// Must be somewhere in either transform or ublas
|
||||
// TODO: find out why
|
||||
// Making them unique helps somehow (while it then still has the same coordinates...)
|
||||
geometry::unique(corner);
|
||||
}
|
||||
|
||||
if (pieces)
|
||||
{
|
||||
if (it->type == buffered_segment)
|
||||
{
|
||||
if(boost::is_same<Tag, ring_tag>::value || boost::is_same<Tag, polygon_tag>::value)
|
||||
{
|
||||
mapper.map(corner, "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(corner, "opacity:0.3;fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.map(corner, "opacity:0.3;fill:rgb(255,0,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
}
|
||||
}
|
||||
|
||||
if (indices)
|
||||
{
|
||||
|
||||
// Put starting piece_index / segment_index in centroid
|
||||
point_type centroid;
|
||||
if (corner.size() > 3)
|
||||
{
|
||||
geometry::centroid(corner, centroid);
|
||||
}
|
||||
else
|
||||
{
|
||||
centroid = corner.front();
|
||||
}
|
||||
std::ostringstream out;
|
||||
out << it->index << "/" << it->first_seg_id.segment_index << ".." << it->last_segment_index - 1;
|
||||
mapper.text(centroid, out.str(), "fill:rgb(255,0,0);font-family='Arial';", 5, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_offsetted_points(Mapper& mapper)
|
||||
{
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator oit = boost::begin(offsetted_rings);
|
||||
oit != boost::end(offsetted_rings);
|
||||
++oit)
|
||||
{
|
||||
int index = 0;
|
||||
for (typename boost::range_iterator<std::vector<point_type> const>::type pit = boost::begin(*oit); pit != boost::end(*oit); ++pit)
|
||||
{
|
||||
mapper.map(*pit, "fill:rgb(0,0,0);", 2);
|
||||
std::ostringstream out;
|
||||
out << index++;
|
||||
mapper.text(*pit, 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_WM_HPP
|
||||
@@ -0,0 +1,126 @@
|
||||
// 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_SIDE_ON_CONVEX_RANGE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SIDE_ON_CONVEX_RANGE_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <int D>
|
||||
struct collinear_point_on_segment_check
|
||||
{
|
||||
typedef double coordinate_type; // TODO just use one - they're all the same (for buffer)
|
||||
|
||||
static inline bool apply_sorted(coordinate_type const& subject, coordinate_type const& c1, coordinate_type const& c2)
|
||||
{
|
||||
return subject >= c1 && subject <= c2;
|
||||
}
|
||||
|
||||
template <typename P0, typename P1, typename P2>
|
||||
static inline bool apply(P0 const& subject, P1 const& p1, P2 const& p2)
|
||||
{
|
||||
coordinate_type const cs = geometry::get<D>(subject);
|
||||
coordinate_type const c1 = geometry::get<D>(p1);
|
||||
coordinate_type const c2 = geometry::get<D>(p2);
|
||||
return c1 > c2
|
||||
? apply_sorted(cs, c2, c1)
|
||||
: apply_sorted(cs, c1, c2)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Checks is subject-point is on the segment, provided that it is already determined that it was collinear
|
||||
template <typename P0, typename P1, typename P2>
|
||||
inline bool collinear_point_on_segment(P0 const& subject, P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return collinear_point_on_segment_check<0>::apply(subject, p1, p2)
|
||||
&& collinear_point_on_segment_check<1>::apply(subject, p1, p2);
|
||||
}
|
||||
|
||||
|
||||
template <typename SideStrategy, typename Point, typename Range>
|
||||
inline int side_on_convex_range(Point const& subject, Range const& range)
|
||||
{
|
||||
bool has_collinear = false;
|
||||
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
Range const
|
||||
>::type iterator_type;
|
||||
|
||||
iterator_type it = boost::begin(range);
|
||||
for (iterator_type prev = it++;
|
||||
it != boost::end(range);
|
||||
prev = it++)
|
||||
{
|
||||
int const side = SideStrategy::apply(subject, *prev, *it);
|
||||
switch(side)
|
||||
{
|
||||
case 1 :
|
||||
return 1;
|
||||
case 0 :
|
||||
// Check if it is really on the segment.
|
||||
// If not, it is either on the left (because polygon is convex)
|
||||
// or it is still on one of the other segments (if segments are collinear)
|
||||
if (collinear_point_on_segment(subject, *prev, *it))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
has_collinear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return has_collinear ? 1 : -1;
|
||||
}
|
||||
|
||||
template <typename SideStrategy, typename Point, typename Iterator>
|
||||
static inline int side_on_convex_range(Point const& subject,
|
||||
Iterator first, Iterator last,
|
||||
/* by value: */ segment_identifier seg_id,
|
||||
segment_identifier& on_segment_seg_id)
|
||||
{
|
||||
bool has_collinear = false;
|
||||
Iterator it = first;
|
||||
for (Iterator prev = it++; it != last; prev = it++, seg_id.segment_index++)
|
||||
{
|
||||
int side = SideStrategy::apply(subject, *prev, *it);
|
||||
switch(side)
|
||||
{
|
||||
case 1 :
|
||||
return 1;
|
||||
case 0 :
|
||||
// Check if it is REALLY on the segment.
|
||||
// If not, it is either on the left (because polygon is convex)
|
||||
// or it is still on one of the other segments (if segments are collinear)
|
||||
if (collinear_point_on_segment(subject, *prev, *it))
|
||||
{
|
||||
on_segment_seg_id = seg_id;
|
||||
return 0;
|
||||
}
|
||||
has_collinear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return has_collinear ? 1 : -1;
|
||||
}
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_SIDE_ON_CONVEX_RANGE_HPP
|
||||
@@ -270,6 +270,11 @@ public :
|
||||
{
|
||||
return side == buffer_side_left ? m_left : m_right;
|
||||
}
|
||||
|
||||
inline int factor() const
|
||||
{
|
||||
return m_left < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
private :
|
||||
CoordinateType m_left;
|
||||
|
||||
@@ -31,6 +31,9 @@ static std::string const two_bends = "LINESTRING(0 0,4 5,7 4,10 6)";
|
||||
static std::string const overlapping = "LINESTRING(0 0,4 5,7 4,10 6, 10 2,2 2)";
|
||||
static std::string const curve = "LINESTRING(2 7,3 5,5 4,7 5,8 7)";
|
||||
|
||||
static std::string const for_collinear = "LINESTRING(2 0,0 0,0 4,6 4,6 0,4 0)";
|
||||
static std::string const for_collinear2 = "LINESTRING(2 1,2 0,0 0,0 4,6 4,6 0,4 0,4 1)";
|
||||
|
||||
static std::string const chained2 = "LINESTRING(0 0,1 1,2 2)";
|
||||
static std::string const chained3 = "LINESTRING(0 0,1 1,2 2,3 3)";
|
||||
static std::string const chained4 = "LINESTRING(0 0,1 1,2 2,3 3,4 4)";
|
||||
@@ -46,32 +49,55 @@ void test_all()
|
||||
typedef bg::model::linestring<P> linestring;
|
||||
typedef bg::model::polygon<P> polygon;
|
||||
|
||||
double factor = +1.0; // does NOT yet work for negative buffer
|
||||
double right = factor * 1.0;
|
||||
test_one<linestring, buf::join_round, polygon>("simplex", simplex, 'r', 19.209, 1.5, 1.5);
|
||||
test_one<linestring, buf::join_miter, polygon>("simplex", simplex, 'm', 19.209, 1.5, 1.5);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("simplex", simplex, 'r', 19.2093727122985, 1.5, right);
|
||||
test_one<linestring, buf::join_miter, polygon>("simplex", simplex, 'm', 19.2093727122985, 1.5, right);
|
||||
test_one<linestring, buf::join_miter, polygon>("simplex_asym_neg", simplex, 'm', 3.202, +1.5, -1.0);
|
||||
test_one<linestring, buf::join_miter, polygon>("simplex_asym_pos", simplex, 'm', 3.202, -1.5, +1.0);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("straight", straight, 'r', 19.2093727122985, 1.5, right);
|
||||
test_one<linestring, buf::join_miter, polygon>("straight", straight, 'm', 19.2093727122985, 1.5, right);
|
||||
//test_one<linestring, buf::join_round, polygon>("straight", straight, 'r', 19.2093727122985, 1.5, 1.5);
|
||||
//test_one<linestring, buf::join_miter, polygon>("straight", straight, 'm', 19.2093727122985, 1.5, 1.5);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("one_bend", one_bend, 'r', 28.4879539312069, 1.5, right);
|
||||
test_one<linestring, buf::join_miter, polygon>("one_bend", one_bend, 'm', 28.6962056928037, 1.5, right);
|
||||
test_one<linestring, buf::join_round, polygon>("one_bend", one_bend, 'r', 28.488, 1.5, 1.5);
|
||||
test_one<linestring, buf::join_miter, polygon>("one_bend", one_bend, 'm', 28.696, 1.5, 1.5);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("two_bends", two_bends, 'r', 39.2220036534424, 1.5, right);
|
||||
test_one<linestring, buf::join_miter, polygon>("two_bends", two_bends, 'm', 39.5128595191957, 1.5, right);
|
||||
test_one<linestring, buf::join_round, polygon>("two_bends", two_bends, 'r', 39.222, 1.5, 1.5);
|
||||
test_one<linestring, buf::join_miter, polygon>("two_bends", two_bends, 'm', 39.513, 1.5, 1.5);
|
||||
test_one<linestring, buf::join_round, polygon>("two_bends_left", two_bends, 'r', 20.028, 1.5, 0.0);
|
||||
test_one<linestring, buf::join_miter, polygon>("two_bends_left", two_bends, 'm', 20.225, 1.5, 0.0);
|
||||
test_one<linestring, buf::join_round, polygon>("two_bends_right", two_bends, 'r', 19.211, 0.0, 1.5);
|
||||
test_one<linestring, buf::join_miter, polygon>("two_bends_right", two_bends, 'm', 19.288, 0.0, 1.5);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("overlapping", overlapping, 'r', 65.646005724872, 1.5, right);
|
||||
test_one<linestring, buf::join_miter, polygon>("overlapping", overlapping, 'm', 68.1395194809293, 1.5, right);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("curve", curve, 'r', 65.646005724872, 5.0, factor * 3.0);
|
||||
test_one<linestring, buf::join_miter, polygon>("curve", curve, 'm', 68.1395194809293, 5.0, factor * 3.0);
|
||||
// Next (and all similar cases) which a offsetted-one-sided buffer has to be fixed.
|
||||
//test_one<linestring, buf::join_miter, polygon>("two_bends_neg", two_bends, 'm', 99, +1.5, -1.0);
|
||||
//test_one<linestring, buf::join_miter, polygon>("two_bends_pos", two_bends, 'm', 99, -1.5, +1.0);
|
||||
//test_one<linestring, buf::join_round, polygon>("two_bends_neg", two_bends, 'r', 99, +1.5, -1.0);
|
||||
//test_one<linestring, buf::join_round, polygon>("two_bends_pos", two_bends, 'r', 99, -1.5, +1.0);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("chained2", chained2, 'r', 65.646005724872, 2.5, factor * 1.5);
|
||||
test_one<linestring, buf::join_round, polygon>("chained3", chained3, 'r', 65.646005724872, 2.5, factor * 1.5);
|
||||
test_one<linestring, buf::join_round, polygon>("chained4", chained4, 'r', 65.646005724872, 2.5, factor * 1.5);
|
||||
test_one<linestring, buf::join_round, polygon>("overlapping150", overlapping, 'r', 65.646, 1.5, 1.5);
|
||||
test_one<linestring, buf::join_miter, polygon>("overlapping150", overlapping, 'm', 68.140, 1.5, 1.5);
|
||||
// Different cases with intersection points on flat and (left/right from line itself)
|
||||
test_one<linestring, buf::join_round, polygon>("overlapping_asym_150_010", overlapping, 'r', 48.308, 1.5, 0.25);
|
||||
test_one<linestring, buf::join_miter, polygon>("overlapping_asym_150_010", overlapping, 'm', 50.770, 1.5, 0.25);
|
||||
test_one<linestring, buf::join_round, polygon>("overlapping_asym_150_075", overlapping, 'r', 58.506, 1.5, 0.75);
|
||||
test_one<linestring, buf::join_miter, polygon>("overlapping_asym_150_075", overlapping, 'm', 60.985, 1.5, 0.75);
|
||||
test_one<linestring, buf::join_round, polygon>("overlapping_asym_150_100", overlapping, 'r', 62.514, 1.5, 1.0);
|
||||
test_one<linestring, buf::join_miter, polygon>("overlapping_asym_150_100", overlapping, 'm', 64.984, 1.5, 1.0);
|
||||
|
||||
test_one<linestring, buf::join_round, polygon>("reallife1", reallife1, 'r', 65.646005724872, 16.5, factor * 6.5);
|
||||
test_one<linestring, buf::join_round, polygon>("for_collinear", for_collinear, 'r', 68.561, 2.0, 2.0);
|
||||
test_one<linestring, buf::join_miter, polygon>("for_collinear", for_collinear, 'm', 72, 2.0, 2.0);
|
||||
test_one<linestring, buf::join_round, polygon>("for_collinear2", for_collinear2, 'r', 74.387, 2.0, 2.0);
|
||||
test_one<linestring, buf::join_miter, polygon>("for_collinear2", for_collinear2, 'm', 78.0, 2.0, 2.0);
|
||||
|
||||
//test_one<linestring, buf::join_round, polygon>("curve", curve, 'r', 99, 5.0, 3.0);
|
||||
//test_one<linestring, buf::join_miter, polygon>("curve", curve, 'm', 99, 5.0, 3.0);
|
||||
|
||||
//test_one<linestring, buf::join_round, polygon>("chained2", chained2, 'r', 99, 2.5, 1.5);
|
||||
//test_one<linestring, buf::join_round, polygon>("chained3", chained3, 'r', 99, 2.5, 1.5);
|
||||
//test_one<linestring, buf::join_round, polygon>("chained4", chained4, 'r', 99, 2.5, 1.5);
|
||||
|
||||
//test_one<linestring, buf::join_round, polygon>("reallife1", reallife1, 'r', 99, 16.5, 6.5);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +112,5 @@ int test_main(int, char* [])
|
||||
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
|
||||
//test_all<bg::model::point<tt, 2, bg::cs::cartesian> >();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,17 @@ static std::string const letter_L
|
||||
= "POLYGON ((0 0,0 4,1 4,1 1,3 1,3 0,0 0))";
|
||||
static std::string const indentation
|
||||
= "POLYGON ((0 0,0 5,4 5,4 4,3 3,2 4,2 1,3 2,4 1,4 0,0 0))";
|
||||
static std::string const funnelgate
|
||||
= "POLYGON((0 0,0 7,7 7,7 0,5 0,5 1,6 6,1 6,2 1,2 0,0 0))";
|
||||
static std::string const gammagate
|
||||
= "POLYGON((0 0,0 6,9 6,9 0,4 0,4 2,7 2,7 4,2 4,2 0,0 0))";
|
||||
static std::string const fork_a
|
||||
= "POLYGON((0 0,0 6,9 6,9 0,4 0,4 2,7 2,7 4,6 4,6 5,5 5,5 4,4 4,4 5,3 5,3 4,2 4,2 0,0 0))";
|
||||
static std::string const fork_b
|
||||
= "POLYGON((0 0,0 8,14 8,14 0,4 0,4 2,13 2,13 4,12 4,12 7,9 7,9 4,7 4,7 7,4 7,4 4,2 4,2 0,0 0))";
|
||||
static std::string const fork_c
|
||||
= "POLYGON((0 0,0 9,12 9,12 0,4 0,4 4,6 4,6 2,8 2,8 4,10 4,10 7,6 7,6 6,2 6,2 0,0 0))";
|
||||
|
||||
static std::string const arrow
|
||||
= "POLYGON ((1 0,1 5,0.5 4.5,2 10,3.5 4.5,3 5,3 0,1 0))";
|
||||
static std::string const tipped_aitch
|
||||
@@ -54,8 +65,6 @@ void test_all()
|
||||
|
||||
typedef bg::model::polygon<P> polygon_type;
|
||||
|
||||
test_one<polygon_type, buf::join_round, polygon_type>("saw", saw, 'r', -1, 1.0);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("L", letter_L, 'm', 14.0, 0.5);
|
||||
test_one<polygon_type, buf::join_round, polygon_type>("L", letter_L, 'r', 13.7314, 0.5);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("simplex", simplex, 'm', 52.8733, 1.5);
|
||||
@@ -80,11 +89,12 @@ test_one<polygon_type, buf::join_round, polygon_type>("saw", saw, 'r', -1, 1.0);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("indentation12", indentation, 'm', 46.3541, 1.2);
|
||||
test_one<polygon_type, buf::join_round, polygon_type>("indentation12", indentation, 'r', 45.0537, 1.2);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("indentation4_neg", indentation, 'm', 6.99098413022335, -0.4);
|
||||
// TODO: fix, the buffered pieces are currently counterclockwise, that should be reversed
|
||||
//test_one<polygon_type, buf::join_miter, polygon_type>("indentation4_neg", indentation, 'm', 6.99098413022335, -0.4);
|
||||
//test_one<polygon_type, buf::join_round, polygon_type>("indentation4_neg", indentation, 'r', 7.25523322189147, -0.4);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("indentation8_neg", indentation, 'm', 1.36941992048731, -0.8);
|
||||
//test_one<polygon_type, buf::join_miter, polygon_type>("indentation8_neg", indentation, 'm', 1.36941992048731, -0.8);
|
||||
//test_one<polygon_type, buf::join_round, polygon_type>("indentation8_neg", indentation, 'r', 1.37375487490664, -0.8);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("indentation12_neg", indentation, 'm', 0, -1.2);
|
||||
//test_one<polygon_type, buf::join_miter, polygon_type>("indentation12_neg", indentation, 'm', 0, -1.2);
|
||||
//test_one<polygon_type, buf::join_round, polygon_type>("indentation12_neg", indentation, 'r', 0, -1.2);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("donut_simplex6", donut_simplex, 'm', 53.648, 0.6);
|
||||
@@ -121,11 +131,19 @@ test_one<polygon_type, buf::join_round, polygon_type>("saw", saw, 'r', -1, 1.0);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("snake6", snake, 'm', 75.44, 0.6);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("snake16", snake, 'm', 114.24, 1.6);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("funnelgate2", funnelgate, 'm', 120.982, 2);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("funnelgate3", funnelgate, 'm', 13*13, 3);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("funnelgate4", funnelgate, 'm', 15*15, 4);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("gammagate1", gammagate, 'm', 88, 1);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("fork_a1", fork_a, 'm', 88, 1);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("fork_b1", fork_b, 'm', 154, 1);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("fork_c1", fork_c, 'm', 152, 1);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("gammagate2", gammagate, 'm', 130, 2);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower1", flower, 'm', 67.614, 0.1);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower20", flower, 'm', 74.894, 0.20);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower25", flower, 'm', 78.226, 0.25);
|
||||
// TODO: fix the flowers-with-miter
|
||||
goto skip_flower_miter;
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower30", flower, 'm', 81.492494146177947, 0.30);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower35", flower, 'm', 84.694183819917185, 0.35);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower40", flower, 'm', 87.8306529577, 0.40);
|
||||
@@ -134,7 +152,6 @@ goto skip_flower_miter;
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower55", flower, 'm', 96.848737155342079, 0.55);
|
||||
test_one<polygon_type, buf::join_miter, polygon_type>("flower60", flower, 'm', 99.724324149315279, 0.60);
|
||||
|
||||
skip_flower_miter:
|
||||
test_one<polygon_type, buf::join_round, polygon_type>("flower10", flower, 'r', 67.486, 0.10);
|
||||
test_one<polygon_type, buf::join_round, polygon_type>("flower20", flower, 'r', 74.702, 0.20);
|
||||
test_one<polygon_type, buf::join_round, polygon_type>("flower25", flower, 'r', 78.071, 0.25);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef BOOST_GEOMETRY_TEST_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_TEST_BUFFER_HPP
|
||||
|
||||
#define BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
//#define BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
#define TEST_WITH_SVG
|
||||
|
||||
#include <fstream>
|
||||
@@ -96,7 +96,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
<< string_from_type<coordinate_type>::name()
|
||||
<< "_" << join;
|
||||
|
||||
//std::cout << complete.str() << std::endl;
|
||||
std::cout << complete.str() << std::endl;
|
||||
|
||||
std::ostringstream filename;
|
||||
filename << "buffer_" << complete.str() << ".svg";
|
||||
@@ -108,13 +108,13 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
{
|
||||
bg::model::box<point_type> box;
|
||||
bg::envelope(geometry, box);
|
||||
double d = distance_left;
|
||||
if (distance_right > 0)
|
||||
{
|
||||
d += distance_right;
|
||||
}
|
||||
double d = std::abs(distance_left);
|
||||
if (distance_right > -998)
|
||||
{
|
||||
d += std::abs(distance_right);
|
||||
}
|
||||
|
||||
bg::buffer(box, box, std::abs(d) * 1.1);
|
||||
bg::buffer(box, box, d * 1.1);
|
||||
mapper.add(box);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
join_strategy_type join_strategy;
|
||||
|
||||
typedef bg::strategy::buffer::distance_assymetric<coordinate_type> distance_strategy_type;
|
||||
distance_strategy_type distance_strategy(distance_left, distance_left / 2.0); // TODO: distance_right
|
||||
distance_strategy_type distance_strategy(distance_left, distance_right);
|
||||
|
||||
std::vector<GeometryOut> buffered;
|
||||
|
||||
@@ -154,7 +154,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
//}
|
||||
|
||||
|
||||
if (distance_left > 0 && expected_area > -0.1)
|
||||
if (expected_area > -0.1)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE
|
||||
(
|
||||
@@ -181,14 +181,13 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Map input geometry in green
|
||||
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,128,0);stroke-width:1");
|
||||
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,128,0);stroke-width:10");
|
||||
|
||||
BOOST_FOREACH(GeometryOut const& polygon, buffered)
|
||||
{
|
||||
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3");
|
||||
//mapper.map(polygon, "opacity:0.2;fill:none;stroke:rgb(255,0,0);stroke-width:3");
|
||||
post_map(polygon, mapper);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user