[buffer] We have to simplify the ring before to avoid very small-scaled

features in the original (convex/concave/convex) being enlarged
in a very large scale and causing issues (IP's within pieces).
This might be reconsidered later. Simplifying with a very small
distance will never be visible in the result,
if it is using round joins. For miter joins they are even more
sensitive to small scale input features, however the result will
look better.

A distance strategy can change behaviour (make larger - set simplify
distance to 0.0 to avoid simplification)

This fixes the parcel issue(s)
This commit is contained in:
Barend Gehrels 2014-06-25 13:32:42 +02:00
parent 7f3b509fb5
commit 7baf1a29e5
5 changed files with 65 additions and 21 deletions

View File

@ -27,6 +27,8 @@
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
#include <boost/geometry/algorithms/simplify.hpp>
namespace boost { namespace geometry
{
@ -240,6 +242,8 @@ struct buffer_range
{
robust_point_type robust_input;
geometry::recalculate(robust_input, *it, robust_policy);
// Check on equality - however, if input is simplified, this is highly
// unlikely (though possible by rescaling)
if (! detail::equals::equals_point_point(previous_robust_input, robust_input))
{
output_point_type p1, p2;
@ -274,8 +278,6 @@ struct buffer_range
previous_robust_input = robust_input;
}
// TODO: take care of degenerate segments
// Might be replaced by specialization
if(boost::is_same<Tag, ring_tag>::value)
{
@ -512,18 +514,30 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
{
if (boost::size(ring) > 3)
{
// We have to simplify the ring before to avoid very small-scaled
// features in the original (convex/concave/convex) being enlarged
// in a very large scale and causing issues (IP's within pieces).
// This might be reconsidered later. Simplifying with a very small
// distance (1%% of the buffer) will never be visible in the result,
// if it is using round joins. For miter joins they are even more
// sensitive to small scale input features, however the result will
// look better.
// It also get rid of duplicate points
RingOutput simplified;
geometry::simplify(ring, simplified, distance.simplify_distance());
if (distance.negative())
{
// Walk backwards (rings will be reversed afterwards)
// It might be that this will be changed later.
// TODO: decide this.
base::iterate(collection, 0, boost::rbegin(ring), boost::rend(ring),
base::iterate(collection, 0, boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, join_strategy, end_strategy, robust_policy);
}
else
{
base::iterate(collection, 0, boost::begin(ring), boost::end(ring),
base::iterate(collection, 0, boost::begin(simplified), boost::end(simplified),
strategy::buffer::buffer_side_left,
distance, join_strategy, end_strategy, robust_policy);
}
@ -566,12 +580,15 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
{
if (boost::size(linestring) > 1)
{
Linestring simplified;
geometry::simplify(linestring, simplified, distance.simplify_distance());
collection.start_new_ring();
base::iterate(collection, 0, boost::begin(linestring), boost::end(linestring),
base::iterate(collection, 0, boost::begin(simplified), boost::end(simplified),
strategy::buffer::buffer_side_left,
distance, join_strategy, end_strategy, robust_policy);
base::iterate(collection, 1, boost::rbegin(linestring), boost::rend(linestring),
base::iterate(collection, 1, boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, join_strategy, end_strategy, robust_policy, true);
}

View File

@ -10,6 +10,7 @@
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
@ -47,6 +48,14 @@ public :
return m_left < 0 && m_right < 0;
}
inline CoordinateType simplify_distance() const
{
CoordinateType const left = geometry::math::abs(m_left);
CoordinateType const right = geometry::math::abs(m_right);
return (left < right ? left : right) / 1000.0;
}
private :
CoordinateType m_left;
CoordinateType m_right;

View File

@ -10,6 +10,7 @@
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
@ -44,6 +45,12 @@ public :
return m_distance < 0;
}
inline CoordinateType simplify_distance() const
{
return geometry::math::abs(m_distance) / 1000.0;
}
private :
CoordinateType m_distance;
};

View File

@ -77,6 +77,11 @@ static std::string const parcel2
static std::string const parcel3
= "POLYGON((120528.56 462115.62,120533.4 462072.1,120533.4 462072.01,120533.39 462071.93,120533.36 462071.86,120533.33 462071.78,120533.28 462071.72,120533.22 462071.66,120533.15 462071.61,120533.08 462071.58,120533 462071.55,120532.92 462071.54,120467.68 462068.66,120468.55 462059.04,120517.39 462062.87,120517.47 462062.87,120517.55 462062.86,120517.62 462062.83,120517.69 462062.79,120517.76 462062.74,120517.81 462062.68,120517.86 462062.62,120517.89 462062.55,120517.92 462062.47,120530.49 461998.63,120530.5 461998.55,120530.49 461998.47,120530.47 461998.39,120530.44 461998.31,120530.4 461998.24,120530.35 461998.18,120530.28 461998.13,120530.21 461998.09,120530.13 461998.06,120482.19 461984.63,120485 461963.14,120528.2 461950.66,120528.28 461950.63,120528.35 461950.59,120528.42 461950.53,120528.47 461950.47,120528.51 461950.4,120528.54 461950.32,120528.56 461950.24,120528.56 461950.15,120528.55 461950.07,120528.53 461949.99,120528.49 461949.92,120528.44 461949.85,120497.49 461915.03,120497.43 461914.98,120497.37 461914.93,120497.3 461914.9,120497.23 461914.88,120497.15 461914.86,120424.61 461910.03,120424.53 461910.03,120424.45 461910.05,120424.37 461910.07,120424.3 461910.11,120424.24 461910.16,120424.18 461910.22,120424.14 461910.29,120424.11 461910.37,120424.09 461910.45,120424.08 461910.53,120424.08 461967.59,120424.08 461967.67,120424.1 461967.75,120424.14 461967.82,120424.18 461967.89,120424.23 461967.95,120424.3 461968,120424.37 461968.04,120424.44 461968.07,120424.52 461968.09,120473.31 461973.83,120469.63 461993.16,120399.48 461986.43,120399.4 461986.43,120399.32 461986.44,120399.25 461986.47,120399.17 461986.5,120399.11 461986.55,120399.05 461986.61,120399.01 461986.67,120398.97 461986.74,120398.95 461986.82,120398.93 461986.9,120394.1 462057.5,120394.1 462057.58,120394.11 462057.66,120394.14 462057.74,120394.18 462057.81,120394.23 462057.87,120394.29 462057.93,120394.35 462057.97,120394.43 462058,120394.5 462058.03,120394.58 462058.03,120458.74 462059.95,120455.16 462072.48,120396.57 462067.68,120396.49 462067.68,120396.4 462067.69,120396.32 462067.72,120396.25 462067.76,120396.18 462067.82,120396.13 462067.88,120396.08 462067.96,120396.05 462068.04,120396.03 462068.12,120392.17 462103.9,120392.16 462103.99,120392.18 462104.07,120392.2 462104.15,120392.24 462104.22,120392.29 462104.29,120392.35 462104.35,120392.42 462104.4,120392.5 462104.43,120392.58 462104.45,120392.66 462104.46,120393.63 462104.46,120393.63 462103.46,120393.22 462103.46,120396.98 462068.71,120455.49 462073.51,120455.57 462073.51,120455.66 462073.49,120455.74 462073.46,120455.81 462073.42,120455.88 462073.37,120455.93 462073.3,120455.98 462073.23,120456.01 462073.15,120459.88 462059.61,120459.89 462059.52,120459.9 462059.44,120459.88 462059.36,120459.86 462059.28,120459.82 462059.21,120459.77 462059.14,120459.72 462059.08,120459.65 462059.04,120459.57 462059,120459.49 462058.98,120459.41 462058.97,120395.13 462057.05,120399.9 461987.48,120469.99 461994.2,120470.07 461994.2,120470.15 461994.19,120470.23 461994.16,120470.3 461994.13,120470.37 461994.08,120470.42 461994.02,120470.47 461993.95,120470.5 461993.88,120470.53 461993.8,120474.4 461973.48,120474.4 461973.4,120474.4 461973.32,120474.38 461973.24,120474.35 461973.16,120474.31 461973.09,120474.25 461973.03,120474.19 461972.98,120474.12 461972.94,120474.04 461972.91,120473.96 461972.9,120425.08 461967.14,120425.08 461911.06,120496.88 461915.85,120527.16 461949.92,120484.4 461962.27,120484.33 461962.3,120484.25 461962.35,120484.19 461962.4,120484.14 461962.46,120484.09 461962.53,120484.06 461962.61,120484.05 461962.69,120481.14 461984.93,120481.14 461985.01,120481.15 461985.09,120481.17 461985.17,120481.2 461985.24,120481.25 461985.31,120481.3 461985.36,120481.36 461985.41,120481.43 461985.45,120481.51 461985.48,120529.42 461998.9,120517.02 462061.84,120468.14 462058,120468.05 462058,120467.97 462058.02,120467.89 462058.05,120467.81 462058.09,120467.75 462058.15,120467.69 462058.22,120467.65 462058.29,120467.62 462058.37,120467.6 462058.46,120466.64 462069.1,120466.63 462069.18,120466.65 462069.26,120466.67 462069.33,120466.71 462069.4,120466.76 462069.47,120466.81 462069.53,120466.88 462069.57,120466.95 462069.61,120467.03 462069.63,120467.11 462069.64,120532.34 462072.52,120527.62 462115.03,120391.73 462106.36,120391.66 462107.36,120528.03 462116.06,120528.12 462116.06,120528.2 462116.04,120528.28 462116.02,120528.35 462115.97,120528.42 462115.92,120528.47 462115.85,120528.51 462115.78,120528.54 462115.7,120528.56 462115.62))";
static std::string const parcel3_bend // of parcel_3 - clipped
= "POLYGON((120399.40000152588 461986.43000030518, 120399.47999954224 461986.43000030518, 120403 461986.76769953477, 120403 461987.777217312, 120399.90000152588 461987.47999954224, 120399.72722010587 461990, 120398.71791817161 461990, 120398.93000030518 461986.90000152588, 120398.95000076294 461986.81999969482, 120398.9700012207 461986.74000167847, 120399.00999832153 461986.66999816895, 120399.04999923706 461986.61000061035, 120399.11000061035 461986.54999923706, 120399.16999816895 461986.5, 120399.25 461986.4700012207, 120399.31999969482 461986.43999862671, 120399.40000152588 461986.43000030518))";
template <typename P>
void test_all()
{
@ -266,26 +271,30 @@ void test_all()
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel1_10", parcel1, 7571.39121246337891, 10.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel1_10", parcel1, 8207.45314788818359, 10.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel1_20", parcel1, 11648.3068237304688, 20.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel1_20", parcel1, 14173.9223403930664, 20.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel1_30", parcel1, 16350.6157989501953, 30.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel1_30", parcel1, 22023.4705047607422, 30.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel1_20", parcel1, 11648.0537185668945, 20.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel1_20", parcel1, 14184.0223083496094, 20.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel1_30", parcel1, 16350.3611068725586, 30.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel1_30", parcel1, 22046.5098342895508, 30.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel2_10", parcel2, 5000.85063171386719, 10.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel2_10", parcel2, 5091.14096832275391, 10.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel2_10", parcel2, 5091.12226867675781, 10.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel2_20", parcel2, 9049.60844421386719, 20.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel2_20", parcel2, 9410.69154357910156, 20.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel2_30", parcel2, 13726.2614288330078, 30.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel2_30", parcel2, 14538.8463592529297, 30.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel2_30", parcel2, 13726.3790588378906, 30.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel2_30", parcel2, 14535.2319564819336, 30.0);
test_one<polygon_type, buf::join_round, buf::end_flat, polygon_type>("parcel3_10", parcel3, 19992.6824035644531, 10.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel3_10", parcel3, 20024.5579376220703, 10.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel3_20", parcel3, 34505.0746192932129, 20.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel3_20", parcel3, 34633.2606201171875, 20.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel3_30", parcel3, 45261.4196014404297, 30.0);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel3_30", parcel3, 45567.3875694274902, 30.0);
test_one<polygon_type, buf::join_round, buf::end_flat, polygon_type>("parcel3_bend_10", parcel3_bend, 155.6188, 5.0);
test_one<polygon_type, buf::join_round, buf::end_flat, polygon_type>("parcel3_bend_10", parcel3_bend, 458.4187, 10.0);
test_one<polygon_type, buf::join_round, buf::end_flat, polygon_type>("parcel3_bend_10", parcel3_bend, 917.9747, 15.0);
test_one<polygon_type, buf::join_round, buf::end_flat, polygon_type>("parcel3_bend_10", parcel3_bend, 1534.4795, 20.0);
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel3_10", parcel3, 99, 10.0);
#endif
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel3_10", parcel3, 20022.4271087646484, 10.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel3_20", parcel3, 34504.8032569885254, 20.0, -999, false);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel3_20", parcel3, 34615.6553726196289, 20.0);
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("parcel3_30", parcel3, 45263.0166702270508, 30.0, -999, false);
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("parcel3_30", parcel3, 45506.1910133361816, 30.0);
// Negative buffers making polygons smaller
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("simplex", simplex, 7.04043, -0.5);

View File

@ -21,6 +21,7 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/buffer.hpp>
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/union.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
@ -479,6 +480,7 @@ void test_one(std::string const& caseid, std::string const& wkt,
namespace bg = boost::geometry;
Geometry g;
bg::read_wkt(wkt, g);
bg::correct(g);
#ifdef BOOST_GEOMETRY_CHECK_WITH_POSTGIS