Upgrade Wagyu to bfbf2893

This commit is contained in:
Eric Fischer
2017-01-04 16:33:43 -08:00
parent e53c8ed7e6
commit bdac4d4e80
37 changed files with 678 additions and 953 deletions
+17 -119
View File
@@ -8,7 +8,6 @@
#include <mapbox/geometry/wagyu/bound.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/exceptions.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <mapbox/geometry/wagyu/local_minimum_util.hpp>
#include <mapbox/geometry/wagyu/ring.hpp>
@@ -119,8 +118,7 @@ active_bound_list_itr<T> insert_bound_into_ABL(bound<T>& bnd,
template <typename T>
inline bool is_maxima(bound<T>& bnd, T y) {
return bnd.next_edge == bnd.edges.end() &&
bnd.current_edge->top.y == y;
return bnd.next_edge == bnd.edges.end() && bnd.current_edge->top.y == y;
}
template <typename T>
@@ -130,8 +128,7 @@ inline bool is_maxima(active_bound_list_itr<T>& bnd, T y) {
template <typename T>
inline bool is_intermediate(bound<T>& bnd, T y) {
return bnd.next_edge != bnd.edges.end() &&
bnd.current_edge->top.y == y;
return bnd.next_edge != bnd.edges.end() && bnd.current_edge->top.y == y;
}
template <typename T>
@@ -155,9 +152,9 @@ inline void swap_positions_in_ABL(active_bound_list_itr<T>& bnd1,
active_bound_list<T>& active_bounds) {
if (std::next(bnd2) == bnd1) {
active_bounds.splice(bnd2, active_bounds, bnd1);
} else {
} else {
active_bounds.splice(bnd1, active_bounds, bnd2);
}
}
}
template <typename T>
@@ -188,19 +185,12 @@ active_bound_list_itr<T> get_maxima_pair(active_bound_list_itr<T> bnd,
template <typename T>
void set_winding_count(active_bound_list_itr<T>& bnd_itr,
active_bound_list<T>& active_bounds,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type) {
auto rev_bnd_itr = active_bound_list_rev_itr<T>(bnd_itr);
if (rev_bnd_itr == active_bounds.rend()) {
if ((*bnd_itr)->winding_delta == 0) {
fill_type pft = ((*bnd_itr)->poly_type == polygon_type_subject) ? subject_fill_type
: clip_fill_type;
(*bnd_itr)->winding_count = (pft == fill_type_negative ? -1 : 1);
} else {
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
}
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
(*bnd_itr)->winding_count2 = 0;
return;
}
@@ -208,39 +198,15 @@ void set_winding_count(active_bound_list_itr<T>& bnd_itr,
// find the edge of the same polytype that immediately preceeds 'edge' in
// AEL
while (rev_bnd_itr != active_bounds.rend() &&
((*rev_bnd_itr)->poly_type != (*bnd_itr)->poly_type ||
(*rev_bnd_itr)->winding_delta == 0)) {
(*rev_bnd_itr)->poly_type != (*bnd_itr)->poly_type) {
++rev_bnd_itr;
}
if (rev_bnd_itr == active_bounds.rend()) {
if ((*bnd_itr)->winding_delta == 0) {
fill_type pft = ((*bnd_itr)->poly_type == polygon_type_subject) ? subject_fill_type
: clip_fill_type;
(*bnd_itr)->winding_count = (pft == fill_type_negative ? -1 : 1);
} else {
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
}
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
(*bnd_itr)->winding_count2 = 0;
} else if ((*bnd_itr)->winding_delta == 0 && cliptype != clip_type_union) {
(*bnd_itr)->winding_count = 1;
(*bnd_itr)->winding_count2 = (*rev_bnd_itr)->winding_count2;
} else if (is_even_odd_fill_type(*(*bnd_itr), subject_fill_type, clip_fill_type)) {
// EvenOdd filling ...
if ((*bnd_itr)->winding_delta == 0) {
// are we inside a subj polygon ...
bool inside = true;
auto rev2 = std::next(rev_bnd_itr);
while (rev2 != active_bounds.rend()) {
if ((*rev2)->poly_type == (*rev_bnd_itr)->poly_type &&
(*rev2)->winding_delta != 0) {
inside = !inside;
}
++rev2;
}
(*bnd_itr)->winding_count = (inside ? 0 : 1);
} else {
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
}
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
(*bnd_itr)->winding_count2 = (*rev_bnd_itr)->winding_count2;
} else {
// nonZero, Positive or Negative filling ...
@@ -259,17 +225,12 @@ void set_winding_count(active_bound_list_itr<T>& bnd_itr,
}
} else {
// now outside all polys of same polytype so set own WC ...
(*bnd_itr)->winding_count =
((*bnd_itr)->winding_delta == 0 ? 1 : (*bnd_itr)->winding_delta);
(*bnd_itr)->winding_count = (*bnd_itr)->winding_delta;
}
} else {
// prev edge is 'increasing' WindCount (WC) away from zero
// so we're inside the previous polygon ...
if ((*bnd_itr)->winding_delta == 0) {
(*bnd_itr)->winding_count =
((*rev_bnd_itr)->winding_count < 0 ? (*rev_bnd_itr)->winding_count - 1
: (*rev_bnd_itr)->winding_count + 1);
} else if ((*rev_bnd_itr)->winding_delta * (*bnd_itr)->winding_delta < 0) {
if ((*rev_bnd_itr)->winding_delta * (*bnd_itr)->winding_delta < 0) {
// if wind direction is reversing prev then use same WC
(*bnd_itr)->winding_count = (*rev_bnd_itr)->winding_count;
} else {
@@ -314,11 +275,6 @@ bool is_contributing(bound<T> const& bnd,
switch (pft) {
case fill_type_even_odd:
// return false if a subj line has been flagged as inside a subj
// polygon
if (bnd.winding_delta == 0 && bnd.winding_count != 1) {
return false;
}
break;
case fill_type_non_zero:
if (std::abs(static_cast<int>(bnd.winding_count)) != 1) {
@@ -388,45 +344,13 @@ bool is_contributing(bound<T> const& bnd,
}
break;
case clip_type_x_or:
if (bnd.winding_delta == 0) {
// XOr always contributing unless open
switch (pft2) {
case fill_type_even_odd:
case fill_type_non_zero:
return (bnd.winding_count2 == 0);
case fill_type_positive:
return (bnd.winding_count2 <= 0);
case fill_type_negative:
default:
return (bnd.winding_count2 >= 0);
}
} else {
return true;
}
return true;
break;
default:
return true;
}
}
template <typename T>
void insert_lm_only_one_bound(bound<T>& bnd,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings,
scanbeam_list<T>& scanbeam,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type) {
auto abl_itr = insert_bound_into_ABL(bnd, active_bounds);
set_winding_count(abl_itr, active_bounds, cliptype, subject_fill_type, clip_fill_type);
if (is_contributing(bnd, cliptype, subject_fill_type, clip_fill_type)) {
add_first_point(abl_itr, active_bounds, (*abl_itr)->current_edge->bot, rings);
}
if (!current_edge_is_horizontal<T>(abl_itr)) {
scanbeam.push((*abl_itr)->current_edge->top.y);
}
}
template <typename T>
void insert_lm_left_and_right_bound(bound<T>& left_bound,
bound<T>& right_bound,
@@ -439,8 +363,8 @@ void insert_lm_left_and_right_bound(bound<T>& left_bound,
// Both left and right bound
auto lb_abl_itr = insert_bound_into_ABL(left_bound, active_bounds);
auto rb_abl_itr = insert_bound_into_ABL(right_bound, lb_abl_itr, active_bounds);
set_winding_count(lb_abl_itr, active_bounds, cliptype, subject_fill_type, clip_fill_type);
auto rb_abl_itr = active_bounds.insert(std::next(lb_abl_itr), &right_bound);
set_winding_count(lb_abl_itr, active_bounds, subject_fill_type, clip_fill_type);
(*rb_abl_itr)->winding_count = (*lb_abl_itr)->winding_count;
(*rb_abl_itr)->winding_count2 = (*lb_abl_itr)->winding_count2;
if (is_contributing(left_bound, cliptype, subject_fill_type, clip_fill_type)) {
@@ -454,16 +378,6 @@ void insert_lm_left_and_right_bound(bound<T>& left_bound,
if (!current_edge_is_horizontal<T>(rb_abl_itr)) {
scanbeam.push((*rb_abl_itr)->current_edge->top.y);
}
auto abl_itr = std::next(lb_abl_itr);
while (abl_itr != rb_abl_itr && abl_itr != active_bounds.end()) {
// We call intersect_bounds here, but we do not swap positions in the ABL
// this is the logic that was copied from angus, but it might be correct
// to swap the positions in the ABL following this or at least move
// lb and rb to be next to each other in the ABL.
intersect_bounds(rb_abl_itr, abl_itr, (*lb_abl_itr)->current_edge->bot, cliptype,
subject_fill_type, clip_fill_type, rings, active_bounds);
++abl_itr;
}
}
template <typename T>
@@ -480,16 +394,8 @@ void insert_local_minima_into_ABL(T const bot_y,
initialize_lm<T>(current_lm);
auto& left_bound = (*current_lm)->left_bound;
auto& right_bound = (*current_lm)->right_bound;
if (left_bound.edges.empty() && !right_bound.edges.empty()) {
insert_lm_only_one_bound(right_bound, active_bounds, rings, scanbeam, cliptype,
subject_fill_type, clip_fill_type);
} else if (right_bound.edges.empty() && !left_bound.edges.empty()) {
insert_lm_only_one_bound(left_bound, active_bounds, rings, scanbeam, cliptype,
subject_fill_type, clip_fill_type);
} else {
insert_lm_left_and_right_bound(left_bound, right_bound, active_bounds, rings, scanbeam,
cliptype, subject_fill_type, clip_fill_type);
}
insert_lm_left_and_right_bound(left_bound, right_bound, active_bounds, rings, scanbeam,
cliptype, subject_fill_type, clip_fill_type);
++current_lm;
}
}
@@ -509,16 +415,8 @@ void insert_horizontal_local_minima_into_ABL(T const top_y,
initialize_lm<T>(current_lm);
auto& left_bound = (*current_lm)->left_bound;
auto& right_bound = (*current_lm)->right_bound;
if (left_bound.edges.empty() && !right_bound.edges.empty()) {
insert_lm_only_one_bound(right_bound, active_bounds, rings, scanbeam, cliptype,
subject_fill_type, clip_fill_type);
} else if (right_bound.edges.empty() && !left_bound.edges.empty()) {
throw clipper_exception(
"There should only be horizontal local minimum on right bounds!");
} else {
insert_lm_left_and_right_bound(left_bound, right_bound, active_bounds, rings, scanbeam,
cliptype, subject_fill_type, clip_fill_type);
}
insert_lm_left_and_right_bound(left_bound, right_bound, active_bounds, rings, scanbeam,
cliptype, subject_fill_type, clip_fill_type);
++current_lm;
}
}
+2 -2
View File
@@ -47,8 +47,8 @@ struct bound {
poly_type(polygon_type_subject),
side(edge_left) {
}
bound(bound<T> && b) noexcept
bound(bound<T>&& b) noexcept
: edges(std::move(b.edges)),
current_edge(std::move(b.current_edge)),
last_point(std::move(b.last_point)),
+10 -46
View File
@@ -6,7 +6,6 @@
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/exceptions.hpp>
#include <mapbox/geometry/wagyu/util.hpp>
namespace mapbox {
@@ -14,42 +13,8 @@ namespace geometry {
namespace wagyu {
template <typename T>
bool build_edge_list(mapbox::geometry::line_string<T> const& path_geometry,
edge_list<T>& edges,
bool& is_flat) {
if (path_geometry.size() < 2) {
return false;
}
auto itr_next = path_geometry.begin();
++itr_next;
auto itr = path_geometry.begin();
while (itr_next != path_geometry.end()) {
if (*itr_next == *itr) {
// Duplicate point advance itr_next, but do not
// advance itr
++itr_next;
continue;
}
if (is_flat && itr_next->y != itr->y) {
is_flat = false;
}
edges.emplace_back(*itr, *itr_next);
itr = itr_next;
++itr_next;
}
if (edges.size() < 2) {
return false;
}
return true;
}
template <typename T>
bool point_2_is_between_point_1_and_point_3(mapbox::geometry::point<T> const& pt1,
mapbox::geometry::point<T> const& pt2,
bool point_2_is_between_point_1_and_point_3(mapbox::geometry::point<T> const& pt1,
mapbox::geometry::point<T> const& pt2,
mapbox::geometry::point<T> const& pt3) {
if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) {
return false;
@@ -62,7 +27,6 @@ bool point_2_is_between_point_1_and_point_3(mapbox::geometry::point<T> const& pt
template <typename T>
bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge_list<T>& edges) {
using value_type = T;
if (path_geometry.size() < 3) {
return false;
@@ -73,8 +37,8 @@ bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge
auto itr_rev = path_geometry.rbegin();
auto itr = path_geometry.begin();
mapbox::geometry::point<value_type> pt1 = *itr_rev;
mapbox::geometry::point<value_type> pt2 = *itr;
mapbox::geometry::point<T> pt1 = *itr_rev;
mapbox::geometry::point<T> pt2 = *itr;
// Find next non repeated point going backwards from
// end for pt1
@@ -86,10 +50,10 @@ bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge
pt1 = *itr_rev;
}
++itr;
mapbox::geometry::point<value_type> pt3 = *itr;
mapbox::geometry::point<T> pt3 = *itr;
auto itr_last = itr_rev.base();
mapbox::geometry::point<value_type> front_pt;
mapbox::geometry::point<value_type> back_pt;
mapbox::geometry::point<T> front_pt;
mapbox::geometry::point<T> back_pt;
while (true) {
if (pt3 == pt2) {
// Duplicate point advance itr, but do not
@@ -129,13 +93,13 @@ bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge
} else {
// If this occurs we must look to the back of the
// ring for new points.
do {
while (*itr_rev == pt2) {
++itr_rev;
if ((itr + 1) == itr_rev.base()) {
return false;
}
pt1 = *itr_rev;
} while (pt1 == pt2);
}
pt1 = *itr_rev;
itr_last = itr_rev.base();
}
continue;
@@ -34,7 +34,6 @@ bool add_linear_ring(mapbox::geometry::linear_ring<T> const& path_geometry,
add_ring_to_local_minima_list(new_edges, minima_list, p_type);
return true;
}
}
}
}
+5 -5
View File
@@ -15,16 +15,16 @@ void push_ring_to_polygon(mapbox::geometry::polygon<T>& poly, ring_ptr<T>& r, bo
auto ptIt = r->points;
if (reverse_output) {
do {
lr.push_back({ ptIt->x, ptIt->y });
lr.emplace_back(ptIt->x, ptIt->y);
ptIt = ptIt->next;
} while (ptIt != firstPt);
} else {
do {
lr.push_back({ ptIt->x, ptIt->y });
lr.emplace_back(ptIt->x, ptIt->y);
ptIt = ptIt->prev;
} while (ptIt != firstPt);
}
lr.push_back({ firstPt->x, firstPt->y }); // close the ring
lr.emplace_back(firstPt->x, firstPt->y); // close the ring
poly.push_back(lr);
}
@@ -36,7 +36,7 @@ void build_result_polygons(std::vector<mapbox::geometry::polygon<T>>& solution,
for (auto& r : rings) {
assert(r->points);
std::size_t cnt = point_count(r->points);
if ((r->is_open && cnt < 2) || (!r->is_open && cnt < 3)) {
if (cnt < 3) {
continue;
}
solution.emplace_back();
@@ -44,7 +44,7 @@ void build_result_polygons(std::vector<mapbox::geometry::polygon<T>>& solution,
for (auto& c : r->children) {
assert(c->points);
cnt = point_count(c->points);
if ((c->is_open && cnt < 2) || (!c->is_open && cnt < 3)) {
if (cnt < 3) {
continue;
}
push_ring_to_polygon(solution.back(), c, reverse_output);
+1
View File
@@ -3,6 +3,7 @@
#include <cassert>
#include <cstdint>
#include <list>
#include <stdexcept>
namespace mapbox {
namespace geometry {
+5 -7
View File
@@ -28,19 +28,18 @@ struct edge {
mapbox::geometry::point<T> top;
double dx;
edge(edge<T> && e) noexcept
: bot(std::move(e.bot)),
top(std::move(e.top)),
dx(std::move(e.dx)) {}
edge(edge<T>&& e) noexcept : bot(std::move(e.bot)), top(std::move(e.top)), dx(std::move(e.dx)) {
}
edge& operator=(edge<T> && e) noexcept {
edge& operator=(edge<T>&& e) noexcept {
bot = std::move(e.bot);
top = std::move(e.top);
dx = std::move(e.dx);
return *this;
}
edge(mapbox::geometry::point<T> const& current, mapbox::geometry::point<T> const& next_pt) noexcept
edge(mapbox::geometry::point<T> const& current,
mapbox::geometry::point<T> const& next_pt) noexcept
: bot(current), top(current), dx(0.0) {
if (current.y >= next_pt.y) {
top = next_pt;
@@ -54,7 +53,6 @@ struct edge {
dx = static_cast<double>(top.x - bot.x) / dy;
}
}
};
template <typename T>
+4 -5
View File
@@ -21,12 +21,11 @@ struct intersect_node {
active_bound_list_itr<T> bound2;
mapbox::geometry::point<double> pt;
intersect_node(intersect_node<T> && n)
: bound1(std::move(n.bound1)),
bound2(std::move(n.bound2)),
pt(std::move(n.pt)) { }
intersect_node(intersect_node<T>&& n)
: bound1(std::move(n.bound1)), bound2(std::move(n.bound2)), pt(std::move(n.pt)) {
}
intersect_node& operator=(intersect_node<T> && n) {
intersect_node& operator=(intersect_node<T>&& n) {
bound1 = std::move(n.bound1);
bound2 = std::move(n.bound2);
pt = std::move(n.pt);
+8 -50
View File
@@ -69,12 +69,13 @@ bool get_edge_intersection(edge<T1> const& e1,
pt.y = p0_y + (t * s1_y);
return true;
}
// LCOV_EXCL_START
return false;
// LCOV_EXCL_END
}
template <typename T>
void build_intersect_list(active_bound_list<T>& active_bounds,
intersect_list<T>& intersects) {
void build_intersect_list(active_bound_list<T>& active_bounds, intersect_list<T>& intersects) {
// bubblesort ...
bool isModified = false;
do {
@@ -87,8 +88,10 @@ void build_intersect_list(active_bound_list<T>& active_bounds,
mapbox::geometry::point<double> pt;
if (!get_edge_intersection<T, double>(*((*bnd)->current_edge),
*((*bnd_next)->current_edge), pt)) {
// LCOV_EXCL_START
throw std::runtime_error(
"Trying to find intersection of lines that do not intersect");
// LCOV_EXCL_END
}
intersects.emplace_back(bnd, bnd_next, pt);
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
@@ -113,50 +116,6 @@ void intersect_bounds(active_bound_list_itr<T>& b1,
active_bound_list<T>& active_bounds) {
bool b1Contributing = ((*b1)->ring != nullptr);
bool b2Contributing = ((*b2)->ring != nullptr);
// if either bound is on an OPEN path ...
if ((*b1)->winding_delta == 0 || (*b2)->winding_delta == 0) {
// ignore subject-subject open path intersections UNLESS they
// are both open paths, AND they are both 'contributing maximas' ...
if ((*b1)->winding_delta == 0 && (*b2)->winding_delta == 0) {
return;
}
// if intersecting a subj line with a subj poly ...
else if ((*b1)->poly_type == (*b2)->poly_type &&
(*b1)->winding_delta != (*b2)->winding_delta && cliptype == clip_type_union) {
if ((*b1)->winding_delta == 0) {
if (b2Contributing) {
add_point(b1, active_bounds, pt, rings);
if (b1Contributing) {
(*b1)->ring = nullptr;
}
}
} else {
if (b1Contributing) {
add_point(b2, active_bounds, pt, rings);
if (b2Contributing) {
(*b2)->ring = nullptr;
}
}
}
} else if ((*b1)->poly_type != (*b2)->poly_type) {
// toggle subj open path index on/off when std::abs(clip.WndCnt) == 1
if (((*b1)->winding_delta == 0) && std::abs(static_cast<int>((*b2)->winding_count)) == 1 &&
(cliptype != clip_type_union || (*b2)->winding_count2 == 0)) {
add_point(b1, active_bounds, pt, rings);
if (b1Contributing) {
(*b1)->ring = nullptr;
}
} else if (((*b2)->winding_delta == 0) && (std::abs(static_cast<int>((*b1)->winding_count)) == 1) &&
(cliptype != clip_type_union || (*b1)->winding_count2 == 0)) {
add_point(b2, active_bounds, pt, rings);
if (b2Contributing) {
(*b2)->ring = nullptr;
}
}
}
return;
}
// update winding counts...
// assumes that b1 will be to the Right of b2 ABOVE the intersection
@@ -347,7 +306,7 @@ void process_intersect_list(intersect_list<T>& intersects,
template <typename T>
void update_current_x(active_bound_list<T>& active_bounds, T top_y) {
std::size_t pos = 0;
for (auto & bnd : active_bounds) {
for (auto& bnd : active_bounds) {
bnd->pos = pos++;
bnd->current_x = get_current_x(*bnd->current_edge, top_y);
}
@@ -372,9 +331,8 @@ void process_intersections(T top_y,
}
// Restore order of active bounds list
active_bounds.sort([] (bound_ptr<T> const& b1, bound_ptr<T> const& b2) {
return b1->pos < b2->pos;
});
active_bounds.sort(
[](bound_ptr<T> const& b1, bound_ptr<T> const& b2) { return b1->pos < b2->pos; });
// Sort the intersection list
std::stable_sort(intersects.begin(), intersects.end(), intersect_list_sorter<T>());
+4 -102
View File
@@ -4,7 +4,7 @@
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#ifdef DEBUG
#include <mapbox/geometry/wagyu/exceptions.hpp>
#include <stdexcept>
#endif
namespace mapbox {
@@ -194,106 +194,8 @@ void move_horizontals_on_left_to_right(bound<T>& left_bound, bound<T>& right_bou
auto dist = std::distance(left_bound.edges.begin(), edge_itr);
std::move(left_bound.edges.begin(), edge_itr, std::back_inserter(right_bound.edges));
left_bound.edges.erase(left_bound.edges.begin(), edge_itr);
std::rotate(right_bound.edges.begin(), std::prev(right_bound.edges.end(), dist), right_bound.edges.end());
}
template <typename T>
void add_line_to_local_minima_list(edge_list<T>& edges, local_minimum_list<T>& minima_list) {
if (edges.empty()) {
return;
}
// Adjust the order of the ring so we start on a local maximum
// therefore we start right away on a bound.
start_list_on_local_maximum(edges);
bound_ptr<T> last_maximum = nullptr;
while (!edges.empty()) {
bool lm_minimum_has_horizontal = false;
auto to_minimum = create_bound_towards_minimum(edges);
assert(!to_minimum.edges.empty());
fix_horizontals(to_minimum);
to_minimum.poly_type = polygon_type_subject;
to_minimum.maximum_bound = last_maximum;
to_minimum.winding_delta = 0;
auto to_min_first_non_horizontal = to_minimum.edges.begin();
while (to_min_first_non_horizontal != to_minimum.edges.end() &&
is_horizontal(*to_min_first_non_horizontal)) {
lm_minimum_has_horizontal = true;
++to_min_first_non_horizontal;
}
if (edges.empty()) {
if (to_min_first_non_horizontal != to_minimum.edges.end() &&
to_min_first_non_horizontal->dx > 0.0) {
to_minimum.side = edge_left;
bound<T> right_bound;
right_bound.winding_delta = 0;
right_bound.side = edge_right;
right_bound.poly_type = polygon_type_subject;
move_horizontals_on_left_to_right(to_minimum, right_bound);
auto const& min_front = to_minimum.edges.front();
minima_list.emplace_back(std::move(to_minimum), std::move(right_bound), min_front.y,
lm_minimum_has_horizontal);
if (last_maximum) {
last_maximum->maximum_bound = &(minima_list.back().left_bound);
last_maximum = nullptr;
}
} else {
to_minimum.side = edge_right;
bound<T> left_bound;
left_bound.winding_delta = 0;
left_bound.side = edge_left;
left_bound.poly_type = polygon_type_subject;
auto const& min_front = to_minimum.edges.front();
minima_list.emplace_back(std::move(left_bound), std::move(to_minimum), min_front.y);
if (last_maximum) {
last_maximum->maximum_bound = &(minima_list.back().right_bound);
last_maximum = nullptr;
}
}
break;
}
bool minimum_is_left = true;
auto to_maximum = create_bound_towards_maximum(edges);
assert(!to_maximum.edges.empty());
fix_horizontals(to_maximum);
auto to_max_first_non_horizontal = to_minimum.edges.begin();
while (to_max_first_non_horizontal != to_maximum.edges.end() &&
is_horizontal(*to_max_first_non_horizontal)) {
lm_minimum_has_horizontal = true;
++to_max_first_non_horizontal;
}
if (to_max_first_non_horizontal != to_maximum.edges.end() &&
(to_min_first_non_horizontal == to_minimum.edges.end() ||
to_max_first_non_horizontal->dx > to_min_first_non_horizontal->dx)) {
minimum_is_left = false;
move_horizontals_on_left_to_right(to_maximum, to_minimum);
} else {
minimum_is_left = true;
move_horizontals_on_left_to_right(to_minimum, to_maximum);
}
auto const& min_front = to_minimum.edges.front();
to_maximum.poly_type = polygon_type_subject;
to_maximum.winding_delta = 0;
if (!minimum_is_left) {
to_minimum.side = edge_right;
to_maximum.side = edge_left;
minima_list.emplace_back(std::move(to_maximum), std::move(to_minimum), min_front.bot.y,
lm_minimum_has_horizontal);
if (last_maximum) {
last_maximum->maximum_bound = &(minima_list.back().right_bound);
}
last_maximum = &(minima_list.back().left_bound);
} else {
to_minimum.side = edge_left;
to_maximum.side = edge_right;
minima_list.emplace_back(std::move(to_minimum), std::move(to_maximum), min_front.bot.y,
lm_minimum_has_horizontal);
if (last_maximum) {
last_maximum->maximum_bound = &(minima_list.back().left_bound);
}
last_maximum = &(minima_list.back().right_bound);
}
}
std::rotate(right_bound.edges.begin(), std::prev(right_bound.edges.end(), dist),
right_bound.edges.end());
}
template <typename T>
@@ -335,7 +237,7 @@ void add_ring_to_local_minima_list(edge_list<T>& edges,
#ifdef DEBUG
if (to_max_first_non_horizontal == to_maximum.edges.end() ||
to_min_first_non_horizontal == to_minimum.edges.end()) {
throw clipper_exception("should not have a horizontal only bound for a ring");
throw std::runtime_error("should not have a horizontal only bound for a ring");
}
#endif
if (lm_minimum_has_horizontal) {
+3 -2
View File
@@ -37,12 +37,13 @@ struct point {
point_ptr<T> next;
point_ptr<T> prev;
point(point<T> && p)
point(point<T>&& p)
: ring(std::move(p.ring)),
x(std::move(p.x)),
y(std::move(p.y)),
next(std::move(p.next)),
prev(std::move(p.prev)) { }
prev(std::move(p.prev)) {
}
point() : ring(nullptr), x(0), y(0), prev(this), next(this) {
}
+27 -39
View File
@@ -6,7 +6,6 @@
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/exceptions.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <mapbox/geometry/wagyu/util.hpp>
@@ -24,7 +23,6 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
fill_type subject_fill_type,
fill_type clip_fill_type) {
auto horizontal_itr_behind = horz_bound;
bool is_open = (*horz_bound)->winding_delta == 0;
bool is_maxima_edge = is_maxima(horz_bound, scanline_y);
auto bound_max_pair = active_bounds.end();
if (is_maxima_edge) {
@@ -32,19 +30,22 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
}
auto hp_itr = rings.current_hp_itr;
while (hp_itr != rings.hot_pixels.end() && (hp_itr->y > scanline_y || (hp_itr->y == scanline_y && hp_itr->x < (*horz_bound)->current_edge->bot.x))) {
while (hp_itr != rings.hot_pixels.end() &&
(hp_itr->y > scanline_y ||
(hp_itr->y == scanline_y && hp_itr->x < (*horz_bound)->current_edge->bot.x))) {
++hp_itr;
}
auto bnd = std::next(horz_bound);
while (bnd != active_bounds.end()) {
// this code block inserts extra coords into horizontal edges (in output
// polygons) wherever hot pixels touch these horizontal edges. This helps
//'simplifying' polygons (ie if the Simplify property is set).
while (hp_itr != rings.hot_pixels.end() && hp_itr->y == scanline_y && hp_itr->x < std::llround((*bnd)->current_x) &&
while (hp_itr != rings.hot_pixels.end() && hp_itr->y == scanline_y &&
hp_itr->x < std::llround((*bnd)->current_x) &&
hp_itr->x < (*horz_bound)->current_edge->top.x) {
if ((*horz_bound)->ring && !is_open) {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
}
++hp_itr;
@@ -63,11 +64,10 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
}
// note: may be done multiple times
if ((*horz_bound)->ring && !is_open) {
add_point_to_ring(*(*horz_bound),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x),
scanline_y),
rings);
if ((*horz_bound)->ring) {
add_point_to_ring(
*(*horz_bound),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y), rings);
}
// OK, so far we're still in range of the horizontal Edge but make sure
@@ -87,8 +87,7 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
}
intersect_bounds(horz_bound, bnd,
mapbox::geometry::point<T>(std::llround((*bnd)->current_x),
scanline_y),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y),
cliptype, subject_fill_type, clip_fill_type, rings, active_bounds);
auto next_bnd = std::next(bnd);
swap_positions_in_ABL(horz_bound, bnd, active_bounds);
@@ -98,7 +97,7 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
bnd = next_bnd;
} // end while (bnd != active_bounds.end())
if ((*horz_bound)->ring && !is_open) {
if ((*horz_bound)->ring) {
while (hp_itr != rings.hot_pixels.end() && hp_itr->y == scanline_y &&
hp_itr->x < std::llround((*horz_bound)->current_edge->top.x)) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
@@ -110,14 +109,6 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
next_edge_in_bound(horz_bound, scanbeam);
if ((*horz_bound)->winding_delta == 0) {
if (horizontal_itr_behind != horz_bound) {
return horizontal_itr_behind;
} else {
return std::next(horz_bound);
}
}
} else {
next_edge_in_bound(horz_bound, scanbeam);
}
@@ -148,14 +139,15 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type) {
bool is_open = (*horz_bound)->winding_delta == 0;
bool is_maxima_edge = is_maxima(horz_bound, scanline_y);
auto bound_max_pair = active_bounds.end();
if (is_maxima_edge) {
bound_max_pair = get_maxima_pair<T>(horz_bound, active_bounds);
}
auto hp_itr_fwd = rings.current_hp_itr;
while (hp_itr_fwd != rings.hot_pixels.end() && (hp_itr_fwd->y < scanline_y || (hp_itr_fwd->y == scanline_y && hp_itr_fwd->x < (*horz_bound)->current_edge->top.x))) {
while (hp_itr_fwd != rings.hot_pixels.end() &&
(hp_itr_fwd->y < scanline_y ||
(hp_itr_fwd->y == scanline_y && hp_itr_fwd->x < (*horz_bound)->current_edge->top.x))) {
++hp_itr_fwd;
}
auto hp_itr = hot_pixel_rev_itr<T>(hp_itr_fwd);
@@ -164,9 +156,10 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
while (bnd != active_bounds.rend()) {
// this code block inserts extra coords into horizontal edges (in output
// polygons) wherever hot pixels touch these horizontal edges.
while (hp_itr != rings.hot_pixels.rend() && hp_itr->y == scanline_y && hp_itr->x > std::llround((*bnd)->current_x) &&
while (hp_itr != rings.hot_pixels.rend() && hp_itr->y == scanline_y &&
hp_itr->x > std::llround((*bnd)->current_x) &&
hp_itr->x > (*horz_bound)->current_edge->top.x) {
if ((*horz_bound)->ring && !is_open) {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
}
++hp_itr;
@@ -185,11 +178,10 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
}
// note: may be done multiple times
if ((*horz_bound)->ring && !is_open) {
add_point_to_ring(*(*horz_bound),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x),
scanline_y),
rings);
if ((*horz_bound)->ring) {
add_point_to_ring(
*(*horz_bound),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y), rings);
}
auto bnd_forward = --(bnd.base());
@@ -205,8 +197,7 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
}
intersect_bounds(bnd_forward, horz_bound,
mapbox::geometry::point<T>(std::llround((*bnd)->current_x),
scanline_y),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y),
cliptype, subject_fill_type, clip_fill_type, rings, active_bounds);
swap_positions_in_ABL(horz_bound, bnd_forward, active_bounds);
// Why are we not incrementing the bnd iterator here:
@@ -216,8 +207,9 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
// so what the reverse bound points to will have changed.
} // end while (bnd != active_bounds.rend())
if ((*horz_bound)->ring && !is_open) {
while (hp_itr != rings.hot_pixels.rend() && hp_itr->y == scanline_y && hp_itr->x > (*horz_bound)->current_edge->top.x) {
if ((*horz_bound)->ring) {
while (hp_itr != rings.hot_pixels.rend() && hp_itr->y == scanline_y &&
hp_itr->x > (*horz_bound)->current_edge->top.x) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
++hp_itr;
}
@@ -227,10 +219,6 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
next_edge_in_bound(horz_bound, scanbeam);
if ((*horz_bound)->winding_delta == 0) {
return std::next(horz_bound);
}
} else {
next_edge_in_bound(horz_bound, scanbeam);
}
+4 -12
View File
@@ -3,7 +3,6 @@
#include <mapbox/geometry/wagyu/active_bound_list.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/exceptions.hpp>
#include <mapbox/geometry/wagyu/intersect_util.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <mapbox/geometry/wagyu/local_minimum_util.hpp>
@@ -47,14 +46,8 @@ active_bound_list_itr<T> do_maxima(active_bound_list_itr<T>& bnd,
} else if ((*bnd)->ring && (*bndMaxPair)->ring) {
add_local_maximum_point(bnd, bndMaxPair, (*bnd)->current_edge->top, rings, active_bounds);
active_bounds.erase(bndMaxPair);
} else if ((*bnd)->winding_delta == 0 && (*bnd)->ring) {
add_point_to_ring(*(*bnd), (*bnd)->current_edge->top, rings);
active_bounds.erase(bndMaxPair);
} else if ((*bnd)->winding_delta == 0 && (*bndMaxPair)->ring) {
add_point_to_ring(*(*bndMaxPair), (*bnd)->current_edge->top, rings);
active_bounds.erase(bndMaxPair);
} else {
throw clipper_exception("DoMaxima error");
throw std::runtime_error("DoMaxima error");
}
auto prev_itr = active_bounds.erase(bnd);
if (skipped) {
@@ -78,7 +71,7 @@ void process_edges_at_top_of_scanbeam(T top_y,
for (auto bnd = active_bounds.begin(); bnd != active_bounds.end();) {
// 1. Process maxima, treating them as if they are "bent" horizontal edges,
// but exclude maxima with horizontal edges.
bool is_maxima_edge = is_maxima(bnd, top_y);
if (is_maxima_edge) {
@@ -87,8 +80,8 @@ void process_edges_at_top_of_scanbeam(T top_y,
!current_edge_is_horizontal<T>(bnd_max_pair)) &&
is_maxima(bnd_max_pair, top_y));
if (is_maxima_edge) {
bnd = do_maxima(bnd, bnd_max_pair, cliptype, subject_fill_type, clip_fill_type, rings,
active_bounds);
bnd = do_maxima(bnd, bnd_max_pair, cliptype, subject_fill_type, clip_fill_type,
rings, active_bounds);
continue;
}
}
@@ -127,7 +120,6 @@ void process_edges_at_top_of_scanbeam(T top_y,
}
}
}
}
}
}
+9 -14
View File
@@ -2,13 +2,13 @@
#include <assert.h>
#include <cmath>
#include <deque>
#include <list>
#include <map>
#include <mapbox/geometry/wagyu/point.hpp>
#include <set>
#include <sstream>
#include <vector>
#include <deque>
#include <mapbox/geometry/wagyu/point.hpp>
#ifdef DEBUG
#include <execinfo.h>
@@ -46,10 +46,9 @@ struct ring {
ring_list<T> children;
point_ptr<T> points;
point_ptr<T> bottom_point;
bool is_open;
ring( ring const& ) = delete;
ring& operator=(ring const& ) = delete;
ring(ring const&) = delete;
ring& operator=(ring const&) = delete;
ring()
: ring_index(0),
@@ -58,8 +57,7 @@ struct ring {
parent(nullptr),
children(),
points(nullptr),
bottom_point(nullptr),
is_open(false) {
bottom_point(nullptr) {
}
};
@@ -74,7 +72,7 @@ using hot_pixel_rev_itr = typename hot_pixel_vector<T>::reverse_iterator;
template <typename T>
struct ring_manager {
ring_list<T> children;
std::vector<point_ptr<T>> all_points;
hot_pixel_vector<T> hot_pixels;
@@ -84,8 +82,8 @@ struct ring_manager {
std::vector<point<T>> storage;
std::size_t index;
ring_manager( ring_manager const& ) = delete;
ring_manager& operator=(ring_manager const& ) = delete;
ring_manager(ring_manager const&) = delete;
ring_manager& operator=(ring_manager const&) = delete;
ring_manager()
: children(),
@@ -328,12 +326,9 @@ void reverse_ring(point_ptr<T> pp) {
}
template <typename T>
double area_from_point(point_ptr<T> op, std::size_t & size) {
double area_from_point(point_ptr<T> op, std::size_t& size) {
point_ptr<T> startOp = op;
size = 1;
if (!op) {
return 0.0;
}
double a = 0.0;
do {
++size;
+25 -34
View File
@@ -83,13 +83,14 @@ void set_hole_state(active_bound_list_rev_itr<T>& bnd,
template <typename T>
void update_current_hp_itr(T scanline_y, ring_manager<T>& rings) {
while (rings.current_hp_itr->y > scanline_y) {
++rings.current_hp_itr;
++rings.current_hp_itr;
}
}
template <typename T>
struct hot_pixel_sorter {
inline bool operator()(mapbox::geometry::point<T> const& pt1, mapbox::geometry::point<T> const& pt2) {
inline bool operator()(mapbox::geometry::point<T> const& pt1,
mapbox::geometry::point<T> const& pt2) {
if (pt1.y == pt2.y) {
return pt1.x < pt2.x;
} else {
@@ -100,7 +101,7 @@ struct hot_pixel_sorter {
// Due to the nature of floating point calculations
// and the high likely hood of values around X.5, we
// need to fudge what is X.5 some for our rounding.
// need to fudge what is X.5 some for our rounding.
const double rounding_offset = 1e-12;
const double rounding_offset_y = 5e-13;
@@ -141,8 +142,9 @@ inline T get_edge_min_x(edge<T> const& edge, const T current_y) {
if (current_y == edge.bot.y) {
return edge.bot.x;
} else {
double return_val = static_cast<double>(edge.bot.x) +
edge.dx * (static_cast<double>(current_y - edge.bot.y) + 0.5 - rounding_offset_y);
double return_val =
static_cast<double>(edge.bot.x) +
edge.dx * (static_cast<double>(current_y - edge.bot.y) + 0.5 - rounding_offset_y);
T value = round_towards_min<T>(return_val);
return value;
}
@@ -170,8 +172,9 @@ inline T get_edge_max_x(edge<T> const& edge, const T current_y) {
if (current_y == edge.bot.y) {
return edge.bot.x;
} else {
double return_val = static_cast<double>(edge.bot.x) +
edge.dx * (static_cast<double>(current_y - edge.bot.y) + 0.5 - rounding_offset_y);
double return_val =
static_cast<double>(edge.bot.x) +
edge.dx * (static_cast<double>(current_y - edge.bot.y) + 0.5 - rounding_offset_y);
T value = round_towards_max<T>(return_val);
return value;
}
@@ -184,14 +187,14 @@ void hot_pixel_set_left_to_right(T y,
T end_x,
bound<T>& bnd,
ring_manager<T>& rings,
hot_pixel_itr<T> & itr,
hot_pixel_itr<T> & end,
hot_pixel_itr<T>& itr,
hot_pixel_itr<T>& end,
bool add_end_point) {
T x_min = get_edge_min_x(*(bnd.current_edge), y);
x_min = std::max(x_min, start_x);
T x_max = get_edge_max_x(*(bnd.current_edge), y);
x_max = std::min(x_max, end_x);
for (;itr != end; ++itr) {
for (; itr != end; ++itr) {
if (itr->x < x_min) {
continue;
}
@@ -221,16 +224,16 @@ void hot_pixel_set_right_to_left(T y,
T end_x,
bound<T>& bnd,
ring_manager<T>& rings,
hot_pixel_rev_itr<T> & itr,
hot_pixel_rev_itr<T> & end,
hot_pixel_rev_itr<T>& itr,
hot_pixel_rev_itr<T>& end,
bool add_end_point) {
T x_min = get_edge_min_x(*(bnd.current_edge), y);
x_min = std::max(x_min, end_x);
T x_max = get_edge_max_x(*(bnd.current_edge), y);
x_max = std::min(x_max, start_x);
for (;itr != end; ++itr) {
for (; itr != end; ++itr) {
if (itr->x > x_max) {
continue;
continue;
}
if (itr->x < x_min) {
break;
@@ -267,10 +270,6 @@ void insert_hot_pixels_in_path(bound<T>& bnd,
if (end_pt == bnd.last_point) {
return;
}
if (!bnd.ring) {
bnd.last_point = end_pt;
return;
}
T start_y = bnd.last_point.y;
T start_x = bnd.last_point.x;
@@ -336,11 +335,8 @@ void add_first_point(active_bound_list_itr<T>& bnd,
ring_ptr<T> r = create_new_ring(rings);
(*bnd)->ring = r;
r->is_open = ((*bnd)->winding_delta == 0);
r->points = create_new_point(r, pt, rings);
if (!r->is_open) {
set_hole_state(bnd, active_bounds, rings);
}
set_hole_state(bnd, active_bounds, rings);
(*bnd)->last_point = pt;
}
@@ -352,11 +348,8 @@ void add_first_point(active_bound_list_rev_itr<T>& bnd,
ring_ptr<T> r = create_new_ring(rings);
// no ring currently set!
(*bnd)->ring = r;
r->is_open = ((*bnd)->winding_delta == 0);
r->points = create_new_point(r, pt, rings);
if (!r->is_open) {
set_hole_state(bnd, active_bounds, rings);
}
set_hole_state(bnd, active_bounds, rings);
(*bnd)->last_point = pt;
}
@@ -556,7 +549,7 @@ ring_ptr<T> get_lower_most_ring(ring_ptr<T> outRec1, ring_ptr<T> outRec2) {
}
template <typename T>
bool ring1_right_of_ring2(ring_ptr<T> ring1, ring_ptr<T> ring2) {
bool ring1_child_below_ring2(ring_ptr<T> ring1, ring_ptr<T> ring2) {
do {
ring1 = ring1->parent;
if (ring1 == ring2) {
@@ -588,12 +581,12 @@ void append_ring(active_bound_list_itr<T>& b1,
bound_ptr<T> keep_bound;
ring_ptr<T> remove_ring;
bound_ptr<T> remove_bound;
if (ring1_right_of_ring2(outRec1, outRec2)) {
if (ring1_child_below_ring2(outRec1, outRec2)) {
keep_ring = outRec2;
keep_bound = *b2;
remove_ring = outRec1;
remove_bound = *b1;
} else if (ring1_right_of_ring2(outRec2, outRec1)) {
} else if (ring1_child_below_ring2(outRec2, outRec1)) {
keep_ring = outRec1;
keep_bound = *b1;
remove_ring = outRec2;
@@ -688,9 +681,6 @@ void add_local_maximum_point(active_bound_list_itr<T>& b1,
active_bound_list<T>& active_bounds) {
insert_hot_pixels_in_path(*(*b2), pt, rings, false);
add_point(b1, active_bounds, pt, rings);
if ((*b2)->winding_delta == 0) {
add_point(b2, active_bounds, pt, rings);
}
if ((*b1)->ring == (*b2)->ring) {
(*b1)->ring = nullptr;
(*b2)->ring = nullptr;
@@ -881,7 +871,9 @@ point_in_polygon_result inside_or_outside_special(point_ptr<T> first_pt, point_p
}
template <typename T>
bool poly2_contains_poly1(point_ptr<T> outpt1, point_ptr<T> outpt2) {
bool poly2_contains_poly1(ring_ptr<T> ring1, ring_ptr<T> ring2) {
point_ptr<T> outpt1 = ring1->points->next;
point_ptr<T> outpt2 = ring2->points->next;
point_ptr<T> op = outpt1;
do {
// nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
@@ -907,7 +899,6 @@ void dispose_out_points(point_ptr<T>& pp) {
tmpPp->next = tmpPp;
tmpPp->prev = tmpPp;
tmpPp->ring = nullptr;
// delete tmpPp;
}
}
}
+27 -29
View File
@@ -1,9 +1,9 @@
#pragma once
#include <mapbox/geometry/wagyu/active_bound_list.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/bound.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/intersect.hpp>
#include <mapbox/geometry/wagyu/intersect_util.hpp>
#include <mapbox/geometry/wagyu/ring.hpp>
@@ -30,11 +30,14 @@ void process_hot_pixel_intersections(T top_y,
auto bnd = active_bounds.begin();
auto bnd_next = std::next(bnd);
while (bnd_next != active_bounds.end()) {
if ((*bnd)->current_x > (*bnd_next)->current_x && !slopes_equal(*(*bnd)->current_edge, *(*bnd_next)->current_edge)) {
if ((*bnd)->current_x > (*bnd_next)->current_x &&
!slopes_equal(*(*bnd)->current_edge, *(*bnd_next)->current_edge)) {
mapbox::geometry::point<double> pt;
if (!get_edge_intersection<T, double>(*((*bnd)->current_edge),
*((*bnd_next)->current_edge), pt)) {
*((*bnd_next)->current_edge), pt)) {
// LCOV_EXCL_START
throw std::runtime_error("Edges do not intersect!");
// LCOV_EXCL_END
}
add_to_hot_pixels(round_point<T>(pt), rings);
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
@@ -55,16 +58,20 @@ void process_hot_pixel_edges_at_top_of_scanbeam(T top_y,
ring_manager<T>& rings) {
for (auto bnd = active_bounds.begin(); bnd != active_bounds.end();) {
auto bnd_2 = std::next(bnd);
while ((*bnd)->current_edge != (*bnd)->edges.end() && (*bnd)->current_edge->top.y == top_y) {
while ((*bnd)->current_edge != (*bnd)->edges.end() &&
(*bnd)->current_edge->top.y == top_y) {
add_to_hot_pixels((*bnd)->current_edge->top, rings);
if (current_edge_is_horizontal<T>(bnd)) {
(*bnd)->current_x = static_cast<double>((*bnd)->current_edge->top.x);
if ((*bnd)->current_edge->bot.x < (*bnd)->current_edge->top.x) {
// left to right
auto bnd_next = std::next(bnd);
while (bnd_next != active_bounds.end() && (*bnd_next)->current_x < (*bnd)->current_x) {
if (std::llround((*bnd_next)->current_edge->top.y) != top_y && std::llround((*bnd_next)->current_edge->bot.y) != top_y) {
mapbox::geometry::point<T> pt(std::llround((*bnd_next)->current_x), top_y);
while (bnd_next != active_bounds.end() &&
(*bnd_next)->current_x < (*bnd)->current_x) {
if (std::llround((*bnd_next)->current_edge->top.y) != top_y &&
std::llround((*bnd_next)->current_edge->bot.y) != top_y) {
mapbox::geometry::point<T> pt(std::llround((*bnd_next)->current_x),
top_y);
add_to_hot_pixels(pt, rings);
}
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
@@ -74,9 +81,12 @@ void process_hot_pixel_edges_at_top_of_scanbeam(T top_y,
// right to left
if (bnd != active_bounds.begin()) {
auto bnd_prev = std::prev(bnd);
while (bnd != active_bounds.begin() && (*bnd_prev)->current_x > (*bnd)->current_x) {
if (std::llround((*bnd_prev)->current_edge->top.y) != top_y && std::llround((*bnd_prev)->current_edge->bot.y) != top_y) {
mapbox::geometry::point<T> pt(std::llround((*bnd_prev)->current_x), top_y);
while (bnd != active_bounds.begin() &&
(*bnd_prev)->current_x > (*bnd)->current_x) {
if (std::llround((*bnd_prev)->current_edge->top.y) != top_y &&
std::llround((*bnd_prev)->current_edge->bot.y) != top_y) {
mapbox::geometry::point<T> pt(std::llround((*bnd_prev)->current_x),
top_y);
add_to_hot_pixels(pt, rings);
}
swap_positions_in_ABL(bnd, bnd_prev, active_bounds);
@@ -96,18 +106,13 @@ void process_hot_pixel_edges_at_top_of_scanbeam(T top_y,
template <typename T>
void insert_local_minima_into_ABL_hot_pixel(T top_y,
local_minimum_ptr_list<T> & minima_sorted,
local_minimum_ptr_list_itr<T> & lm,
local_minimum_ptr_list<T>& minima_sorted,
local_minimum_ptr_list_itr<T>& lm,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings,
scanbeam_list<T>& scanbeam) {
while (lm != minima_sorted.end() && (*lm)->y == top_y) {
if ((*lm)->left_bound.edges.empty() || (*lm)->right_bound.edges.empty()) {
++lm;
continue;
}
add_to_hot_pixels((*lm)->left_bound.edges.front().bot, rings);
add_to_hot_pixels((*lm)->left_bound.edges.front().bot, rings);
auto& left_bound = (*lm)->left_bound;
left_bound.current_edge = left_bound.edges.begin();
left_bound.current_x = static_cast<double>(left_bound.current_edge->bot.x);
@@ -127,12 +132,7 @@ void insert_local_minima_into_ABL_hot_pixel(T top_y,
}
template <typename T>
void build_hot_pixels(local_minimum_list<T>& minima_list,
ring_manager<T>& rings) {
if (minima_list.empty()) {
return;
}
void build_hot_pixels(local_minimum_list<T>& minima_list, ring_manager<T>& rings) {
active_bound_list<T> active_bounds;
scanbeam_list<T> scanbeam;
T scanline_y = std::numeric_limits<T>::max();
@@ -149,7 +149,7 @@ void build_hot_pixels(local_minimum_list<T>& minima_list,
// Estimate size for reserving hot pixels
std::size_t reserve = 0;
for (auto & lm : minima_list) {
for (auto& lm : minima_list) {
reserve += lm.left_bound.edges.size() + 2;
reserve += lm.right_bound.edges.size() + 2;
}
@@ -160,15 +160,13 @@ void build_hot_pixels(local_minimum_list<T>& minima_list,
process_hot_pixel_intersections(scanline_y, active_bounds, rings);
insert_local_minima_into_ABL_hot_pixel(scanline_y, minima_sorted, current_lm, active_bounds,
rings, scanbeam);
rings, scanbeam);
process_hot_pixel_edges_at_top_of_scanbeam(scanline_y, scanbeam, active_bounds, rings);
}
preallocate_point_memory(rings, rings.hot_pixels.size());
sort_hot_pixels(rings);
}
}
}
}
+152 -98
View File
@@ -28,22 +28,19 @@ struct point_ptr_pair {
point_ptr<T> op1;
point_ptr<T> op2;
constexpr point_ptr_pair(point_ptr<T> o1, point_ptr<T> o2)
: op1(o1),
op2(o2) {}
constexpr point_ptr_pair(point_ptr<T> o1, point_ptr<T> o2) : op1(o1), op2(o2) {
}
point_ptr_pair(point_ptr_pair<T> const& p) = default;
point_ptr_pair(point_ptr_pair<T> && p)
: op1(std::move(p.op1)),
op2(std::move(p.op2)) {}
point_ptr_pair(point_ptr_pair<T>&& p) : op1(std::move(p.op1)), op2(std::move(p.op2)) {
}
point_ptr_pair& operator=(point_ptr_pair<T> && p) {
point_ptr_pair& operator=(point_ptr_pair<T>&& p) {
op1 = std::move(p.op1);
op2 = std::move(p.op2);
return *this;
}
};
#ifdef DEBUG
@@ -202,19 +199,65 @@ void remove_spikes(point_ptr<T>& pt) {
}
template <typename T>
void fixup_children(ring_ptr<T> old_ring, ring_ptr<T> new_ring) {
void fixup_children_complex(ring_ptr<T> old_ring,
ring_ptr<T> new_ring,
ring_vector<T> const& grand_children,
ring_manager<T> const& rings) {
// Tests if any of the children from the old ring are now children of the new ring
assert(old_ring != new_ring);
for (auto r = old_ring->children.begin(); r != old_ring->children.end();) {
assert((*r)->points);
assert((*r) != old_ring);
if ((*r) != new_ring && !ring1_right_of_ring2(new_ring, (*r)) &&
poly2_contains_poly1((*r)->points, new_ring->points)) {
if ((*r) == new_ring) {
++r;
continue;
}
if (poly2_contains_poly1(*r, new_ring)) {
(*r)->parent = new_ring;
new_ring->children.push_back((*r));
r = old_ring->children.erase(r);
} else {
} else if (poly2_contains_poly1(*r, old_ring)) {
++r;
} else {
// Rare situation where one of old_rings's previous grand children
// should actually contain this ring.
bool found = false;
for (auto const& gc : grand_children) {
if (poly2_contains_poly1(*r, gc)) {
(*r)->parent = gc;
gc->children.push_back((*r));
r = old_ring->children.erase(r);
found = true;
break;
}
}
if (!found) {
if (old_ring->parent == nullptr) {
for (auto const& r2 : rings.children) {
if (r2 != new_ring && r2 != old_ring && r2->points && r2 != (*r) &&
poly2_contains_poly1(*r, r2)) {
(*r)->parent = r2;
r2->children.push_back((*r));
r = old_ring->children.erase(r);
found = true;
break;
}
}
} else {
for (auto const& r2 : old_ring->parent->children) {
if (r2 != new_ring && r2 != old_ring && r2->points && r2 != (*r) &&
poly2_contains_poly1((*r), r2)) {
(*r)->parent = r2;
r2->children.push_back((*r));
r = old_ring->children.erase(r);
found = true;
break;
}
}
}
}
if (!found) {
throw std::runtime_error("No proper parent for child ring found");
}
}
}
}
@@ -266,16 +309,7 @@ bool fix_intersects(std::unordered_multimap<ring_ptr<T>, point_ptr_pair<T>>& dup
if (ring_parent != ring_search->parent) {
// The two holes do not have the same parent, do not add them
// simply return!
if (ring_parent->parent != ring_search &&
poly2_contains_poly1(ring_search->points, ring_parent->points) &&
!ring1_right_of_ring2(ring_search, ring_parent)) {
ring_ptr<T> old_parent = ring_search->parent;
ring_search->parent = ring_parent;
old_parent->children.remove(ring_search);
ring_parent->children.push_back(ring_search);
} else {
return false;
}
return false;
}
bool found = false;
std::list<std::pair<ring_ptr<T>, point_ptr_pair<T>>> iList;
@@ -459,11 +493,15 @@ bool fix_intersects(std::unordered_multimap<ring_ptr<T>, point_ptr_pair<T>>& dup
ring_origin->bottom_point = nullptr;
ring_vector<T> grand_children;
for (auto& iRing : iList) {
ring_ptr<T> ring_itr = iRing.first;
ring_itr->points = nullptr;
ring_itr->area = std::numeric_limits<double>::quiet_NaN();
ring_itr->bottom_point = nullptr;
for (auto& c : ring_itr->children) {
grand_children.push_back(c);
}
if (ring_is_hole(ring_origin)) {
ring1_replaces_ring2(ring_origin, ring_itr, rings);
} else {
@@ -473,8 +511,8 @@ bool fix_intersects(std::unordered_multimap<ring_ptr<T>, point_ptr_pair<T>>& dup
if (ring_is_hole(ring_origin)) {
ring_new->parent = ring_origin;
ring_new->parent->children.push_back(ring_new);
fixup_children(ring_origin, ring_new);
fixup_children(ring_parent, ring_new);
fixup_children_complex(ring_origin, ring_new, grand_children, rings);
fixup_children_complex(ring_parent, ring_new, grand_children, rings);
} else {
ring_new->parent = ring_origin->parent;
if (ring_new->parent == nullptr) {
@@ -482,7 +520,7 @@ bool fix_intersects(std::unordered_multimap<ring_ptr<T>, point_ptr_pair<T>>& dup
} else {
ring_new->parent->children.push_back(ring_new);
}
fixup_children(ring_origin, ring_new);
fixup_children_complex(ring_origin, ring_new, grand_children, rings);
}
}
@@ -601,6 +639,58 @@ bool parent_in_tree(ring_ptr<T> r, ring_ptr<T> possible_parent) {
return false;
}
template <typename T>
void fixup_children_sibling(ring_ptr<T> old_ring, ring_ptr<T> new_ring) {
for (auto r = old_ring->children.begin(); r != old_ring->children.end();) {
if ((*r) == new_ring) {
++r;
continue;
}
if (poly2_contains_poly1(*r, new_ring)) {
(*r)->parent = new_ring;
new_ring->children.push_back((*r));
r = old_ring->children.erase(r);
} else {
++r;
}
}
}
template <typename T>
void fixup_parents_siblings(ring_ptr<T> parent, ring_ptr<T> ring, ring_manager<T>& rings) {
bool parent_ring_area_is_positive = area(parent) > 0.0;
if (parent->parent == nullptr) {
for (auto r = rings.children.begin(); r != rings.children.end();) {
assert((*r)->points);
bool ring_area_is_positive = area((*r)) > 0.0;
if ((*r) != parent && ring_area_is_positive == parent_ring_area_is_positive &&
poly2_contains_poly1(ring, (*r))) {
ring->parent = (*r);
(*r)->children.push_back(ring);
parent->children.remove(ring);
break;
} else {
++r;
}
}
} else {
ring_ptr<T> grand_parent = parent->parent;
for (auto r = grand_parent->children.begin(); r != grand_parent->children.end();) {
assert((*r)->points);
bool ring_area_is_positive = area((*r)) > 0.0;
if ((*r) != parent && ring_area_is_positive == parent_ring_area_is_positive &&
poly2_contains_poly1(ring, (*r))) {
ring->parent = (*r);
(*r)->children.push_back(ring);
parent->children.remove(ring);
break;
} else {
++r;
}
}
}
}
template <typename T>
void fixup_children_new_interior_ring(ring_ptr<T> old_ring,
ring_ptr<T> new_ring,
@@ -614,7 +704,7 @@ void fixup_children_new_interior_ring(ring_ptr<T> old_ring,
assert((*r)->points);
bool ring_area_is_positive = area((*r)) > 0.0;
if ((*r) != new_ring && ring_area_is_positive == old_ring_area_is_positive &&
poly2_contains_poly1((*r)->points, new_ring->points)) {
poly2_contains_poly1((*r), new_ring)) {
(*r)->parent = new_ring;
new_ring->children.push_back((*r));
r = rings.children.erase(r);
@@ -629,7 +719,7 @@ void fixup_children_new_interior_ring(ring_ptr<T> old_ring,
assert((*r) != parent);
bool ring_area_is_positive = area((*r)) > 0.0;
if ((*r) != new_ring && ring_area_is_positive == old_ring_area_is_positive &&
poly2_contains_poly1((*r)->points, new_ring->points)) {
poly2_contains_poly1((*r), new_ring)) {
(*r)->parent = new_ring;
new_ring->children.push_back((*r));
r = parent->children.erase(r);
@@ -804,23 +894,23 @@ void handle_self_intersections(point_ptr<T> op,
}
update_points_ring(ring);
update_points_ring(new_ring);
if (poly2_contains_poly1(new_ring->points, ring->points)) {
// This is the situation where there is the new ring is
// created inside the ring. Later on this should be inherited
// as child of a newly created hole. However, we should check existing
// holes of this polygon to see if they might belong inside this polygon.
new_ring->parent = ring;
new_ring->parent->children.push_back(new_ring);
fixup_children(ring, new_ring);
// Polygons are completely seperate
new_ring->parent = ring->parent;
if (new_ring->parent == nullptr) {
rings.children.push_back(new_ring);
} else {
// Polygons are completely seperate
new_ring->parent = ring->parent;
if (new_ring->parent == nullptr) {
rings.children.push_back(new_ring);
} else {
new_ring->parent->children.push_back(new_ring);
new_ring->parent->children.push_back(new_ring);
}
fixup_children_sibling(ring, new_ring);
// The parent might need to be reassigned in rare situations
if (ring->parent) {
if (!poly2_contains_poly1(ring, ring->parent)) {
// Parent ring split on outside - search parent's siblings
fixup_parents_siblings(ring->parent, ring, rings);
} else if (!poly2_contains_poly1(new_ring, ring->parent)) {
// child ring split on the outside
fixup_parents_siblings(ring->parent, new_ring, rings);
}
fixup_children(ring, new_ring);
}
}
update_duplicate_point_entries(ring, dupe_ring);
@@ -1190,7 +1280,8 @@ bool clockwise_of_next(point_ptr<T> const& origin, point_ptr<T> pt) {
} else if (ot_next_prev == orientation_collinear_line) {
// This shouldn't happen?
// LCOV_EXCL_START
throw std::runtime_error("Impossible situation reached in clockwise_of_next - 2");
throw std::runtime_error(
"Impossible situation reached in clockwise_of_next - 2");
// LCOV_EXCL_END
} else {
// Pt next is counter clockwise of origin prev
@@ -1548,7 +1639,6 @@ bool process_repeated_point_set(std::size_t first_index,
std::unordered_multimap<ring_ptr<T>, point_ptr_pair<T>>& dupe_ring,
ring_manager<T>& rings) {
point_ptr<T> point_1 = rings.all_points[current_index];
if (point_1->ring == nullptr) {
return false;
}
@@ -1576,8 +1666,10 @@ bool process_repeated_point_set(std::size_t first_index,
if (ot_next == orientation_collinear_spike) {
orientation_type ot_prev = orientation_of_points(point_2, point_2->prev, point_3->prev);
if (ot_prev == orientation_collinear_spike) {
// Start at point_1 and we will travel around the circle until we find another point at
// the same location. We will measure its area, and then continue till the next point at
// Start at point_1 and we will travel around the circle until we find another point
// at
// the same location. We will measure its area, and then continue till the next
// point at
// the same location. The smallest absolute value of area is the one we will use.
point_ptr<T> point_a = point_1;
point_ptr<T> min_a = nullptr;
@@ -1586,7 +1678,8 @@ bool process_repeated_point_set(std::size_t first_index,
double area = 0.0;
double min_area = std::numeric_limits<double>::max();
while (pt != point_1) {
area += static_cast<double>(pt->prev->x + pt->x) * static_cast<double>(pt->prev->y - pt->y);
area += static_cast<double>(pt->prev->x + pt->x) *
static_cast<double>(pt->prev->y - pt->y);
if (*pt == *point_1) {
if (std::fabs(area) < min_area) {
min_area = std::fabs(area);
@@ -1603,7 +1696,8 @@ bool process_repeated_point_set(std::size_t first_index,
throw std::runtime_error("No other point was between point_1 on the path");
// LCOV_EXCL_END
}
area += static_cast<double>(pt->prev->x + pt->x) * static_cast<double>(pt->prev->y - pt->y);
area += static_cast<double>(pt->prev->x + pt->x) *
static_cast<double>(pt->prev->y - pt->y);
if (std::fabs(area) < min_area) {
min_area = std::fabs(area);
min_a = point_a;
@@ -1659,7 +1753,7 @@ void process_repeated_points(std::size_t first_index,
}
}
}
// LCOV_EXCL_STOP
// LCOV_EXCL_END
#endif
}
@@ -1721,14 +1815,10 @@ bool index_is_after_point(std::size_t const& i,
return false;
}
if (rings.all_points[i]->y < pt.y) {
return true;
} else if (rings.all_points[i]->y > pt.y) {
return false;
} else if (rings.all_points[i]->x >= pt.x) {
return true;
if (rings.all_points[i]->y == pt.y) {
return rings.all_points[i]->x >= pt.x;
} else {
return false;
return rings.all_points[i]->y < pt.y;
}
}
@@ -1771,35 +1861,6 @@ void remove_spikes_in_polygons(ring_ptr<T> r, ring_manager<T>& rings) {
}
}
template <typename T>
void fixup_out_polyline(ring<T>& ring, ring_manager<T>& rings) {
point_ptr<T> pp = ring.points;
point_ptr<T> lastPP = pp->prev;
while (pp != lastPP) {
pp = pp->next;
if (*pp == *pp->prev) {
if (pp == lastPP)
lastPP = pp->prev;
point_ptr<T> tmpPP = pp->prev;
tmpPP->next = pp->next;
pp->next->prev = tmpPP;
// delete pp;
pp->next = pp;
pp->prev = pp;
pp->ring = nullptr;
pp = tmpPP;
}
}
if (pp == pp->prev) {
remove_ring(&ring, rings);
dispose_out_points(pp);
ring.points = nullptr;
return;
}
}
template <typename T>
void fixup_out_polygon(ring<T>& ring, ring_manager<T>& rings) {
// FixupOutPolygon() - removes duplicate points and simplifies consecutive
@@ -1820,8 +1881,7 @@ void fixup_out_polygon(ring<T>& ring, ring_manager<T>& rings) {
}
// test for duplicate points and collinear edges ...
if ((*pp == *pp->next) || (*pp == *pp->prev) ||
(slopes_equal(*pp->prev, *pp, *pp->next))) {
if ((*pp == *pp->next) || (*pp == *pp->prev) || (slopes_equal(*pp->prev, *pp, *pp->next))) {
lastOK = nullptr;
point_ptr<T> tmp = pp;
pp->prev->next = pp->next;
@@ -1842,13 +1902,11 @@ void fixup_out_polygon(ring<T>& ring, ring_manager<T>& rings) {
ring.points = pp;
}
template <typename T>
void do_simple_polygons(ring_manager<T>& rings) {
// fix orientations ...
for (auto& r : rings.rings) {
if (!r.points || r.is_open) {
if (!r.points) {
continue;
}
std::size_t s = 0;
@@ -1904,7 +1962,7 @@ void do_simple_polygons(ring_manager<T>& rings) {
#if DEBUG
// LCOV_EXCL_START
for (auto& r : rings.rings) {
if (!r.points || r.is_open) {
if (!r.points) {
continue;
}
double stored_area = area(&r);
@@ -1914,18 +1972,14 @@ void do_simple_polygons(ring_manager<T>& rings) {
throw std::runtime_error("Difference in stored area vs calculated area!");
}
}
// LCOV_EXCL_END
// LCOV_EXCL_END
#endif
for (auto& r : rings.rings) {
if (!r.points || r.is_open) {
if (!r.points) {
continue;
}
fixup_out_polygon(r, rings);
if (ring_is_hole(&r) == (area(&r) > 0.0)) {
reverse_ring(r.points);
r.area = std::numeric_limits<double>::quiet_NaN();
}
}
}
}
-4
View File
@@ -46,10 +46,6 @@ inline bool greater_than_or_equal(double x, double y) {
return x > y || values_are_equal(x, y);
}
inline bool less_than_or_equal(double x, double y) {
return x < y || values_are_equal(x, y);
}
template <typename T>
bool slopes_equal(mapbox::geometry::point<T> const& pt1,
mapbox::geometry::point<T> const& pt2,
+5 -8
View File
@@ -5,7 +5,6 @@
#include <mapbox/geometry/wagyu/active_bound_list.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/exceptions.hpp>
#include <mapbox/geometry/wagyu/intersect_util.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <mapbox/geometry/wagyu/local_minimum_util.hpp>
@@ -29,7 +28,7 @@ bool execute_vatti(local_minimum_list<T>& minima_list,
if (minima_list.empty()) {
return false;
}
active_bound_list<T> active_bounds;
scanbeam_list<T> scanbeam;
T scanline_y = std::numeric_limits<T>::max();
@@ -48,8 +47,8 @@ bool execute_vatti(local_minimum_list<T>& minima_list,
while (pop_from_scanbeam(scanline_y, scanbeam) || current_lm != minima_sorted.end()) {
process_intersections(scanline_y, active_bounds, cliptype,
subject_fill_type, clip_fill_type, rings);
process_intersections(scanline_y, active_bounds, cliptype, subject_fill_type,
clip_fill_type, rings);
update_current_hp_itr(scanline_y, rings);
@@ -63,10 +62,8 @@ bool execute_vatti(local_minimum_list<T>& minima_list,
// Next we will add local minima bounds to the active bounds list that are on the local
// minima queue at
// this current scanline_y
insert_local_minima_into_ABL(scanline_y, minima_sorted, current_lm, active_bounds,
rings, scanbeam, cliptype, subject_fill_type,
clip_fill_type);
insert_local_minima_into_ABL(scanline_y, minima_sorted, current_lm, active_bounds, rings,
scanbeam, cliptype, subject_fill_type, clip_fill_type);
}
// std::clog << rings.rings << std::endl;
// std::clog << output_as_polygon(rings.all_rings[0]);
+6 -16
View File
@@ -7,8 +7,8 @@
#include <mapbox/geometry/multi_polygon.hpp>
#include <mapbox/geometry/polygon.hpp>
#include <mapbox/geometry/wagyu/build_result.hpp>
#include <mapbox/geometry/wagyu/build_local_minima_list.hpp>
#include <mapbox/geometry/wagyu/build_result.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <mapbox/geometry/wagyu/snap_rounding.hpp>
@@ -25,28 +25,19 @@ private:
using value_type = T;
local_minimum_list<value_type> minima_list;
bool has_open_paths;
bool reverse_output;
wagyu( wagyu const& ) = delete;
wagyu& operator=(wagyu const& ) = delete;
wagyu(wagyu const&) = delete;
wagyu& operator=(wagyu const&) = delete;
public:
wagyu() : minima_list(), has_open_paths(false), reverse_output(false) {
wagyu() : minima_list(), reverse_output(false) {
}
~wagyu() {
clear();
}
bool add_line(mapbox::geometry::line_string<value_type> const& pg) {
bool success = add_line_string(pg, minima_list);
if (success) {
has_open_paths = true;
}
return success;
}
bool add_ring(mapbox::geometry::linear_ring<value_type> const& pg,
polygon_type p_type = polygon_type_subject) {
return add_linear_ring(pg, minima_list, p_type);
@@ -69,7 +60,6 @@ public:
void clear() {
minima_list.clear();
has_open_paths = false;
}
mapbox::geometry::box<value_type> get_bounds() {
@@ -122,13 +112,13 @@ public:
fill_type clip_fill_type) {
ring_manager<T> rings;
build_hot_pixels(minima_list, rings);
if (!execute_vatti(minima_list, rings, cliptype, subject_fill_type, clip_fill_type)) {
return false;
}
do_simple_polygons(rings);
build_result(solution, rings, reverse_output);