1 #pragma once
2
3 #include <mapbox/geometry/wagyu/active_bound_list.hpp>
4 #include <mapbox/geometry/wagyu/config.hpp>
5 #include <mapbox/geometry/wagyu/edge.hpp>
6 #include <mapbox/geometry/wagyu/intersect_util.hpp>
7 #include <mapbox/geometry/wagyu/local_minimum.hpp>
8 #include <mapbox/geometry/wagyu/local_minimum_util.hpp>
9 #include <mapbox/geometry/wagyu/process_horizontal.hpp>
10 #include <mapbox/geometry/wagyu/ring.hpp>
11 #include <mapbox/geometry/wagyu/ring_util.hpp>
12 #include <mapbox/geometry/wagyu/topology_correction.hpp>
13 #include <mapbox/geometry/wagyu/util.hpp>
14
15 namespace mapbox {
16 namespace geometry {
17 namespace wagyu {
18
19 template <typename T>
do_maxima(active_bound_list_itr<T> & bnd,active_bound_list_itr<T> & bndMaxPair,clip_type cliptype,fill_type subject_fill_type,fill_type clip_fill_type,ring_manager<T> & manager,active_bound_list<T> & active_bounds)20 active_bound_list_itr<T> do_maxima(active_bound_list_itr<T>& bnd,
21 active_bound_list_itr<T>& bndMaxPair,
22 clip_type cliptype,
23 fill_type subject_fill_type,
24 fill_type clip_fill_type,
25 ring_manager<T>& manager,
26 active_bound_list<T>& active_bounds) {
27 auto bnd_next = std::next(bnd);
28 auto return_bnd = bnd;
29 bool skipped = false;
30 while (bnd_next != active_bounds.end() && bnd_next != bndMaxPair) {
31 if (*bnd_next == nullptr) {
32 ++bnd_next;
33 continue;
34 }
35 skipped = true;
36 intersect_bounds(*(*bnd), *(*bnd_next), (*bnd)->current_edge->top, cliptype,
37 subject_fill_type, clip_fill_type, manager, active_bounds);
38 std::iter_swap(bnd, bnd_next);
39 bnd = bnd_next;
40 ++bnd_next;
41 }
42
43 if ((*bnd)->ring && (*bndMaxPair)->ring) {
44 add_local_maximum_point(*(*bnd), *(*bndMaxPair), (*bnd)->current_edge->top, manager,
45 active_bounds);
46 } else if ((*bnd)->ring || (*bndMaxPair)->ring) {
47 throw std::runtime_error("DoMaxima error");
48 }
49 *bndMaxPair = nullptr;
50 *bnd = nullptr;
51 if (!skipped) {
52 ++return_bnd;
53 }
54 return return_bnd;
55 }
56
57 template <typename T>
process_edges_at_top_of_scanbeam(T top_y,active_bound_list<T> & active_bounds,scanbeam_list<T> & scanbeam,local_minimum_ptr_list<T> const & minima_sorted,local_minimum_ptr_list_itr<T> & current_lm,ring_manager<T> & manager,clip_type cliptype,fill_type subject_fill_type,fill_type clip_fill_type)58 void process_edges_at_top_of_scanbeam(T top_y,
59 active_bound_list<T>& active_bounds,
60 scanbeam_list<T>& scanbeam,
61 local_minimum_ptr_list<T> const& minima_sorted,
62 local_minimum_ptr_list_itr<T>& current_lm,
63 ring_manager<T>& manager,
64 clip_type cliptype,
65 fill_type subject_fill_type,
66 fill_type clip_fill_type) {
67
68 for (auto bnd = active_bounds.begin(); bnd != active_bounds.end();) {
69 if (*bnd == nullptr) {
70 ++bnd;
71 continue;
72 }
73 // 1. Process maxima, treating them as if they are "bent" horizontal edges,
74 // but exclude maxima with horizontal edges.
75
76 bool is_maxima_edge = is_maxima(bnd, top_y);
77
78 if (is_maxima_edge) {
79 auto bnd_max_pair = get_maxima_pair(bnd, active_bounds);
80 is_maxima_edge = ((bnd_max_pair == active_bounds.end() ||
81 !current_edge_is_horizontal<T>(bnd_max_pair)) &&
82 is_maxima(bnd_max_pair, top_y));
83 if (is_maxima_edge) {
84 bnd = do_maxima(bnd, bnd_max_pair, cliptype, subject_fill_type, clip_fill_type,
85 manager, active_bounds);
86 continue;
87 }
88 }
89
90 // 2. Promote horizontal edges.
91 if (is_intermediate(bnd, top_y) && next_edge_is_horizontal<T>(bnd)) {
92 if ((*bnd)->ring) {
93 insert_hot_pixels_in_path(*(*bnd), (*bnd)->current_edge->top, manager, false);
94 }
95 next_edge_in_bound(*(*bnd), scanbeam);
96 if ((*bnd)->ring) {
97 add_point_to_ring(*(*bnd), (*bnd)->current_edge->bot, manager);
98 }
99 } else {
100 (*bnd)->current_x = get_current_x(*((*bnd)->current_edge), top_y);
101 }
102 ++bnd;
103 }
104 active_bounds.erase(std::remove(active_bounds.begin(), active_bounds.end(), nullptr),
105 active_bounds.end());
106
107 insert_horizontal_local_minima_into_ABL(top_y, minima_sorted, current_lm, active_bounds,
108 manager, scanbeam, cliptype, subject_fill_type,
109 clip_fill_type);
110
111 process_horizontals(top_y, active_bounds, manager, scanbeam, cliptype, subject_fill_type,
112 clip_fill_type);
113
114 // 4. Promote intermediate vertices
115
116 for (auto bnd = active_bounds.begin(); bnd != active_bounds.end(); ++bnd) {
117 if (is_intermediate(bnd, top_y)) {
118 if ((*bnd)->ring) {
119 add_point_to_ring(*(*bnd), (*bnd)->current_edge->top, manager);
120 }
121 next_edge_in_bound(*(*bnd), scanbeam);
122 }
123 }
124 }
125 }
126 }
127 }
128