forked from pcb2gcode/pcb2gcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bg_helpers.cpp
122 lines (108 loc) · 4.5 KB
/
bg_helpers.cpp
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
#include "eulerian_paths.hpp"
#ifdef GEOS_VERSION
#include <geos/operation/buffer/BufferOp.h>
#include "geos_helpers.hpp"
#endif // GEOS_VERSION
#include "bg_operators.hpp"
#include "bg_helpers.hpp"
namespace bg_helpers {
// The below implementations of buffer are similar to bg::buffer but
// always convert to floating-point before doing work, if needed, and
// convert back afterward, if needed. Also, they work if expand_by is
// 0, unlike bg::buffer.
const int points_per_circle = 32;
multi_polygon_type_fp buffer(multi_polygon_type_fp const & geometry_in, coordinate_type_fp expand_by) {
if (expand_by == 0 || geometry_in.size() == 0) {
return geometry_in;
}
#ifdef GEOS_VERSION
auto geos_in = to_geos(geometry_in);
return from_geos<multi_polygon_type_fp>(
std::unique_ptr<geos::geom::Geometry>(
geos::operation::buffer::BufferOp::bufferOp(geos_in.get(), expand_by, points_per_circle/4)));
#else
multi_polygon_type_fp geometry_out;
bg::buffer(geometry_in, geometry_out,
bg::strategy::buffer::distance_symmetric<coordinate_type_fp>(expand_by),
bg::strategy::buffer::side_straight(),
bg::strategy::buffer::join_round(points_per_circle),
bg::strategy::buffer::end_round(points_per_circle),
bg::strategy::buffer::point_circle(points_per_circle));
return geometry_out;
#endif
}
multi_polygon_type_fp buffer_miter(multi_polygon_type_fp const & geometry_in, coordinate_type_fp expand_by) {
if (expand_by == 0) {
return geometry_in;
} else {
multi_polygon_type_fp geometry_out;
bg::buffer(geometry_in, geometry_out,
bg::strategy::buffer::distance_symmetric<coordinate_type_fp>(expand_by),
bg::strategy::buffer::side_straight(),
bg::strategy::buffer::join_miter(expand_by),
bg::strategy::buffer::end_round(points_per_circle),
bg::strategy::buffer::point_circle(points_per_circle));
return geometry_out;
}
}
template<typename CoordinateType>
multi_polygon_type_fp buffer(polygon_type_fp const & geometry_in, CoordinateType expand_by) {
return buffer(multi_polygon_type_fp{geometry_in}, expand_by);
}
template multi_polygon_type_fp buffer(polygon_type_fp const&, double);
template<typename CoordinateType>
multi_polygon_type_fp buffer_miter(polygon_type_fp const & geometry_in, CoordinateType expand_by) {
return buffer_miter(multi_polygon_type_fp{geometry_in}, expand_by);
}
template<typename CoordinateType>
multi_polygon_type_fp buffer(linestring_type_fp const & geometry_in, CoordinateType expand_by) {
if (expand_by == 0) {
return {};
}
#ifdef GEOS_VERSION
auto geos_in = to_geos(geometry_in);
return from_geos<multi_polygon_type_fp>(
std::unique_ptr<geos::geom::Geometry>(
geos::operation::buffer::BufferOp::bufferOp(geos_in.get(), expand_by, points_per_circle/4)));
#else
multi_polygon_type_fp geometry_out;
bg::buffer(geometry_in, geometry_out,
bg::strategy::buffer::distance_symmetric<coordinate_type_fp>(expand_by),
bg::strategy::buffer::side_straight(),
bg::strategy::buffer::join_round(points_per_circle),
bg::strategy::buffer::end_round(points_per_circle),
bg::strategy::buffer::point_circle(points_per_circle));
return geometry_out;
#endif
}
template<typename CoordinateType>
multi_polygon_type_fp buffer(multi_linestring_type_fp const & geometry_in, CoordinateType expand_by) {
if (expand_by == 0 || geometry_in.size() == 0) {
return {};
}
// bg::buffer of multilinestring is broken in boost. Converting the
// multilinestring to non-intersecting paths seems to help.
multi_linestring_type_fp mls = eulerian_paths::make_eulerian_paths(geometry_in, true, true);
#ifdef GEOS_VERSION
auto geos_in = to_geos(mls);
return from_geos<multi_polygon_type_fp>(
std::unique_ptr<geos::geom::Geometry>(
geos::operation::buffer::BufferOp::bufferOp(geos_in.get(), expand_by, points_per_circle/4)));
#else
if (expand_by == 0) {
return {};
}
multi_polygon_type_fp ret;
for (const auto& ls : mls) {
ret = ret + buffer(ls, expand_by);
}
return ret;
#endif
}
template multi_polygon_type_fp buffer(const multi_linestring_type_fp&, double expand_by);
template<typename CoordinateType>
multi_polygon_type_fp buffer_miter(ring_type_fp const & geometry_in, CoordinateType expand_by) {
return buffer_miter(polygon_type_fp{geometry_in}, expand_by);
}
template multi_polygon_type_fp buffer_miter(ring_type_fp const&, double);
} // namespace bg_helpers