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