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 
local_minimummapbox::geometry::wagyu::local_minimum23     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 {
operator ()mapbox::geometry::wagyu::local_minimum_sorter48     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>
operator <<(std::basic_ostream<charT,traits> & out,const local_minimum<T> & lm)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>
operator <<(std::basic_ostream<charT,traits> & out,const local_minimum_ptr_list<T> & lms)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>
output_all_edges(local_minimum_ptr_list<T> const & lms)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