Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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.