-
Notifications
You must be signed in to change notification settings - Fork 0
/
graph.hpp
204 lines (165 loc) · 6.32 KB
/
graph.hpp
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <iostream>
struct Point{
double x, y;
// true if x coords & y coords are equal
bool operator==(const Point& other) const {
return this->x == other.x && this->y == other.y;
}
// true if x coords or y coords are not equal
bool operator!=(const Point& other) const {
return this->x != other.x || this->y != other.y;
}
// true if x coord is smaller than the other x coord
// also true, in case x's are equal, if y coord is smaller than the other y coord
bool operator<(const Point& other) const {
if (this->x != other.x) return this->x < other.x;
return this->y < other.y;
}
};
class Edge{
public:
Edge(Point from, Point to){
this->from = from;
this->to = to;
this->angle = atan2(this->to.y - this->from.y, this->to.x - this->from.x);
}
//get the reverse directed edge
Edge getReverse() const{
Edge reverse(this->to, this->from);
reverse.fromIndex = this->toIndex;
reverse.toIndex = this->fromIndex;
return reverse;
}
void setToIndex(int i){
this->toIndex = i;
}
void setFromIndex(int i){
this->fromIndex = i;
}
int getToIndex() const{
return this->toIndex;
}
int getFromIndex() const{
return this->fromIndex;
}
bool operator==(const Edge& other) const{
if(this->from == other.from && this->to == other.to){
return true;
}
return false;
}
bool operator<(const Edge& other) const {
if(this->angle == other.angle) return this->toIndex < other.toIndex;
return this->angle < other.angle;
}
private:
Point from;
Point to;
int fromIndex;
int toIndex;
double angle;
};
class Vertex{
public:
bool visited;
Vertex(int index, Point p){
this->index = index;
this->p = p;
this->visited = false;
this->num_neighbors = 0;
}
int getIndex() const{
return this->index;
}
void addEdge(Edge e){
this->outGoingEdges.push_back(e);
}
void sortEdges(){
std::sort(this->outGoingEdges.begin(), this->outGoingEdges.end());
}
void addNeighbor(int neighborIndex){
this->neighbors.push_back(neighborIndex);
this->num_neighbors++;
}
int getNeighbor(int i) const{
return this->neighbors[i];
}
int getNumNeighbors() const{
return this->num_neighbors;
}
double getX() const{
return this->p.x;
}
double getY() const{
return this->p.y;
}
Edge getEdge(int i) const{
return this->outGoingEdges[i];
}
private:
int index;
Point p;
std::vector<Edge> outGoingEdges;
std::vector<int> neighbors;
int num_neighbors;
};
class GraphFaces{
public:
void insertChains(Edge e1, Edge e2){
this->chains_map.insert(std::pair<Edge, Edge>(e1, e2)); // -> If a single element is inserted, logarithmic in size in general O(log n), \
but amortized constant if a hint is given and the position given is the optimal
}
void findFaces(){
// loop inside the map of the chained edges
for (std::map<Edge, Edge>::iterator iterator = chains_map.begin();
iterator != chains_map.end(); ++iterator){ // Θ(2E)
std::vector<int> face; // declare the current face
face.clear();
Edge firstKey = iterator->first; // firstKey = in the first iteration is equal the first element (edge) of the first pair in the map
auto itSet = this->chained_edges.find(firstKey); // check if firstKey is already chained -> O(log n)
if(itSet != chained_edges.end()){
continue;
}
chained_edges.insert(firstKey); // 'mark' the edge as already chained -> Θ(log n)
face.push_back(firstKey.getFromIndex()); // insert in the face the index of the origin vertex (the 'from vertex' of the edge) -> O(1)
// declare and initialize current_key and current_value
Edge current_key = iterator->first;
Edge current_value = iterator->second;
while(true){ // runs through the map linking the chains
auto it = chains_map.find(current_value); // finds the pair which has the current_value as its key
if(it == chains_map.end() || it->second == firstKey){ // check if there's not such key or the key is equal the firstKey of the loop
chained_edges.insert(it->first); // 'mark' the edge as already chained
// inserts the last vertex of the face and the first one
face.push_back(it->first.getFromIndex());
face.push_back(firstKey.getFromIndex());
break;
}
// update the current_key and the current_value w/ the element which has the current_value as its key
current_key = it->first;
current_value = it->second;
chained_edges.insert(current_key); // 'mark' the edge as already chained
face.push_back(current_key.getFromIndex()); // inserts the vertex in the face
}
faces.push_back(face); // inserts the face in the vector of faces
}
}
void printFaces(){ // Θ(2E)
std::cout << faces.size() << std::endl;
for(auto face : faces){
std::cout << face.size() << " ";
for(auto v : face){
std::cout << v << " ";
}
std::cout << std::endl;
}
}
private:
std::multimap<Edge, Edge> chains_map;
std::vector<std::vector<int>> faces;
std::set<Edge> chained_edges;
};