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 "areas.h"
#include "segment_tree.h"
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.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
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());
// run sweepline
Unit current_cross_section_length = 0;
// init data and run sweepline
Unit total_area = 0;
SegmentTree segmentTree(x_points);
for(Index y_index = 0 ; y_index < y_points.size() ; ++y_index) {
// first, update cross section
if (y_points[y_index].rect->bottom_left.y == y_points[y_index].coord) {
// 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) {
++coverage_numbers[index];
if (coverage_numbers[index] == 1) {
current_cross_section_length += (x_points[index + 1].coord - x_points[index].coord);
}
}
segmentTree.add_interval(
{x_points[y_points[y_index].rect->i_left].coord,
x_points[y_points[y_index].rect->i_right].coord}
);
} else {
assert(y_points[y_index].rect->top_right.y == y_points[y_index].coord);
// 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) {
--coverage_numbers[index];
if (coverage_numbers[index] == 0) {
current_cross_section_length -= (x_points[index + 1].coord - x_points[index].coord);
}
}
segmentTree.remove_interval(
{x_points[y_points[y_index].rect->i_left].coord,
x_points[y_points[y_index].rect->i_right].coord}
);
}
//cross section is now up to date
if(y_index + 1 < y_points.size()) {
// 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
for(auto coverage : coverage_numbers) {
assert(coverage == 0);
}
// TODO: sanity check that nothing is covered when arriving at the end
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;
// 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
// 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;
}
// 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].right_coord = right_child(node_idx).right_coord;
}