Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

ExtractCellFromBloatedDual.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>
37 
38 # include <vector>
39 
40 namespace ogdf {
41 namespace internal {
42 namespace gcm {
43 namespace geometry {
44 
45 namespace details {
46 
47 
48 template<typename Kernel>
49 typename graph::BloatedDualGraph<Kernel>::Edge forward(
50  const typename graph::BloatedDualGraph<Kernel>::Node prev,
51  const typename graph::BloatedDualGraph<Kernel>::Node cur,
52  const typename graph::BloatedDualGraph<Kernel>& bd) {
53  OGDF_ASSERT(bd.degree(cur) >= 2);
54 
55  auto is_good = [&](const unsigned int e) {
56  //return bd.edge_to_segments[e].seg_a != bd.edge_to_segments[e].seg_b
57  return bd.is_face_edge(e) && bd.edges[e] != prev && bd.edges[e] != cur; // not a self-loop
58  };
59 
60  using Edge = typename graph::BloatedDualGraph<Kernel>::Edge;
61  const Edge e_1 = 3 * cur;
62  const Edge e_2 = 3 * cur + 1;
63  const Edge e_3 = 3 * cur + 2;
64 
65  if (is_good(e_1)) {
66  return e_1;
67  } else if (is_good(e_2)) {
68  return e_2;
69  } else {
70  return e_3;
71  }
72 }
73 
74 template<typename Kernel>
75 typename graph::BloatedDualGraph<Kernel>::Edge find_start(
76  const typename graph::BloatedDualGraph<Kernel>::Node cur,
77  const graph::BloatedDualGraph<Kernel>& bd) {
78  using Edge = typename graph::BloatedDualGraph<Kernel>::Edge;
79  const Edge e_1 = 3 * cur;
80  const Edge e_2 = 3 * cur + 1;
81  const Edge e_3 = 3 * cur + 2;
82 
83  if (bd.is_face_edge(e_1) || bd.degree(cur) == 1) {
84  return e_1;
85  } else if (bd.is_face_edge(e_2)) {
86  return e_2;
87  } else {
88  return e_3;
89  }
90 }
91 
92 }
93 
99 //use clockwise and counter clockwise to decode which side??
100 template<typename Kernel>
101 std::vector<unsigned int> extract_cell(const graph::BloatedDualGraph<Kernel>& bd,
102  const typename graph::BloatedDualGraph<Kernel>::Node v) {
103  using Graph = graph::BloatedDualGraph<Kernel>;
104  using Node = typename Graph::Node;
105 
106  std::vector<unsigned int> segments;
107 
108  auto cur_edge = details::find_start(v, bd);
109 
110  //in case that bd.degree(v) == 1, the arrangment is a single segment
111  if (bd.degree(v) > 1) {
112  Node prev = v;
113  segments.push_back(bd.node_to_segment[v]);
114  Node current = bd.edges[cur_edge];
115  while (current != v) {
116  cur_edge = details::forward(prev, current, bd);
117 
118  //segment_pairs.push_back(bd.edge_to_segments[cur_edge]);
119  segments.push_back(bd.node_to_segment[current]);
120  prev = current;
121  current = bd.edges[cur_edge];
122  }
123  }
124  return segments;
125 }
126 
127 /*
128  *@caution does not handle open regions properly
129  */
130 template<typename Kernel>
131 Polygon_t<Kernel> extract_polygon(const std::vector<LineSegment_t<Kernel>>& segments,
132  const std::vector<unsigned int>& seq) {
133  Polygon_t<Kernel> poly;
134 
135  //for (auto x : seq) {
136  for (unsigned int i = 0; i < seq.size(); ++i) {
137  Point_t<Kernel> p;
138  bool common_endpoint = false;
139  unsigned int seg_a = seq[i];
140 
141  unsigned int seg_b = -1;
142  if (i + 1 < seq.size()) {
143  seg_b = seq[i + 1];
144  } else {
145  seg_b = seq[0];
146  }
147 
148  for (unsigned int l = 0; l <= 1; ++l) {
149  for (unsigned int j = 0; j <= 1; ++j) {
150  OGDF_ASSERT(seg_a < segments.size());
151  OGDF_ASSERT(seg_b < segments.size());
152  if (segments[seg_a].vertex(l) == segments[seg_b].vertex(j)) {
153  p = segments[seg_a].vertex(l);
154  common_endpoint = true;
155  }
156  }
157  }
158 
159  if (!common_endpoint) {
160  p = geometry::intersect(segments[seg_a], segments[seg_b]);
161  }
162 
163  if (poly.is_empty() || *(--poly.vertices_end()) != p) {
164  poly.push_back(p);
165  }
166  }
167 
168  if (*poly.vertices_begin() == *(--poly.vertices_end())) {
169  OGDF_ASSERT(poly.size() > 0);
170  poly.erase(--poly.vertices_end());
171  }
172 
173  return poly;
174 }
175 
176 template<typename Kernel>
177 typename graph::BloatedDualGraph<Kernel>::Node find_representative_node(
178  const graph::BloatedDualGraph<Kernel>& bd, const Point_t<Kernel>& p) {
179  auto& segments = bd.segments;
180  unsigned int opt = -1; // segment with the smallest distance to p
181  Point_t<Kernel> is_with_r;
182  while (opt > segments.size()) {
183  Ray_t<Kernel> r(p,
184  Vector_t<Kernel>(ogdf::randomNumber(0, INT_MAX) % 1000 - 500,
185  ogdf::randomNumber(0, INT_MAX) % 1000 - 500));
186  for (unsigned i = 0; i < segments.size(); ++i) {
187  if (CGAL::do_intersect(segments[i], r)) {
188  if (opt > segments.size()) {
189  opt = i;
190  is_with_r = geometry::intersect(segments[i], r);
191  } else {
192  auto o = geometry::intersect(segments[i], r);
193  if (squared_distance(o, p) < squared_distance(is_with_r, p)) {
194  opt = i;
195  is_with_r = o;
196  }
197  }
198  }
199  }
200  }
201 
202  unsigned int opt_is = 0;
203  typename Kernel::FT distance = CGAL::squared_distance(segments[opt].source(), is_with_r);
204  // find subsegment on segments[opt]
205  for (unsigned int i = 0; i < bd.segment_to_intersections[opt].size(); ++i) {
206  auto is = bd.get_intersection_point(bd.segment_to_intersections[opt][i]);
207  if (CGAL::squared_distance(is, is_with_r) < distance) {
208  distance = CGAL::squared_distance(is, is_with_r);
209  opt_is = i;
210  }
211  }
212 
213  typename graph::BloatedDualGraph<Kernel>::Node v;
214  bool left = geometry::left_turn(segments[opt], p);
215 
216  // endpoint should be an intersection
217  OGDF_ASSERT(!bd.segment_to_intersections[opt].empty());
218 
219  if (CGAL::squared_distance(segments[opt].source(), is_with_r)
220  < CGAL::squared_distance(segments[opt].source(),
221  bd.get_intersection_point(bd.segment_to_intersections[opt][opt_is]))) {
222  if (left) {
223  v = bd.first_left(opt, bd.segment_to_intersections[opt][opt_is]);
224  } else {
225  v = bd.first_right(opt, bd.segment_to_intersections[opt][opt_is]);
226  }
227 
228  } else {
229  if (left) {
230  v = bd.second_left(opt, bd.segment_to_intersections[opt][opt_is]);
231  } else {
232  v = bd.second_right(opt, bd.segment_to_intersections[opt][opt_is]);
233  }
234  }
235 
236  return v;
237 }
238 
239 }
240 }
241 }
242 }
243 
244 #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
ogdf::gml::Key::Node
@ Node
ogdf::gml::Key::Edge
@ Edge
r
int r[]
Definition: hierarchical-ranking.cpp:13
ogdf::gml::Key::Graph
@ Graph
basic.h
Basic declarations, included by all source files.
BloatedDual.h
ogdf::randomNumber
int randomNumber(int low, int high)
Returns random integer between low and high (including).