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
183{
184 ankerl::unordered_dense::map<edge_t*, Edges::iterator> edge_locator;
185 ankerl::unordered_dense::map<node_t*, Nodes::iterator> node_locator;
186
187 for (
auto edge_it =
edges.begin(); edge_it !=
edges.end(); ++edge_it)
188 {
189 edge_locator.emplace(&*edge_it, edge_it);
190 }
191
192 for (
auto node_it =
nodes.begin(); node_it !=
nodes.end(); ++node_it)
193 {
194 node_locator.emplace(&*node_it, node_it);
195 }
196
197 auto safelyRemoveEdge = [
this, &edge_locator](
edge_t* to_be_removed, Edges::iterator& current_edge_it,
bool& edge_it_is_updated)
198 {
199 if (current_edge_it !=
edges.end()
200 && to_be_removed == &*current_edge_it)
201 {
202 current_edge_it =
edges.erase(current_edge_it);
203 edge_it_is_updated = true;
204 }
205 else
206 {
207 edges.erase(edge_locator[to_be_removed]);
208 }
209 };
210
212 {
214 };
215
216 for (
auto edge_it =
edges.begin(); edge_it !=
edges.end();)
217 {
218 if (edge_it->prev)
219 {
220 edge_it++;
221 continue;
222 }
223
224 edge_t* quad_start = &*edge_it;
225 edge_t* quad_end = quad_start;
while (quad_end->next) quad_end = quad_end->
next;
226 edge_t* quad_mid = (quad_start->next == quad_end)?
nullptr : quad_start->next;
227
228 bool edge_it_is_updated = false;
229 if (quad_mid && should_collapse(quad_mid->from, quad_mid->to))
230 {
231 assert(quad_mid->twin);
232 if(!quad_mid->twin)
233 {
234 BOOST_LOG_TRIVIAL(warning) << "Encountered quad edge without a twin.";
235 continue;
236 }
238 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)
239 {
240 edge_from_3->from = quad_mid->from;
241 edge_from_3->twin->to = quad_mid->from;
242 if (count > 50)
243 {
244 std::cerr << edge_from_3->from->p << " - " << edge_from_3->to->p << '\n';
245 }
246 if (++count > 1000)
247 {
248 break;
249 }
250 }
251
252
253
254
255
256
257 if (quad_mid->from->incident_edge == quad_mid)
258 {
259 if (quad_mid->twin->next)
260 {
261 quad_mid->from->incident_edge = quad_mid->twin->next;
262 }
263 else
264 {
265 quad_mid->from->incident_edge = quad_mid->prev->twin;
266 }
267 }
268
269 nodes.erase(node_locator[quad_mid->to]);
270
271 quad_mid->prev->next = quad_mid->next;
272 quad_mid->next->prev = quad_mid->prev;
273 quad_mid->twin->next->prev = quad_mid->twin->prev;
274 quad_mid->twin->prev->next = quad_mid->twin->next;
275
276 safelyRemoveEdge(quad_mid->twin, edge_it, edge_it_is_updated);
277 safelyRemoveEdge(quad_mid, edge_it, edge_it_is_updated);
278 }
279
280
281
282
283 if ( should_collapse(quad_start->from, quad_end->to) && should_collapse(quad_start->to, quad_end->from))
284 {
285
286 quad_start->twin->to = quad_end->to;
287 quad_end->to->incident_edge = quad_end->twin;
288 if (quad_end->from->incident_edge == quad_end)
289 {
290 if (quad_end->twin->next)
291 {
292 quad_end->from->incident_edge = quad_end->twin->next;
293 }
294 else
295 {
296 quad_end->from->incident_edge = quad_end->prev->twin;
297 }
298 }
299 nodes.erase(node_locator[quad_start->from]);
300
301 quad_start->twin->twin = quad_end->twin;
302 quad_end->twin->twin = quad_start->twin;
303 safelyRemoveEdge(quad_start, edge_it, edge_it_is_updated);
304 safelyRemoveEdge(quad_end, edge_it, edge_it_is_updated);
305 }
306
307
308
309
310 if (!edge_it_is_updated)
311 {
312 edge_it++;
313 }
314 }
315}
edge_t * twin
Definition HalfEdge.hpp:24
edge_t * next
Definition HalfEdge.hpp:25
STHalfEdgeNode node_t
Definition SkeletalTrapezoidationGraph.hpp:76
STHalfEdge edge_t
Definition SkeletalTrapezoidationGraph.hpp:75
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:301
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12