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 "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue