-
Notifications
You must be signed in to change notification settings - Fork 0
/
deberg.hpp
117 lines (92 loc) · 3.67 KB
/
deberg.hpp
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
#ifndef DEBERG_HPP
#define DEBERG_HPP
#include "tangent_splitter.hpp"
#include "point_distributor.hpp"
#include "shortcut_acceptor.hpp"
#include "monotone_decomposition.hpp"
#include <iostream>
template<typename PointFilterT>
class deberg
{
public:
deberg(const poly_line& in_line, std::vector<point>&& in_points)
: line(in_line)
, points(in_points)
{
}
std::vector<shortcut> operator()() const
{
std::vector<shortcut> shortcuts;
monotone_decomposition decomposition;
auto monotone_lines = decomposition(line);
auto line_points = get_line_points(monotone_lines, line.coordinates);
for (auto i = 0u; i < monotone_lines.size(); ++i)
{
const auto& m = monotone_lines[i];
PointFilterT filter(line.coordinates.begin() + m.begin_idx, line.coordinates.begin() + m.end_idx, i);
auto filtered_points = filter(line_points);
filtered_points.insert(filtered_points.end(), points.begin(), points.end());
auto transformed_points = transform_points(m.mono, filtered_points);
auto monotone_shortcuts = simplify_monotone_line(m.line, transformed_points);
// fix up indices
for (auto& s : monotone_shortcuts)
{
s.first += m.begin_idx;
s.last += m.begin_idx;
BOOST_ASSERT(s.first < m.end_idx);
BOOST_ASSERT(s.last < m.end_idx);
}
shortcuts.insert(shortcuts.end(), monotone_shortcuts.begin(), monotone_shortcuts.end());
}
return shortcuts;
}
private:
std::vector<point> get_line_points(const std::vector<monotone_decomposition::monotone_subpath>& lines, const std::vector<coordinate>& coordinates) const
{
std::vector<point> line_points;
auto line_idx = 0u;
for (auto i = 0u; i < coordinates.size(); ++i)
{
if (i == lines[line_idx].end_idx)
{
++line_idx;
BOOST_ASSERT(line_idx < lines.size());
}
line_points.push_back({line_idx, i, coordinates[i]});
}
return line_points;
}
std::vector<point> transform_points(geometry::monoticity mono, const std::vector<point>& points) const
{
std::vector<point> transformed_points;
transformed_points.reserve(points.size());
// FIXME this is unecessary copying, we can do this nicer
std::vector<coordinate> temp_coordinates(points.size());
std::transform(points.begin(), points.end(), temp_coordinates.begin(), [](const point& p) { return p.location; });
geometry::make_x_monotone_increasing(mono, temp_coordinates);
for (auto i = 0u; i < points.size(); ++i)
{
transformed_points.push_back(point {points[i].line_id, points[i].id, temp_coordinates[i]});
}
return transformed_points;
}
std::vector<shortcut> simplify_monotone_line(const poly_line& l, const std::vector<point>& points) const
{
tangent_splitter splitter(l);
point_distributor distributor(l, points);
shortcut_acceptor acceptor(l);
std::vector<shortcut> all_shortcuts;
// note: no edges after last coordinate
for (auto i = 0u; i < l.coordinates.size() - 1; ++i)
{
auto tangents = splitter(i);
auto assignments = distributor(i, tangents);
auto partial_shortcuts = acceptor(i, tangents, assignments);
all_shortcuts.insert(all_shortcuts.end(), partial_shortcuts.begin(), partial_shortcuts.end());
}
return all_shortcuts;
}
const poly_line& line;
std::vector<point> points;
};
#endif