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
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
40namespace ogdf {
41namespace internal {
42namespace gcm {
43namespace geometry {
44
45namespace details {
46
47
48template<typename Kernel>
49typename 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
74template<typename Kernel>
75typename 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??
100template<typename Kernel>
101std::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 */
130template<typename Kernel>
132 const std::vector<unsigned int>& seq) {
134
135 //for (auto x : seq) {
136 for (unsigned int i = 0; i < seq.size(); ++i) {
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
176template<typename Kernel>
177typename 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
182 while (opt > segments.size()) {
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);
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
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
int randomNumber(int low, int high)
Returns random integer between low and high (including).
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.