-
Notifications
You must be signed in to change notification settings - Fork 0
/
BSP.cpp
108 lines (98 loc) · 3.2 KB
/
BSP.cpp
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
#include "BSP.h"
#include "utils.h"
#include <vector>
using namespace std;
BSP::BSP(Polygon& polygon){
polygonPtr = &polygon;
root=constructBSP(polygon.edges, height, isConvex(polygon));
}
BSP::~BSP(){
freeBSP(root);
polygonPtr=nullptr;
}
TreeNode* BSP::constructBSP(vector<Edge> edges, int& height, bool convex){
if(edges.size()==0) return nullptr;
TreeNode* root = new TreeNode();
Edge split;
++height;
if(convex){
if (edges.size() != 1) {
int pivot = getMiddleIndex(edges[0].indexes.first, edges[edges.size() - 1].indexes.second, polygonPtr->vertexSize);
int startIndex = edges[0].indexes.first;
split = Edge(polygonPtr->dots[startIndex], polygonPtr->dots[pivot]);
}
else {
split = edges[0];
}
}
else{
split=edges[0];
}
root->edge=split;
Edge subPos, subNeg;
vector<Edge> posArr, negArr;
for(int i=0;i<edges.size();++i){
PostionState state=getEdgePositionState(split, edges[i], subPos, subNeg);
if(state==PostionState::CROSSES){
posArr.push_back(subPos);
negArr.push_back(subNeg);
}else if(state==PostionState::POSITIVE){
posArr.push_back(edges[i]);
}else if(state==PostionState::NEGATIVE){
negArr.push_back(edges[i]);
}else{
root->coincident.push_back(edges[i]);
}
}
if(!posArr.empty()){
root->left=constructBSP(posArr, height, convex);
}else {
root->left=nullptr;
}
if(!negArr.empty()){
root->right=constructBSP(negArr, height, convex);
}else {
root->right=nullptr;
}
return root;
}
void BSP::freeBSP(TreeNode* root){
if(root==nullptr) return;
freeBSP(root->left);
freeBSP(root->right);
delete root;
return;
}
int BSP::getPointLocation(TreeNode* root, int x, int y){
Edge tmp({0,0}, {x,y});
pair<double, double> point(x, y);
PostionState state=getPointPositionState(root->edge, point);
if(state==PostionState::POSITIVE){
if(root->left) return getPointLocation(root->left, x, y);
else return 1; // inside
}else if (state==PostionState::NEGATIVE) {
if(root->right) return getPointLocation(root->right, x, y);
else return -1; // outside
}else{
for(auto& edge: root->coincident){
Edge normal=Edge({0,0}, {-edge.val.second, edge.val.first });
tmp=Edge({edge.v0.first, edge.v0.second}, {x,y});
if(vectorDot(tmp, normal)==0){
int xLeft=edge.v0.first, xRight=edge.v1.second,xbak;
xbak=xLeft;
xLeft=xLeft<xRight?xLeft:xRight;
xRight=xRight>xbak?xRight:xbak;
int yDonw = edge.v0.second, yUp = edge.v1.second, ybak;
ybak = yDonw;
yDonw = yDonw <yUp ? yDonw : yUp;
yUp = yUp > ybak ? yUp : ybak;
if(xLeft<=x&&x<=xRight&& yDonw <= y && y <= yUp) return 0; // onEdge
}
}
if(root->left) return getPointLocation(root->left, x, y);
else if(root->right) return getPointLocation(root->right, x, y);
else{
return 0;
}
}
}