Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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.