Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
BloatedDual.h
Go to the documentation of this file.
1
31#pragma once
32
33#ifdef OGDF_INCLUDE_CGAL
34
35# include <ogdf/basic/basic.h>
39
40# include <vector>
41
42# include <omp.h>
43
44namespace ogdf {
45namespace internal {
46namespace gcm {
47
48namespace graph {
49template<typename Kernel, bool parallel = false>
50class BloatedDualGraph {
51private:
52 using Segment = geometry::LineSegment_t<Kernel>;
53 using Point = geometry::Point_t<Kernel>;
54
55 unsigned int m_number_of_nodes = 0;
56
57 std::vector<omp_lock_t> locks;
58
59public:
60 //intersection from the perspective of a @reference_segment
61 struct LocalIntersection {
62 unsigned int left_intersection_ids[2] = {(unsigned int)-1, (unsigned int)-1};
63 unsigned int right_intersection_ids[2] = {(unsigned int)-1, (unsigned int)-1};
64 bool is_end_point = false;
65
66 inline bool left_is_valid() const { return left_intersection_ids[0] != (unsigned int)-1; }
67
68 inline bool right_is_valid() const { return right_intersection_ids[0] != (unsigned int)-1; }
69
70 unsigned int intersection_id() const {
71 if (left_is_valid()) {
72 return left_intersection_ids[0];
73 } else {
74 return right_intersection_ids[0];
75 }
76 }
77 };
78
79 using Node = unsigned int;
80 using Edge = unsigned int;
81
82 std::vector<Segment> segments;
83 std::vector<geometry::Intersection> intersecting_segments;
84 std::vector<Point> intersections;
85
86 std::vector<unsigned int> segm_to_node_range; //TODO actually edge range, now
87 std::vector<Node> edges;
88 std::vector<unsigned int> node_to_segment;
89 std::vector<std::vector<LocalIntersection>> segment_to_intersections;
90
91 void clear() {
93 segments.clear();
95 intersections.clear();
96 segm_to_node_range.clear();
97 edges.clear();
98 node_to_segment.clear();
100 locks.clear();
101 }
102
103 BloatedDualGraph() { }
104
105 unsigned int number_of_nodes() const { return m_number_of_nodes; }
106
107 unsigned int degree(const Node v) const {
108 if (edges[3 * v + 2] != v) {
109 return 3;
110 } else if (edges[3 * v + 1] != v) {
111 return 2;
112 } else if (edges[3 * v] != v) {
113 return 1;
114 } else {
115 return 0;
116 }
117 }
118
119 Node add_node(unsigned int segment_id) {
120 edges.push_back(m_number_of_nodes); // initial every edge is a self loop
121 edges.push_back(m_number_of_nodes);
122 edges.push_back(m_number_of_nodes);
123
124 node_to_segment.push_back(segment_id);
125
126 if (parallel) {
127 locks.push_back(omp_lock_t());
128 }
129
130 return m_number_of_nodes++;
131 }
132
133 void add_edge(const Node u, const Node v, bool face_edge) {
136
137 auto add_edge = [&](Node _u, Node _v) {
138 if (parallel) {
140 }
141
142 unsigned int i = _u * 3;
143 OGDF_ASSERT(i < edges.size());
144 if (edges[i] != _v && edges[i + 1] != _v && edges[i + 2] != _v) {
145 OGDF_ASSERT(edges[i + 2] == _u);
146
147 unsigned int off = 0;
148 if (face_edge) {
149 off = 1;
150 if (edges[i + 1] != _u) {
151 off = 2; //self loop serves as sentinel
152 }
153 }
154
155 edges[i + off] = _v;
156 }
157 if (parallel) {
159 }
160 };
161
162 add_edge(u, v);
163 add_edge(v, u);
164 }
165
166 bool is_left(const Node v) const {
168 return v % 2 == 0;
169 }
170
171 bool is_right(const Node v) const {
173 return v % 2 == 1;
174 }
175
177 unsigned int intersection_id = -1;
178 if (li.left_is_valid()) {
179 intersection_id = li.left_intersection_ids[0];
180 } else {
181 intersection_id = li.right_intersection_ids[1];
182 }
184 }
185
186 unsigned int get_first_id(const unsigned int segment, const unsigned int intersection_id) const {
188
189 const geometry::Intersection& is = intersecting_segments[intersection_id];
190 OGDF_ASSERT(is.is_incident(segment));
191 unsigned int pos = 2 * (is.pos(segment) - 1); //2 accounts for the left and right vertices...
192 OGDF_ASSERT(segment < segment_to_intersections.size());
193 OGDF_ASSERT(segm_to_node_range[segment] + pos < segm_to_node_range[segment + 1]);
194 return segm_to_node_range[segment] + pos;
195 }
196
197 unsigned int get_second_id(const unsigned int segment, const unsigned int intersection_id) const {
199
200 const geometry::Intersection& is = intersecting_segments[intersection_id];
201 OGDF_ASSERT(is.is_incident(segment));
202
203 unsigned int pos = 2 * is.pos(segment);
204
205 OGDF_ASSERT(segment < segment_to_intersections.size());
206 OGDF_ASSERT(segm_to_node_range[segment] + pos < segm_to_node_range[segment + 1]);
207
208 return segm_to_node_range[segment] + pos;
209 }
210
211 unsigned int get_first_id(const unsigned int segment, const LocalIntersection& li) const {
212 if (li.left_is_valid()) {
213 return get_first_id(segment, li.left_intersection_ids[0]);
214 } else {
215 return get_first_id(segment, li.right_intersection_ids[0]);
216 }
217 }
218
219 unsigned int get_second_id(const unsigned int segment, const LocalIntersection& li) const {
220 if (li.left_is_valid()) {
221 return get_second_id(segment, li.left_intersection_ids[0]);
222 } else {
223 return get_second_id(segment, li.right_intersection_ids[0]);
224 }
225 }
226
227 Node first_left(const unsigned int segment, const unsigned int intersection_id) const {
229 return get_first_id(segment, intersection_id);
230 }
231
232 Node first_right(const unsigned int segment, const unsigned int intersection_id) const {
234 return get_first_id(segment, intersection_id) + 1;
235 }
236
237 Node second_left(const unsigned int segment, const unsigned int intersection_id) const {
239 return get_second_id(segment, intersection_id);
240 }
241
242 Node second_right(const unsigned int segment, const unsigned int intersection_id) const {
244 return get_second_id(segment, intersection_id) + 1;
245 }
246
247 Node first_left(const unsigned int segment, const LocalIntersection& li) const {
249 return get_first_id(segment, li);
250 }
251
252 Node first_right(const unsigned int segment, const LocalIntersection& li) const {
253 OGDF_ASSERT(get_first_id(segment, li) + 1 < number_of_nodes());
254 return get_first_id(segment, li) + 1;
255 }
256
257 Node second_left(const unsigned int segment, const LocalIntersection& li) const {
259 return get_second_id(segment, li);
260 }
261
262 Node second_right(const unsigned int segment, const LocalIntersection& li) const {
263 OGDF_ASSERT(get_second_id(segment, li) + 1 < number_of_nodes());
264 return get_second_id(segment, li) + 1;
265 }
266
267 bool is_face_edge(const Edge e) const {
268 OGDF_ASSERT(e < 3 * number_of_nodes());
269 return e % 3 != 0;
270 }
271};
272
273}
274}
275}
276}
277
278#endif
Basic declarations, included by all source files.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.