integrate segment tree, fix some bugs

This commit is contained in:
Maximilian Keßler 2022-04-16 12:02:27 +02:00
parent aac97307e9
commit cdfaeb668d
2 changed files with 16 additions and 24 deletions

View file

@ -7,6 +7,7 @@
#include "geometry.h" #include "geometry.h"
#include "areas.h" #include "areas.h"
#include "segment_tree.h"
Unit get_area_union(std::vector<Rectangle> rectangles) { Unit get_area_union(std::vector<Rectangle> rectangles) {
@ -15,9 +16,6 @@ Unit get_area_union(std::vector<Rectangle> rectangles) {
assert(rect.bottom_left.x <= rect.top_right.x); assert(rect.bottom_left.x <= rect.top_right.x);
assert(rect.bottom_left.y <= rect.top_right.y); assert(rect.bottom_left.y <= rect.top_right.y);
} }
// entry i will describe coverage of the interval (x_points[i], x_points[i+1])
std::vector<unsigned> coverage_numbers;
coverage_numbers.reserve(2*rectangles.size() -1);
//sorted vector of all x coordinates of all rectangles //sorted vector of all x coordinates of all rectangles
std::vector<RectCoord> x_points; std::vector<RectCoord> x_points;
@ -48,39 +46,33 @@ Unit get_area_union(std::vector<Rectangle> rectangles) {
} }
std::sort(y_points.begin(), y_points.end()); std::sort(y_points.begin(), y_points.end());
// run sweepline // init data and run sweepline
Unit current_cross_section_length = 0;
Unit total_area = 0; Unit total_area = 0;
SegmentTree segmentTree(x_points);
for(Index y_index = 0 ; y_index < y_points.size() ; ++y_index) { for(Index y_index = 0 ; y_index < y_points.size() ; ++y_index) {
// first, update cross section // first, update cross section
if (y_points[y_index].rect->bottom_left.y == y_points[y_index].coord) { if (y_points[y_index].rect->bottom_left.y == y_points[y_index].coord) {
// rectangle is starting now, add its cross section // rectangle is starting now, add its cross section
for (Index index = y_points[y_index].rect->i_left; index < y_points[y_index].rect->i_right; ++index) { segmentTree.add_interval(
++coverage_numbers[index]; {x_points[y_points[y_index].rect->i_left].coord,
if (coverage_numbers[index] == 1) { x_points[y_points[y_index].rect->i_right].coord}
current_cross_section_length += (x_points[index + 1].coord - x_points[index].coord); );
}
}
} else { } else {
assert(y_points[y_index].rect->top_right.y == y_points[y_index].coord); assert(y_points[y_index].rect->top_right.y == y_points[y_index].coord);
// rectangle stopping, remove its cross section // rectangle stopping, remove its cross section
for (Index index = y_points[y_index].rect->i_left; index < y_points[y_index].rect->i_right; ++index) { segmentTree.remove_interval(
--coverage_numbers[index]; {x_points[y_points[y_index].rect->i_left].coord,
if (coverage_numbers[index] == 0) { x_points[y_points[y_index].rect->i_right].coord}
current_cross_section_length -= (x_points[index + 1].coord - x_points[index].coord); );
}
}
} }
//cross section is now up to date //cross section is now up to date
if(y_index + 1 < y_points.size()) { if(y_index + 1 < y_points.size()) {
// add area up to next y point // add area up to next y point
total_area += current_cross_section_length * (y_points[y_index+1].coord - y_points[y_index].coord); total_area += segmentTree.length_covered_intervals();
} }
} }
// sanity check that nothing is covered when arriving at the end // TODO: sanity check that nothing is covered when arriving at the end
for(auto coverage : coverage_numbers) {
assert(coverage == 0);
}
return total_area; return total_area;
} }

View file

@ -15,7 +15,7 @@ SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
size_t num_meta_nodes = std::bit_ceil(num_leaf_nodes) - 1; size_t num_meta_nodes = std::bit_ceil(num_leaf_nodes) - 1;
// Initialize all nodes with zero coverage and dummy interval // Initialize all nodes with zero coverage and dummy interval
_nodes.resize(2 * num_meta_nodes - 1, {0, coords[num_leaf_nodes].coord, coords[num_leaf_nodes].coord}); _nodes.resize(2 * num_meta_nodes + 1, {0, coords[num_leaf_nodes].coord, coords[num_leaf_nodes].coord});
// We initialize the tree from bottom up, keeping track of the index ranges // We initialize the tree from bottom up, keeping track of the index ranges
// and the length of the corresponding segment // and the length of the corresponding segment
@ -25,7 +25,7 @@ SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
_nodes[leaf_node_idx + num_meta_nodes].right_coord = coords[leaf_node_idx +1].coord; _nodes[leaf_node_idx + num_meta_nodes].right_coord = coords[leaf_node_idx +1].coord;
} }
// Note that there are remaining leafs that represent dummy ranges // Note that there are remaining leafs that represent dummy ranges
for(Index node_idx = num_meta_nodes - 1; node_idx >= 0; ++node_idx) { for(Index node_idx = num_meta_nodes - 1; node_idx != -1 ; --node_idx) {
_nodes[node_idx].left_coord = left_child(node_idx).left_coord; _nodes[node_idx].left_coord = left_child(node_idx).left_coord;
_nodes[node_idx].right_coord = right_child(node_idx).right_coord; _nodes[node_idx].right_coord = right_child(node_idx).right_coord;
} }