1 #pragma once 2 3 #include <list> 4 5 #include <mapbox/geometry/box.hpp> 6 #include <mapbox/geometry/line_string.hpp> 7 #include <mapbox/geometry/multi_polygon.hpp> 8 #include <mapbox/geometry/polygon.hpp> 9 10 #include <mapbox/geometry/wagyu/build_local_minima_list.hpp> 11 #include <mapbox/geometry/wagyu/build_result.hpp> 12 #include <mapbox/geometry/wagyu/config.hpp> 13 #include <mapbox/geometry/wagyu/local_minimum.hpp> 14 #include <mapbox/geometry/wagyu/snap_rounding.hpp> 15 #include <mapbox/geometry/wagyu/topology_correction.hpp> 16 #include <mapbox/geometry/wagyu/vatti.hpp> 17 18 #define WAGYU_MAJOR_VERSION 0 19 #define WAGYU_MINOR_VERSION 4 20 #define WAGYU_PATCH_VERSION 3 21 22 #define WAGYU_VERSION \ 23 (WAGYU_MAJOR_VERSION * 100000) + (WAGYU_MINOR_VERSION * 100) + (WAGYU_PATCH_VERSION) 24 25 namespace mapbox { 26 namespace geometry { 27 namespace wagyu { 28 29 template <typename T> 30 class wagyu { 31 private: 32 local_minimum_list<T> minima_list; 33 bool reverse_output; 34 35 wagyu(wagyu const&) = delete; 36 wagyu& operator=(wagyu const&) = delete; 37 38 public: wagyu()39 wagyu() : minima_list(), reverse_output(false) { 40 } 41 ~wagyu()42 ~wagyu() { 43 clear(); 44 } 45 46 template <typename T2> add_ring(mapbox::geometry::linear_ring<T2> const & pg,polygon_type p_type=polygon_type_subject)47 bool add_ring(mapbox::geometry::linear_ring<T2> const& pg, 48 polygon_type p_type = polygon_type_subject) { 49 return add_linear_ring(pg, minima_list, p_type); 50 } 51 52 template <typename T2> add_polygon(mapbox::geometry::polygon<T2> const & ppg,polygon_type p_type=polygon_type_subject)53 bool add_polygon(mapbox::geometry::polygon<T2> const& ppg, 54 polygon_type p_type = polygon_type_subject) { 55 bool result = false; 56 for (auto const& r : ppg) { 57 if (add_ring(r, p_type)) { 58 result = true; 59 } 60 } 61 return result; 62 } 63 reverse_rings(bool value)64 void reverse_rings(bool value) { 65 reverse_output = value; 66 } 67 clear()68 void clear() { 69 minima_list.clear(); 70 } 71 get_bounds()72 mapbox::geometry::box<T> get_bounds() { 73 mapbox::geometry::point<T> min = { 0, 0 }; 74 mapbox::geometry::point<T> max = { 0, 0 }; 75 if (minima_list.empty()) { 76 return mapbox::geometry::box<T>(min, max); 77 } 78 bool first_set = false; 79 for (auto const& lm : minima_list) { 80 if (!lm.left_bound.edges.empty()) { 81 if (!first_set) { 82 min = lm.left_bound.edges.front().top; 83 max = lm.left_bound.edges.back().bot; 84 first_set = true; 85 } else { 86 min.y = std::min(min.y, lm.left_bound.edges.front().top.y); 87 max.y = std::max(max.y, lm.left_bound.edges.back().bot.y); 88 max.x = std::max(max.x, lm.left_bound.edges.back().top.x); 89 min.x = std::min(min.x, lm.left_bound.edges.back().top.x); 90 } 91 for (auto const& e : lm.left_bound.edges) { 92 max.x = std::max(max.x, e.bot.x); 93 min.x = std::min(min.x, e.bot.x); 94 } 95 } 96 if (!lm.right_bound.edges.empty()) { 97 if (!first_set) { 98 min = lm.right_bound.edges.front().top; 99 max = lm.right_bound.edges.back().bot; 100 first_set = true; 101 } else { 102 min.y = std::min(min.y, lm.right_bound.edges.front().top.y); 103 max.y = std::max(max.y, lm.right_bound.edges.back().bot.y); 104 max.x = std::max(max.x, lm.right_bound.edges.back().top.x); 105 min.x = std::min(min.x, lm.right_bound.edges.back().top.x); 106 } 107 for (auto const& e : lm.right_bound.edges) { 108 max.x = std::max(max.x, e.bot.x); 109 min.x = std::min(min.x, e.bot.x); 110 } 111 } 112 } 113 return mapbox::geometry::box<T>(min, max); 114 } 115 116 template <typename T2> execute(clip_type cliptype,mapbox::geometry::multi_polygon<T2> & solution,fill_type subject_fill_type,fill_type clip_fill_type)117 bool execute(clip_type cliptype, 118 mapbox::geometry::multi_polygon<T2>& solution, 119 fill_type subject_fill_type, 120 fill_type clip_fill_type) { 121 122 if (minima_list.empty()) { 123 return false; 124 } 125 126 ring_manager<T> manager; 127 128 build_hot_pixels(minima_list, manager); 129 130 execute_vatti(minima_list, manager, cliptype, subject_fill_type, clip_fill_type); 131 132 correct_topology(manager); 133 134 build_result(solution, manager, reverse_output); 135 136 return true; 137 } 138 }; 139 } 140 } 141 } 142