1 #pragma once
2 
3 #include <cmath>
4 #include <limits>
5 #include <list>
6 
7 #include <mapbox/geometry/point.hpp>
8 #include <mapbox/geometry/wagyu/config.hpp>
9 #include <mapbox/geometry/wagyu/util.hpp>
10 
11 #ifdef DEBUG
12 #include <iostream>
13 #endif
14 
15 namespace mapbox {
16 namespace geometry {
17 namespace wagyu {
18 
19 template <typename T>
20 struct bound;
21 
22 template <typename T>
23 using bound_ptr = bound<T>*;
24 
25 template <typename T>
26 struct edge {
27     mapbox::geometry::point<T> bot;
28     mapbox::geometry::point<T> top;
29     double dx;
30 
edgemapbox::geometry::wagyu::edge31     edge(edge<T>&& e) noexcept : bot(std::move(e.bot)), top(std::move(e.top)), dx(std::move(e.dx)) {
32     }
33 
operator =mapbox::geometry::wagyu::edge34     edge& operator=(edge<T>&& e) noexcept {
35         bot = std::move(e.bot);
36         top = std::move(e.top);
37         dx = std::move(e.dx);
38         return *this;
39     }
40 
41     template <typename T2>
edgemapbox::geometry::wagyu::edge42     edge(mapbox::geometry::point<T2> const& current,
43          mapbox::geometry::point<T2> const& next_pt) noexcept
44         : bot(static_cast<T>(current.x), static_cast<T>(current.y)),
45           top(static_cast<T>(current.x), static_cast<T>(current.y)),
46           dx(0.0) {
47         if (current.y >= next_pt.y) {
48             top = mapbox::geometry::point<T>(static_cast<T>(next_pt.x), static_cast<T>(next_pt.y));
49         } else {
50             bot = mapbox::geometry::point<T>(static_cast<T>(next_pt.x), static_cast<T>(next_pt.y));
51         }
52         double dy = static_cast<double>(top.y - bot.y);
53         if (value_is_zero(dy)) {
54             dx = std::numeric_limits<double>::infinity();
55         } else {
56             dx = static_cast<double>(top.x - bot.x) / dy;
57         }
58     }
59 };
60 
61 template <typename T>
62 using edge_ptr = edge<T>*;
63 
64 template <typename T>
65 using edge_list = std::vector<edge<T>>;
66 
67 template <typename T>
68 using edge_list_itr = typename edge_list<T>::iterator;
69 
70 template <typename T>
slopes_equal(edge<T> const & e1,edge<T> const & e2)71 bool slopes_equal(edge<T> const& e1, edge<T> const& e2) {
72     return (e1.top.y - e1.bot.y) * (e2.top.x - e2.bot.x) ==
73            (e1.top.x - e1.bot.x) * (e2.top.y - e2.bot.y);
74 }
75 
76 template <typename T>
is_horizontal(edge<T> const & e)77 inline bool is_horizontal(edge<T> const& e) {
78     return std::isinf(e.dx);
79 }
80 
81 template <typename T>
get_current_x(edge<T> const & edge,const T current_y)82 inline double get_current_x(edge<T> const& edge, const T current_y) {
83     if (current_y == edge.top.y) {
84         return static_cast<double>(edge.top.x);
85     } else {
86         return static_cast<double>(edge.bot.x) +
87                edge.dx * static_cast<double>(current_y - edge.bot.y);
88     }
89 }
90 
91 #ifdef DEBUG
92 
93 template <class charT, class traits, typename T>
operator <<(std::basic_ostream<charT,traits> & out,const edge<T> & e)94 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
95                                                      const edge<T>& e) {
96     out << "    Edge: " << std::endl;
97     out << "        bot x: " << e.bot.x << " y: " << e.bot.y << std::endl;
98     out << "        top x: " << e.top.x << " y: " << e.top.y << std::endl;
99     return out;
100 }
101 
102 template <class charT, class traits, typename T>
operator <<(std::basic_ostream<charT,traits> & out,edge_list<T> const & edges)103 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
104                                                      edge_list<T> const& edges) {
105     out << "[";
106     bool first = true;
107     for (auto const& e : edges) {
108         if (first) {
109             first = false;
110         } else {
111             out << ",";
112         }
113         out << "[[" << e.bot.x << "," << e.bot.y << "],[";
114         out << e.top.x << "," << e.top.y << "]]";
115     }
116     out << "]";
117     return out;
118 }
119 
120 #endif
121 }
122 }
123 }
124