1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
// Boost.Geometry
// Copyright (c) 2024 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2019-2024.
// Modifications copyright (c) 2019-2024 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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)
#include <geometry_test_common.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/optional.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
namespace bg = boost::geometry;
#if defined(TEST_WITH_SVG)
#include "test_buffer_svg.hpp"
#endif
// A point with extra info, such that
// - it can influence the buffer with dynamically (input)
// - it can receive the side at which the buffer was (output)
struct specific_point
{
double x{0.0};
double y{0.0};
double distance_left{0.0};
double distance_right{0.0};
boost::optional<bg::strategy::buffer::buffer_side_selector> side{};
};
BOOST_GEOMETRY_REGISTER_POINT_2D(specific_point, double, cs::cartesian, x, y)
struct specific_buffer_side_strategy
{
bool equidistant() const
{
return true;
}
template <typename Point, typename OutputRange, typename DistanceStrategy>
bg::strategy::buffer::result_code apply(Point const& input_p1, Point const& input_p2,
bg::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance,
OutputRange &output_range) const
{
const auto result =
bg::strategy::buffer::side_straight::apply(input_p1, input_p2, side, distance, output_range);
for (auto& point : output_range)
{
point.side = side;
}
return result;
}
};
struct specific_buffer_distance_strategy
{
/// Returns the distance-value.
template <typename Point>
double apply(Point const& p, Point const& q,
bg::strategy::buffer::buffer_side_selector side) const
{
return bg::strategy::buffer::buffer_side_left == side
? std::max(p.distance_left, q.distance_left)
: std::max(p.distance_right, q.distance_right);
}
bool negative() const
{
return false;
}
bool empty(bg::strategy::buffer::buffer_side_selector) const
{
return false;
}
/// Returns the max distance distance up to the buffer will reach.
template <typename JoinStrategy, typename EndStrategy>
double max_distance(JoinStrategy const &, EndStrategy const &) const
{
constexpr double unit_buffer_width{3.0};
return 6.0 * unit_buffer_width;
}
/// Returns the distance at which the input is simplified before the buffer process.
double simplify_distance() const
{
constexpr double unit_buffer_width{3.0};
return unit_buffer_width / 1000.0;
}
};
void test_buffer(std::string const& caseid, std::string const& wkt, std::vector<double> const& widths, double expected_area)
{
using ls_t = boost::geometry::model::linestring<specific_point>;
using mls_t = boost::geometry::model::multi_linestring<ls_t>;
using polygon_t = boost::geometry::model::polygon<specific_point>;
mls_t mls;
boost::geometry::read_wkt(wkt, mls);
if (mls.size() != widths.size())
{
throw std::runtime_error("There should be correct widths");
}
using point_type = specific_point;
using strategy_t = bg::strategies::buffer::services::default_strategy<
mls_t>::type;
strategy_t strategy;
#if defined(TEST_WITH_SVG)
bg::model::box<point_type> envelope;
bg::envelope(mls, envelope, strategy);
buffer_svg_mapper<point_type> buffer_mapper(caseid);
std::ostringstream filename;
filename << "/tmp/buffer_variable_width_" << caseid << ".svg";
std::ofstream svg(filename.str().c_str());
typedef bg::svg_mapper<point_type> mapper_type;
mapper_type mapper(svg, 1000, 800);
svg_visitor<mapper_type, bg::model::box<point_type>> visitor(mapper);
// Set the SVG boundingbox, with a margin. The margin is necessary because
// drawing is already started before the buffer is finished. It is not
// possible to "add" the buffer (unless we buffer twice).
buffer_mapper.prepare(mapper, visitor, envelope, 2.0);
#else
bg::detail::buffer::visit_pieces_default_policy visitor;
#endif
for (std::size_t i = 0; i < mls.size(); i++)
{
for (auto& point : mls[i])
{
point.distance_left = widths[i];
point.distance_right = widths[i];
}
}
specific_buffer_side_strategy buffer_side_strategy;
specific_buffer_distance_strategy distance_strategy;
boost::geometry::strategy::buffer::join_miter join_strategy;
boost::geometry::strategy::buffer::end_flat end_strategy;
boost::geometry::strategy::buffer::point_circle point_strategy;
boost::geometry::model::multi_polygon<polygon_t> result;
boost::geometry::detail::buffer::buffer_inserter
<
polygon_t
>(mls,
std::back_inserter(result),
distance_strategy, buffer_side_strategy, join_strategy,
end_strategy, point_strategy,
strategy,
visitor);
#if defined(TEST_WITH_SVG)
buffer_mapper.map_input_output(mapper, mls, result, false);
#endif
std::cout << caseid << " : " << boost::geometry::area(result) << std::endl;
BOOST_CHECK_CLOSE_FRACTION(boost::geometry::area(result), expected_area, 0.001);
}
int test_main(int argc, char **argv)
{
test_buffer("case1", "MULTILINESTRING((-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,18.00000000002045652536253328435122966766357421875 10.4999999997948947338954894803464412689208984375),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,17.99999999995061017443731543608009815216064453125 -4.5000000001943778471513724070973694324493408203125),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,11.99999999996175148453403380699455738067626953125 -10.49999999983214848953139153309166431427001953125))",
{4.5, 1.5, 1.5}, 304.294);
test_buffer("case2", "MULTILINESTRING((-18.00000000002045652536253328435122966766357421875 10.4999999997948929575386500800959765911102294921875,-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,17.99999999995061017443731543608009815216064453125 -4.5000000001943778471513724070973694324493408203125),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,11.99999999996175148453403380699455738067626953125 -10.49999999983214848953139153309166431427001953125))",
{6.0, 1.5, 1.5}, 319.767);
test_buffer("case3", "MULTILINESTRING((-18.00000000002045652536253328435122966766357421875 10.4999999997948929575386500800959765911102294921875,-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,18.00000000002045652536253328435122966766357421875 10.4999999997948947338954894803464412689208984375),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,11.99999999996175148453403380699455738067626953125 -10.49999999983214848953139153309166431427001953125))",
{6.0, 4.5, 1.5}, 429.831);
test_buffer("case4", "MULTILINESTRING((-18.00000000002045652536253328435122966766357421875 10.4999999997948929575386500800959765911102294921875,-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,18.00000000002045652536253328435122966766357421875 10.4999999997948947338954894803464412689208984375),(-2.99999999998012700785920969792641699314117431640625 10.4999999997948929575386500800959765911102294921875,17.99999999995061017443731543608009815216064453125 -4.5000000001943778471513724070973694324493408203125))",
{6.0, 4.5, 1.5}, 423.195);
return 0;
}
|