Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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 
44 namespace ogdf {
45 namespace internal {
46 namespace gcm {
47 
48 namespace graph {
49 template<typename Kernel, bool parallel = false>
50 class BloatedDualGraph {
51 private:
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 
59 public:
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() {
92  m_number_of_nodes = 0;
93  segments.clear();
94  intersecting_segments.clear();
95  intersections.clear();
96  segm_to_node_range.clear();
97  edges.clear();
98  node_to_segment.clear();
99  segment_to_intersections.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) {
134  OGDF_ASSERT(u < number_of_nodes());
135  OGDF_ASSERT(v < number_of_nodes());
136 
137  auto add_edge = [&](Node _u, Node _v) {
138  if (parallel) {
139  omp_set_lock(&locks[_u]);
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) {
158  omp_unset_lock(&locks[_u]);
159  }
160  };
161 
162  add_edge(u, v);
163  add_edge(v, u);
164  }
165 
166  bool is_left(const Node v) const {
167  OGDF_ASSERT(v < number_of_nodes());
168  return v % 2 == 0;
169  }
170 
171  bool is_right(const Node v) const {
172  OGDF_ASSERT(v < number_of_nodes());
173  return v % 2 == 1;
174  }
175 
176  Point get_intersection_point(const LocalIntersection& li) const {
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  }
183  return intersections[intersection_id];
184  }
185 
186  unsigned int get_first_id(const unsigned int segment, const unsigned int intersection_id) const {
187  OGDF_ASSERT(intersection_id < intersecting_segments.size());
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 {
198  OGDF_ASSERT(intersection_id < intersecting_segments.size());
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 {
228  OGDF_ASSERT(get_first_id(segment, intersection_id) < number_of_nodes());
229  return get_first_id(segment, intersection_id);
230  }
231 
232  Node first_right(const unsigned int segment, const unsigned int intersection_id) const {
233  OGDF_ASSERT(get_first_id(segment, intersection_id) + 1 < number_of_nodes());
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 {
238  OGDF_ASSERT(get_second_id(segment, intersection_id) < number_of_nodes());
239  return get_second_id(segment, intersection_id);
240  }
241 
242  Node second_right(const unsigned int segment, const unsigned int intersection_id) const {
243  OGDF_ASSERT(get_second_id(segment, intersection_id) + 1 < number_of_nodes());
244  return get_second_id(segment, intersection_id) + 1;
245  }
246 
247  Node first_left(const unsigned int segment, const LocalIntersection& li) const {
248  OGDF_ASSERT(get_first_id(segment, li) < number_of_nodes());
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 {
258  OGDF_ASSERT(get_second_id(segment, li) < number_of_nodes());
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
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
Point.h
ogdf::gml::Key::Node
@ Node
ogdf::gml::Key::Edge
@ Edge
LineSegment.h
basic.h
Basic declarations, included by all source files.
ogdf::gml::Key::Point
@ Point
PlanarSubdivision.h