integrate segment tree, fix some bugs
This commit is contained in:
parent
aac97307e9
commit
cdfaeb668d
2 changed files with 16 additions and 24 deletions
36
areas.cpp
36
areas.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue