Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

RandomPoint.h
Go to the documentation of this file.
1 
31 #pragma once
32 
33 #ifdef OGDF_INCLUDE_CGAL
34 
39 
40 namespace ogdf {
41 namespace internal {
42 namespace gcm {
43 namespace graph {
44 
45 template<typename Kernel>
46 class RandomPointsInCell {
47 private:
48  using BD = BloatedDualGraph<Kernel>;
49 
50  using Point = geometry::Point_t<Kernel>;
51  using Segment = geometry::LineSegment_t<Kernel>;
52  using Polygon = geometry::Polygon_t<Kernel>;
53 
54  static std::vector<int> vertex_weights(const BD& bd, const Point& p,
55  const std::vector<int>& left_to_right_cost, std::vector<bool>& visited,
56  datastructure::UnionFind& uf) {
57  typename BD::Node min_node = bd.segm_to_node_range[left_to_right_cost.size() - 4];
58 
59  auto rep = geometry::find_representative_node(bd, p);
60 
61  int min_weight = 0; // this value becomes negative, if we can improve...
62  int max_weight = 0; // this value becomes negative, if we can improve...
63 
64 
65  std::vector<typename BD::Node> parent(bd.number_of_nodes());
66  std::vector<typename BD::Edge> parent_edge(bd.number_of_nodes());
67 
68  auto f_weight = [&](typename BD::Node v, typename BD::Edge e) {
69  if (bd.is_face_edge(e) || bd.degree(v) == 2) {
70  return 0;
71  } else if (bd.is_left(v)) {
72  return left_to_right_cost[bd.node_to_segment[v]];
73  } else {
74  return -left_to_right_cost[bd.node_to_segment[v]];
75  }
76  };
77 
78  auto expand = [&](typename BD::Node w, typename BD::Edge e) {
79  bool bad_edge = w >= min_node && bd.edges[e] >= min_node; //TODO correct??
80  return !bad_edge;
81  };
82 
83  parent[rep] = rep;
84 
85  std::vector<typename BD::Node> queue;
86  std::vector<int> weight(bd.number_of_nodes(), 0);
87 
88 
89  queue.push_back(rep);
90  weight[rep] = 0;
91  visited[rep] = true;
92 
93  auto handle_edge = [&](typename BD::Node v, typename BD::Edge e) {
94  typename BD::Node w = bd.edges[e];
95  OGDF_ASSERT(!visited[w] || v == w || weight[w] == weight[v] + f_weight(v, e));
96 
97  if (!visited[w] && expand(v, e) && v != w) {
98  weight[w] = weight[v] + f_weight(v, e);
99  visited[w] = true;
100  queue.push_back(w);
101  parent[w] = v;
102  parent_edge[w] = e;
103  if (bd.is_face_edge(e)) {
104  uf.merge(v, w);
105  }
106  }
107  };
108 
109  while (!queue.empty()) {
110  typename BD::Node current = queue.back();
111  queue.pop_back();
112  min_weight = std::min(min_weight, weight[current]);
113  max_weight = std::max(max_weight, weight[current]);
114 
115  handle_edge(current, 3 * current);
116  handle_edge(current, 3 * current + 1);
117  handle_edge(current, 3 * current + 2);
118  }
119 
120  for (auto& w : weight) {
121  w = max_weight - w + 1;
122  }
123 
124  return weight;
125  }
126 
127 public:
128  static std::vector<Point> compute(const BD& bd, const std::vector<int>& left_to_right_cost,
129  const Point& reference, unsigned int nof_points, std::mt19937_64& gen) {
130  datastructure::UnionFind uf(bd.number_of_nodes());
131  uf.all_to_singletons();
132 
133  std::vector<bool> visited(bd.number_of_nodes(), false);
134  std::vector<int> weights = vertex_weights(bd, reference, left_to_right_cost, visited, uf);
135 
136  std::vector<unsigned int> repr;
137  for (unsigned int u = 0; u < bd.number_of_nodes(); ++u) {
138  if (uf.find(u) == u && visited[u]) {
139  repr.push_back(u);
140  }
141  }
142 
143 
144  std::vector<double> repr_weights(repr.size(), 0);
145  std::vector<unsigned int> interval;
146 
147  for (unsigned int i = 0; i < repr.size(); ++i) {
148  repr_weights[i] = std::pow(2, weights[repr[i]]);
149 
150  interval.push_back(i);
151  }
152 
153  interval.push_back(repr.size());
154 
155  std::piecewise_constant_distribution<double> dist(interval.begin(), interval.end(),
156  repr_weights.begin());
157 
158  std::vector<Point> point_set;
159  if (!repr.empty()) {
160  for (unsigned int r = 0; r < nof_points; ++r) {
161  //select a region randomly inverse proportional to its number of crossings
162  unsigned int v_id = std::floor(dist(gen));
163  OGDF_ASSERT(v_id < repr.size());
164  unsigned int v = repr[v_id];
165 
166  OGDF_ASSERT(v < bd.number_of_nodes());
167  auto seq = geometry::extract_cell(bd, v);
168  auto region = geometry::extract_polygon(bd.segments, seq);
169  if (CGAL::abs(region.area()) > 1e-5) {
170  auto p = geometry::random_point_in_polygon(region, gen);
171  point_set.push_back(p);
172  }
173  }
174  }
175  return point_set;
176  }
177 };
178 
179 
180 }
181 }
182 }
183 }
184 
185 #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
UnionFind.h
r
int r[]
Definition: hierarchical-ranking.cpp:13
ExtractCellFromBloatedDual.h
ogdf::gml::Key::Point
@ Point
BloatedDual.h
RandomPointInPolygon.h