mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-08 23:02:09 +00:00
Merge branch 'develop' of github.com:boostorg/geometry into develop
This commit is contained in:
@@ -14,12 +14,14 @@
|
||||
static std::string const simplex = "MULTIPOINT((5 5),(7 7))";
|
||||
static std::string const three = "MULTIPOINT((5 8),(9 8),(7 11))";
|
||||
|
||||
// Generates error (extra polygon on top of rest) at distance 14.0:
|
||||
// Generated error (extra polygon on top of rest) at distance 14.0:
|
||||
static std::string const multipoint_a = "MULTIPOINT((39 44),(38 37),(41 29),(15 33),(58 39))";
|
||||
|
||||
// Just one with holes at distance ~ 15
|
||||
static std::string const multipoint_b = "MULTIPOINT((5 56),(98 67),(20 7),(58 60),(10 4),(75 68),(61 68),(75 62),(92 26),(74 6),(67 54),(20 43),(63 30),(45 7))";
|
||||
|
||||
// Grid, U-form, generates error for square point at 0.54 (top cells to control rescale)
|
||||
static std::string const grid_a = "MULTIPOINT(5 0,6 0,7 0, 5 1,7 1, 0 13,8 13)";
|
||||
|
||||
template <bool Clockwise, typename P>
|
||||
void test_all()
|
||||
@@ -46,6 +48,29 @@ void test_all()
|
||||
test_one<multi_point_type, polygon>("multipoint_b", multipoint_b, join_miter, end_flat, 7109.88, 15.0, 15.0);
|
||||
test_one<multi_point_type, polygon>("multipoint_b1", multipoint_b, join_miter, end_flat, 6911.89, 14.7, 14.7);
|
||||
test_one<multi_point_type, polygon>("multipoint_b2", multipoint_b, join_miter, end_flat, 7174.79, 15.1, 15.1);
|
||||
|
||||
|
||||
// Grid tests
|
||||
{
|
||||
bg::strategy::buffer::point_square point_strategy;
|
||||
bg::strategy::buffer::side_straight side_strategy;
|
||||
|
||||
typedef bg::strategy::buffer::distance_symmetric
|
||||
<
|
||||
typename bg::coordinate_type<P>::type
|
||||
> distance_strategy;
|
||||
|
||||
test_with_custom_strategies<multi_point_type, polygon>("grid_a50",
|
||||
grid_a, join_miter, end_flat,
|
||||
distance_strategy(0.5), side_strategy, point_strategy, 7.0);
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
|
||||
test_with_custom_strategies<multi_point_type, polygon>("grid_a54",
|
||||
grid_a, join_miter, end_flat,
|
||||
distance_strategy(0.54), side_strategy, point_strategy, 99);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
template
|
||||
|
||||
@@ -16,8 +16,19 @@
|
||||
|
||||
#if defined(TEST_WITH_SVG)
|
||||
#define BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS
|
||||
|
||||
// Uncomment next lines if you want to have a zoomed view
|
||||
// #define BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
|
||||
// If possible define box before including this unit with the right view
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
# ifndef BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX
|
||||
# define BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX "BOX(0 0,100 100)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // TEST_WITH_SVG
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <geometry_test_common.hpp>
|
||||
|
||||
@@ -26,24 +37,20 @@
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/buffer.hpp>
|
||||
#include <boost/geometry/algorithms/correct.hpp>
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/is_valid.hpp>
|
||||
#include <boost/geometry/algorithms/union.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/geometries.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/strategies.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
|
||||
|
||||
|
||||
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||
|
||||
|
||||
@@ -91,9 +98,13 @@ void post_map(Geometry const& geometry, Mapper& mapper, RescalePolicy const& res
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SvgMapper, typename Tag>
|
||||
template <typename SvgMapper, typename Box, typename Tag>
|
||||
struct svg_visitor
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
Box m_alternate_box;
|
||||
#endif
|
||||
|
||||
class si
|
||||
{
|
||||
private :
|
||||
@@ -134,6 +145,13 @@ struct svg_visitor
|
||||
for (typename boost::range_iterator<Turns const>::type it =
|
||||
boost::begin(turns); it != boost::end(turns); ++it)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
if (bg::disjoint(it->point, m_alternate_box))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_good = true;
|
||||
char color = 'g';
|
||||
std::string fill = "fill:rgb(0,255,0);";
|
||||
@@ -242,6 +260,12 @@ struct svg_visitor
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
if (bg::disjoint(corner, m_alternate_box))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (do_pieces)
|
||||
{
|
||||
@@ -311,11 +335,13 @@ struct svg_visitor
|
||||
map_pieces(collection.m_pieces, collection.offsetted_rings, true, true);
|
||||
map_turns(collection.m_turns, true, false);
|
||||
}
|
||||
#if !defined(BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX)
|
||||
if (phase == 1)
|
||||
{
|
||||
// map_traversed_rings(collection.traversed_rings);
|
||||
// map_offsetted_rings(collection.offsetted_rings);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -451,6 +477,18 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
typedef bg::svg_mapper<point_type> mapper_type;
|
||||
mapper_type mapper(svg, 1000, 1000);
|
||||
|
||||
svg_visitor<mapper_type, bg::model::box<point_type>, tag> visitor(mapper);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
// Create a zoomed-in view
|
||||
bg::model::box<point_type> alternate_box;
|
||||
bg::read_wkt(BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX, alternate_box);
|
||||
mapper.add(alternate_box);
|
||||
|
||||
// Take care non-visible elements are skipped
|
||||
visitor.m_alternate_box = alternate_box;
|
||||
#else
|
||||
|
||||
{
|
||||
bg::model::box<point_type> box = envelope;
|
||||
if (distance_strategy.negative())
|
||||
@@ -463,8 +501,8 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
}
|
||||
mapper.add(box);
|
||||
}
|
||||
#endif
|
||||
|
||||
svg_visitor<mapper_type, tag> visitor(mapper);
|
||||
#else
|
||||
bg::detail::buffer::visit_pieces_default_policy visitor;
|
||||
#endif
|
||||
@@ -479,7 +517,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
rescale_policy_type rescale_policy
|
||||
= bg::get_rescale_policy<rescale_policy_type>(envelope);
|
||||
|
||||
std::vector<GeometryOut> buffered;
|
||||
bg::model::multi_polygon<GeometryOut> buffered;
|
||||
|
||||
bg::detail::buffer::buffer_inserter<GeometryOut>(geometry,
|
||||
std::back_inserter(buffered),
|
||||
@@ -491,19 +529,12 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
rescale_policy,
|
||||
visitor);
|
||||
|
||||
typename bg::default_area_result<GeometryOut>::type area = 0;
|
||||
BOOST_FOREACH(GeometryOut const& polygon, buffered)
|
||||
{
|
||||
area += bg::area(polygon);
|
||||
}
|
||||
typename bg::default_area_result<GeometryOut>::type area = bg::area(buffered);
|
||||
|
||||
//std::cout << caseid << " " << distance_left << std::endl;
|
||||
//std::cout << "INPUT: " << bg::wkt(geometry) << std::endl;
|
||||
//std::cout << "OUTPUT: " << area << std::endl;
|
||||
//BOOST_FOREACH(GeometryOut const& polygon, buffered)
|
||||
//{
|
||||
// std::cout << bg::wkt(polygon) << std::endl;
|
||||
//}
|
||||
//std::cout << bg::wkt(buffered) << std::endl;
|
||||
|
||||
|
||||
if (expected_area > -0.1)
|
||||
@@ -521,18 +552,26 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
{
|
||||
// Be sure resulting polygon does not contain
|
||||
// self-intersections
|
||||
BOOST_FOREACH(GeometryOut const& polygon, buffered)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE
|
||||
(
|
||||
! bg::detail::overlay::has_self_intersections(polygon,
|
||||
rescale_policy, false),
|
||||
complete.str() << " output is self-intersecting. "
|
||||
);
|
||||
}
|
||||
BOOST_CHECK_MESSAGE
|
||||
(
|
||||
! bg::detail::overlay::has_self_intersections(buffered,
|
||||
rescale_policy, false),
|
||||
complete.str() << " output is self-intersecting. "
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_IS_VALID
|
||||
if (! bg::is_valid(buffered))
|
||||
{
|
||||
std::cout
|
||||
<< "NOT VALID: " << complete.str() << std::endl
|
||||
<< std::fixed << std::setprecision(16) << bg::wkt(buffered) << std::endl;
|
||||
}
|
||||
// BOOST_CHECK_MESSAGE(bg::is_valid(buffered) == true, complete.str() << " is not valid");
|
||||
// BOOST_CHECK_MESSAGE(bg::intersects(buffered) == false, complete.str() << " intersects");
|
||||
#endif
|
||||
|
||||
#if defined(TEST_WITH_SVG)
|
||||
bool const areal = boost::is_same
|
||||
<
|
||||
@@ -542,38 +581,46 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
// Map input geometry in green
|
||||
if (areal)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX_FOR_INPUT
|
||||
// Assuming input is areal
|
||||
bg::model::multi_polygon<GeometryOut> clipped;
|
||||
bg::intersection(geometry, alternate_box, clipped);
|
||||
mapper.map(clipped, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
|
||||
#else
|
||||
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: clip input points/linestring
|
||||
mapper.map(geometry, "opacity:0.5;stroke:rgb(0,128,0);stroke-width:10");
|
||||
}
|
||||
|
||||
// Map buffer in yellow (inflate) and with orange-dots (deflate)
|
||||
BOOST_FOREACH(GeometryOut const& polygon, buffered)
|
||||
{
|
||||
if (distance_strategy.negative())
|
||||
{
|
||||
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,192);stroke:rgb(255,128,0);stroke-width:3");
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3");
|
||||
}
|
||||
post_map(polygon, mapper, rescale_policy);
|
||||
}
|
||||
// Map buffer in yellow (inflate) and with orange-dots (deflate)
|
||||
std::string style = distance_strategy.negative()
|
||||
? "opacity:0.4;fill:rgb(255,255,192);stroke:rgb(255,128,0);stroke-width:3"
|
||||
: "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3";
|
||||
|
||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||
// Clip output multi-polygon with box
|
||||
bg::model::multi_polygon<GeometryOut> clipped;
|
||||
bg::intersection(buffered, alternate_box, clipped);
|
||||
mapper.map(clipped, style);
|
||||
#else
|
||||
mapper.map(buffered, style);
|
||||
#endif
|
||||
}
|
||||
post_map(buffered, mapper, rescale_policy);
|
||||
#endif // TEST_WITH_SVG
|
||||
|
||||
if (self_ip_count != NULL)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
BOOST_FOREACH(GeometryOut const& polygon, buffered)
|
||||
if (bg::detail::overlay::has_self_intersections(buffered,
|
||||
rescale_policy, false))
|
||||
{
|
||||
if (bg::detail::overlay::has_self_intersections(polygon,
|
||||
rescale_policy, false))
|
||||
{
|
||||
count += count_self_ips(polygon, rescale_policy);
|
||||
}
|
||||
count = count_self_ips(buffered, rescale_policy);
|
||||
}
|
||||
|
||||
*self_ip_count += count;
|
||||
@@ -708,7 +755,8 @@ void test_with_custom_strategies(std::string const& caseid,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
double expected_area)
|
||||
double expected_area,
|
||||
double tolerance = 0.01)
|
||||
{
|
||||
namespace bg = boost::geometry;
|
||||
Geometry g;
|
||||
@@ -719,7 +767,7 @@ void test_with_custom_strategies(std::string const& caseid,
|
||||
(caseid, g,
|
||||
join_strategy, end_strategy,
|
||||
distance_strategy, side_strategy, point_strategy,
|
||||
true, expected_area, 0.01, NULL);
|
||||
true, expected_area, tolerance, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
301
test/robustness/overlay/buffer/many_ring_buffer.cpp
Normal file
301
test/robustness/overlay/buffer/many_ring_buffer.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Unit Test
|
||||
|
||||
// Copyright (c) 2012-2014 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)
|
||||
|
||||
#define BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX_FOR_INPUT
|
||||
#define BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX "BOX(179 4, 180 5)"
|
||||
|
||||
|
||||
#include <test_buffer.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/difference.hpp>
|
||||
#include <boost/geometry/multi/geometries/multi_geometries.hpp>
|
||||
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/random/uniform_real.hpp>
|
||||
#include <boost/random/variate_generator.hpp>
|
||||
|
||||
|
||||
|
||||
const int point_count = 90; // points for a full circle
|
||||
|
||||
// Function to let buffer-distance depend on alpha, e.g.:
|
||||
inline double corrected_distance(double distance, double alpha)
|
||||
{
|
||||
return distance * 1.0 + 0.2 * sin(alpha * 6.0);
|
||||
}
|
||||
|
||||
class buffer_point_strategy_sample
|
||||
{
|
||||
public :
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename OutputRange,
|
||||
typename DistanceStrategy
|
||||
>
|
||||
void apply(Point const& point,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
OutputRange& output_range) const
|
||||
{
|
||||
double const distance = distance_strategy.apply(point, point,
|
||||
bg::strategy::buffer::buffer_side_left);
|
||||
|
||||
double const angle_increment = 2.0 * M_PI / double(point_count);
|
||||
|
||||
double alpha = 0;
|
||||
for (std::size_t i = 0; i <= point_count; i++, alpha -= angle_increment)
|
||||
{
|
||||
double const cd = corrected_distance(distance, alpha);
|
||||
|
||||
typename boost::range_value<OutputRange>::type output_point;
|
||||
bg::set<0>(output_point, bg::get<0>(point) + cd * cos(alpha));
|
||||
bg::set<1>(output_point, bg::get<1>(point) + cd * sin(alpha));
|
||||
output_range.push_back(output_point);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class buffer_join_strategy_sample
|
||||
{
|
||||
private :
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename DistanceType,
|
||||
typename RangeOut
|
||||
>
|
||||
inline void generate_points(Point const& vertex,
|
||||
Point const& perp1, Point const& perp2,
|
||||
DistanceType const& buffer_distance,
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
double dx1 = bg::get<0>(perp1) - bg::get<0>(vertex);
|
||||
double dy1 = bg::get<1>(perp1) - bg::get<1>(vertex);
|
||||
double dx2 = bg::get<0>(perp2) - bg::get<0>(vertex);
|
||||
double dy2 = bg::get<1>(perp2) - bg::get<1>(vertex);
|
||||
|
||||
// Assuming the corner is convex, angle2 < angle1
|
||||
double const angle1 = atan2(dy1, dx1);
|
||||
double angle2 = atan2(dy2, dx2);
|
||||
|
||||
while (angle2 > angle1)
|
||||
{
|
||||
angle2 -= 2 * M_PI;
|
||||
}
|
||||
|
||||
double const angle_increment = 2.0 * M_PI / double(point_count);
|
||||
double alpha = angle1 - angle_increment;
|
||||
|
||||
for (int i = 0; alpha >= angle2 && i < point_count; i++, alpha -= angle_increment)
|
||||
{
|
||||
double cd = corrected_distance(buffer_distance, alpha);
|
||||
|
||||
Point p;
|
||||
bg::set<0>(p, bg::get<0>(vertex) + cd * cos(alpha));
|
||||
bg::set<1>(p, bg::get<1>(vertex) + cd * sin(alpha));
|
||||
range_out.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
public :
|
||||
|
||||
template <typename Point, typename DistanceType, typename RangeOut>
|
||||
inline bool apply(Point const& ip, Point const& vertex,
|
||||
Point const& perp1, Point const& perp2,
|
||||
DistanceType const& buffer_distance,
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
generate_points(vertex, perp1, perp2, buffer_distance, range_out);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename NumericType>
|
||||
static inline NumericType max_distance(NumericType const& distance)
|
||||
{
|
||||
return distance;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class buffer_side_sample
|
||||
{
|
||||
public :
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename OutputRange,
|
||||
typename DistanceStrategy
|
||||
>
|
||||
static inline void apply(
|
||||
Point const& input_p1, Point const& input_p2,
|
||||
bg::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
OutputRange& output_range)
|
||||
{
|
||||
// Generate a block along (left or right of) the segment
|
||||
|
||||
double const dx = bg::get<0>(input_p2) - bg::get<0>(input_p1);
|
||||
double const dy = bg::get<1>(input_p2) - bg::get<1>(input_p1);
|
||||
|
||||
// For normalization [0,1] (=dot product d.d, sqrt)
|
||||
double const length = bg::math::sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (bg::math::equals(length, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate the normalized perpendicular p, to the left (ccw)
|
||||
double const px = -dy / length;
|
||||
double const py = dx / length;
|
||||
|
||||
// Both vectors perpendicular to input p1 and input p2 have same angle
|
||||
double const alpha = atan2(py, px);
|
||||
|
||||
double const d = distance.apply(input_p1, input_p2, side);
|
||||
|
||||
double const cd = corrected_distance(d, alpha);
|
||||
|
||||
output_range.resize(2);
|
||||
|
||||
bg::set<0>(output_range.front(), bg::get<0>(input_p1) + px * cd);
|
||||
bg::set<1>(output_range.front(), bg::get<1>(input_p1) + py * cd);
|
||||
bg::set<0>(output_range.back(), bg::get<0>(input_p2) + px * cd);
|
||||
bg::set<1>(output_range.back(), bg::get<1>(input_p2) + py * cd);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef TEST_WITH_SVG
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
void create_svg(std::string const& filename, Geometry1 const& original, Geometry2 const& buffer, std::string const& color)
|
||||
{
|
||||
typedef typename bg::point_type<Geometry1>::type point_type;
|
||||
std::ofstream svg(filename.c_str());
|
||||
|
||||
bg::svg_mapper<point_type> mapper(svg, 800, 800);
|
||||
mapper.add(buffer);
|
||||
|
||||
mapper.map(original, "fill-opacity:0.3;fill:rgb(255,0,0);stroke:rgb(0,0,0);stroke-width:1");
|
||||
|
||||
std::string style = "fill-opacity:0.3;fill:";
|
||||
style += color;
|
||||
style += ";stroke:rgb(0,0,0);stroke-width:1";
|
||||
mapper.map(buffer, style);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void test_many_rings(int imn, int jmx, int count,
|
||||
double expected_area_exterior,
|
||||
double expected_area_interior)
|
||||
{
|
||||
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
|
||||
typedef bg::model::polygon<point> polygon_type;
|
||||
typedef bg::model::multi_polygon<polygon_type> multi_polygon_type;
|
||||
|
||||
// Predefined strategies
|
||||
bg::strategy::buffer::distance_symmetric<double> distance_strategy(1.3);
|
||||
bg::strategy::buffer::end_flat end_strategy; // not effectively used
|
||||
|
||||
// Own strategies
|
||||
buffer_join_strategy_sample join_strategy;
|
||||
buffer_point_strategy_sample point_strategy;
|
||||
buffer_side_sample side_strategy;
|
||||
|
||||
// Declare output
|
||||
|
||||
bg::model::multi_point<point> mp;
|
||||
|
||||
// Use a bit of random disturbance in the otherwise too regular grid
|
||||
typedef boost::minstd_rand base_generator_type;
|
||||
base_generator_type generator(12345);
|
||||
boost::uniform_real<> random_range(0.0, 0.5);
|
||||
boost::variate_generator
|
||||
<
|
||||
base_generator_type&,
|
||||
boost::uniform_real<>
|
||||
> random(generator, random_range);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
double x = i * 3.0 + random();
|
||||
double y = j * 3.0 + random();
|
||||
//if (i > 30 && j < 30)
|
||||
if (i > imn && j < jmx)
|
||||
{
|
||||
point p(x, y);
|
||||
mp.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
multi_polygon_type many_rings;
|
||||
// Create the buffer of a multi-point
|
||||
bg::buffer(mp, many_rings,
|
||||
distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy);
|
||||
|
||||
bg::model::box<point> envelope;
|
||||
bg::envelope(many_rings, envelope);
|
||||
bg::buffer(envelope, envelope, 1.0);
|
||||
|
||||
multi_polygon_type many_interiors;
|
||||
bg::difference(envelope, many_rings, many_interiors);
|
||||
|
||||
#ifdef TEST_WITH_SVG
|
||||
create_svg("/tmp/many_interiors.svg", mp, many_interiors, "rgb(51,51,153)");
|
||||
create_svg("/tmp/buffer.svg", mp, many_rings, "rgb(51,51,153)");
|
||||
#endif
|
||||
|
||||
bg::strategy::buffer::join_round join_round(100);
|
||||
bg::strategy::buffer::end_flat end_flat;
|
||||
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "many_rings_" << count;
|
||||
out << "_" << imn << "_" << jmx;
|
||||
std::ostringstream wkt;
|
||||
wkt << std::setprecision(12) << bg::wkt(many_rings);
|
||||
|
||||
boost::timer t;
|
||||
test_one<multi_polygon_type, polygon_type>(out.str(), wkt.str(), join_round, end_flat, expected_area_exterior, 0.3);
|
||||
std::cout << "Exterior " << count << " " << t.elapsed() << std::endl;
|
||||
}
|
||||
|
||||
return;
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "many_interiors_" << count;
|
||||
std::ostringstream wkt;
|
||||
wkt << std::setprecision(12) << bg::wkt(many_interiors);
|
||||
|
||||
boost::timer t;
|
||||
test_one<multi_polygon_type, polygon_type>(out.str(), wkt.str(), join_round, end_flat, expected_area_interior, 0.3);
|
||||
std::cout << "Interior " << count << " " << t.elapsed() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
{
|
||||
// test_many_rings(10, 795.70334, 806.7609);
|
||||
// test_many_rings(30, 7136.7098, 6174.4496);
|
||||
test_many_rings(30, 30, 70, 38764.2721, 31910.3280);
|
||||
// for (int i = 30; i < 60; i++)
|
||||
// {
|
||||
// for (int j = 5; j <= 30; j++)
|
||||
// {
|
||||
// test_many_rings(i, j, 70, 38764.2721, 31910.3280);
|
||||
// }
|
||||
// }
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user