-
Notifications
You must be signed in to change notification settings - Fork 0
/
BSPTree.h
executable file
·134 lines (109 loc) · 3.86 KB
/
BSPTree.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef BSPTree_h
#define BSPTree_h
/**
BSPTree.h
Description:
This structure divides entire map into convex areas. It is used for drawing walls
in right order near -> far. BSP tree is builded from list of walls which forms
areas called sectors. If every sector is convex, there is no need to divide any area.
Otherwise a cut must be made. In order to do this, algorithm try division along every
wall in map and save its weight (a heuristics is used to determine the best cut). Than
the wall with the lowest weight is used to cut the map into two halves.
Convex sub-sectors are stored in leafs. Inner nodes hold division line and bounding box.
Bounding box is implemented here, but is not used futher in this program, because it
is fast enough, so why bother.
*/
#include <vector>
#include <memory>
#include <stack>
#include "MapTypes.h"
#include "Geometry.h"
class BSPTree {
public:
struct node;
using node_p = std::unique_ptr<node>;
struct node {
bool leaf;
segments_t lines;
StraightLine split;
Vector min_bound;
Vector max_bound;
node_p left;
node_p right;
};
class iterator {
public:
iterator(Vector pos) : n_(nullptr), pos_(pos) {}
iterator(const node* &n, const Vector& pos) : n_(n), pos_(pos) {}
const segments_t & operator*() const {
return n_->lines;
}
bool operator!=(const iterator & it) const {
return it.n_ != n_;
}
iterator operator++();
private:
friend class BSPTree;
const node* n_;
std::stack<const node*> s_;
Vector pos_;
};
/**
@param position Position of point which defines order of the traversal.
*/
iterator begin(const Vector& position) const;
iterator end(const Vector& position) const {
return iterator(position);
}
/**
@param lines Lines defining map.
*/
static BSPTree build(const lines_t& lines);
/**
@return Returns reference to the tree root.
*/
const node& get_root() const { return *root_.get(); }
/**
@param point A point which defines sub-sector being returned.
@return Returns sub-sector specified by point argument.
*/
const segments_t* get_subsector(const Vector& point) const;
private:
/**
@param lines Lines to be converted to Segments, see MapTypes.h
@return Returns new vector of created segments.
*/
static segments_t lines_to_segments(const lines_t& lines);
/**
Checks if segments are convex; if so, new leaf node builded,
otherwise a cut is made and new inner node is created.
@param segments Segments to be checked.
@return A pointer to node, see method description.
*/
node_p partition_segments(segments_t& segments);
static void div_line_from_segment(StraightLine& d, const Segment& s);
/**
@param segments Sub-sector to be splitted, all segments are candidates.
@param split_line This arguments is filled by the best split candidate.
@param best_value Already found splitting value, suitable for clipping.
@return Returns the best split weight.
*/
static int split_evaluate(const segments_t& segments, Segment& split_line, int best_value);
/**
@param s Segment to be checked.
@param d Division line.
@return Returns 0 if entire segment is on the left side, 1 on the right side and
-1 if the segment must be splitted.
*/
static int determine_seg_side(const Segment& s, const StraightLine& d);
/**
@param segments Segments to be checked divided into two halves.
@param splitter Division segment (converted to line).
@param front Argument is filled with segments on the left side
@param back Argument is filled with segments on the right side
*/
static void split_segments(const segments_t& segments, const Segment& splitter, segments_t& front, segments_t& back);
static Segment split_segment(Segment& segment, const StraightLine& splitter);
node_p root_;
};
#endif