If an edge is too small, collapse it and its twin and fix the surrounding edges to ensure a consistent graph.
Don't collapse support edges, unless we can collapse the whole quad.
o-, | "-o | | > Don't collapse this edge only. o o
194{
195 ankerl::unordered_dense::map<edge_t*, Edges::iterator> edge_locator;
196 ankerl::unordered_dense::map<node_t*, Nodes::iterator> node_locator;
197
198 for (
auto edge_it =
edges.begin(); edge_it !=
edges.end(); ++edge_it)
199 {
200 edge_locator.emplace(&*edge_it, edge_it);
201 }
202
203 for (
auto node_it =
nodes.begin(); node_it !=
nodes.end(); ++node_it)
204 {
205 node_locator.emplace(&*node_it, node_it);
206 }
207
208 auto safelyRemoveEdge = [
this, &edge_locator](
edge_t* to_be_removed, Edges::iterator& current_edge_it,
bool& edge_it_is_updated)
209 {
210 if (current_edge_it !=
edges.end()
211 && to_be_removed == &*current_edge_it)
212 {
213 current_edge_it =
edges.erase(current_edge_it);
214 edge_it_is_updated = true;
215 }
216 else
217 {
218 edges.erase(edge_locator[to_be_removed]);
219 }
220 };
221
222 auto should_collapse = [snap_dist](
node_t* a,
node_t* b)
223 {
225 };
226
227 for (
auto edge_it =
edges.begin(); edge_it !=
edges.end();)
228 {
229 if (edge_it->prev)
230 {
231 edge_it++;
232 continue;
233 }
234
235 edge_t* quad_start = &*edge_it;
236 edge_t* quad_end = quad_start;
while (quad_end->next) quad_end = quad_end->next;
237 edge_t* quad_mid = (quad_start->next == quad_end)?
nullptr : quad_start->next;
238
239 bool edge_it_is_updated = false;
240 if (quad_mid && should_collapse(quad_mid->from, quad_mid->to))
241 {
242 assert(quad_mid->twin);
243 if(!quad_mid->twin)
244 {
245 BOOST_LOG_TRIVIAL(warning) << "Encountered quad edge without a twin.";
246 continue;
247 }
249 for (
edge_t* edge_from_3 = quad_end; edge_from_3 && edge_from_3 != quad_mid->twin; edge_from_3 = edge_from_3->twin->next)
250 {
251 edge_from_3->from = quad_mid->from;
252 edge_from_3->twin->to = quad_mid->from;
254 {
255 std::cerr << edge_from_3->from->p << " - " << edge_from_3->to->p << '\n';
256 }
258 {
259 break;
260 }
261 }
262
263
264
265
266
267
268 if (quad_mid->from->incident_edge == quad_mid)
269 {
270 if (quad_mid->twin->next)
271 {
272 quad_mid->from->incident_edge = quad_mid->twin->next;
273 }
274 else
275 {
276 quad_mid->from->incident_edge = quad_mid->prev->twin;
277 }
278 }
279
280 nodes.erase(node_locator[quad_mid->to]);
281
282 quad_mid->prev->next = quad_mid->next;
283 quad_mid->next->prev = quad_mid->prev;
284 quad_mid->twin->next->prev = quad_mid->twin->prev;
285 quad_mid->twin->prev->next = quad_mid->twin->next;
286
287 safelyRemoveEdge(quad_mid->twin, edge_it, edge_it_is_updated);
288 safelyRemoveEdge(quad_mid, edge_it, edge_it_is_updated);
289 }
290
291
292
293
294 if ( should_collapse(quad_start->from, quad_end->to) && should_collapse(quad_start->to, quad_end->from))
295 {
296
297 quad_start->twin->to = quad_end->to;
298 quad_end->to->incident_edge = quad_end->twin;
299 if (quad_end->from->incident_edge == quad_end)
300 {
301 if (quad_end->twin->next)
302 {
303 quad_end->from->incident_edge = quad_end->twin->next;
304 }
305 else
306 {
307 quad_end->from->incident_edge = quad_end->prev->twin;
308 }
309 }
310 nodes.erase(node_locator[quad_start->from]);
311
312 quad_start->twin->twin = quad_end->twin;
313 quad_end->twin->twin = quad_start->twin;
314 safelyRemoveEdge(quad_start, edge_it, edge_it_is_updated);
315 safelyRemoveEdge(quad_end, edge_it, edge_it_is_updated);
316 }
317
318
319
320
321 if (!edge_it_is_updated)
322 {
323 edge_it++;
324 }
325 }
326}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
STHalfEdgeNode node_t
Definition SkeletalTrapezoidationGraph.hpp:81
STHalfEdge edge_t
Definition SkeletalTrapezoidationGraph.hpp:80
Edges edges
Definition HalfEdgeGraph.hpp:26
Nodes nodes
Definition HalfEdgeGraph.hpp:27
bool shorter_then(const Point &p0, const coord_t len)
Definition Point.hpp:486