1 | #pragma once |
2 | |
3 | #ifdef DEBUG |
4 | #include <iostream> |
5 | #include <sstream> |
6 | #endif |
7 | |
8 | #include <queue> |
9 | |
10 | #include <mapbox/geometry/wagyu/bound.hpp> |
11 | |
12 | namespace mapbox { |
13 | namespace geometry { |
14 | namespace wagyu { |
15 | |
16 | template <typename T> |
17 | struct local_minimum { |
18 | bound<T> left_bound; |
19 | bound<T> right_bound; |
20 | T y; |
21 | bool minimum_has_horizontal; |
22 | |
23 | local_minimum(bound<T>&& left_bound_, bound<T>&& right_bound_, T y_, bool has_horz_) |
24 | : left_bound(std::move(left_bound_)), |
25 | right_bound(std::move(right_bound_)), |
26 | y(y_), |
27 | minimum_has_horizontal(has_horz_) { |
28 | } |
29 | }; |
30 | |
31 | template <typename T> |
32 | using local_minimum_list = std::deque<local_minimum<T>>; |
33 | |
34 | template <typename T> |
35 | using local_minimum_itr = typename local_minimum_list<T>::iterator; |
36 | |
37 | template <typename T> |
38 | using local_minimum_ptr = local_minimum<T>*; |
39 | |
40 | template <typename T> |
41 | using local_minimum_ptr_list = std::vector<local_minimum_ptr<T>>; |
42 | |
43 | template <typename T> |
44 | using local_minimum_ptr_list_itr = typename local_minimum_ptr_list<T>::iterator; |
45 | |
46 | template <typename T> |
47 | struct local_minimum_sorter { |
48 | inline bool operator()(local_minimum_ptr<T> const& locMin1, |
49 | local_minimum_ptr<T> const& locMin2) { |
50 | if (locMin2->y == locMin1->y) { |
51 | return locMin2->minimum_has_horizontal != locMin1->minimum_has_horizontal && |
52 | locMin1->minimum_has_horizontal; |
53 | } |
54 | return locMin2->y < locMin1->y; |
55 | } |
56 | }; |
57 | |
58 | #ifdef DEBUG |
59 | |
60 | template <class charT, class traits, typename T> |
61 | inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out, |
62 | const local_minimum<T>& lm) { |
63 | out << " Local Minimum:" << std::endl; |
64 | out << " y: " << lm.y << std::endl; |
65 | if (lm.minimum_has_horizontal) { |
66 | out << " minimum_has_horizontal: true" << std::endl; |
67 | } else { |
68 | out << " minimum_has_horizontal: false" << std::endl; |
69 | } |
70 | out << " left_bound: " << std::endl; |
71 | out << lm.left_bound << std::endl; |
72 | out << " right_bound: " << std::endl; |
73 | out << lm.right_bound << std::endl; |
74 | return out; |
75 | } |
76 | |
77 | template <class charT, class traits, typename T> |
78 | inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out, |
79 | const local_minimum_ptr_list<T>& lms) { |
80 | for (auto const& lm : lms) { |
81 | out << *lm; |
82 | } |
83 | return out; |
84 | } |
85 | |
86 | template <typename T> |
87 | std::string output_all_edges(local_minimum_ptr_list<T> const& lms) { |
88 | std::ostringstream out; |
89 | out << "[" ; |
90 | bool first = true; |
91 | for (auto const& lm : lms) { |
92 | for (auto const& e : lm->left_bound.edges) { |
93 | if (first) { |
94 | first = false; |
95 | } else { |
96 | out << "," ; |
97 | } |
98 | out << "[[" << e.bot.x << "," << e.bot.y << "],[" ; |
99 | out << e.top.x << "," << e.top.y << "]]" ; |
100 | } |
101 | for (auto const& e : lm->right_bound.edges) { |
102 | if (first) { |
103 | first = false; |
104 | } else { |
105 | out << "," ; |
106 | } |
107 | out << "[[" << e.bot.x << "," << e.bot.y << "],[" ; |
108 | out << e.top.x << "," << e.top.y << "]]" ; |
109 | } |
110 | } |
111 | out << "]" ; |
112 | return out.str(); |
113 | } |
114 | |
115 | #endif |
116 | } |
117 | } |
118 | } |
119 | |