size_t carve::triangulate::detail::removeDegeneracies(vertex_info *&begin, std::vector<carve::triangulate::tri_idx> &result) { vertex_info *v; vertex_info *n; size_t count = 0; size_t remain = 0; v = begin; do { v = v->next; ++remain; } while (v != begin); v = begin; do { if (remain < 4) break; bool remove = false; if (v->p == v->next->p) { remove = true; } else if (v->p == v->next->next->p) { if (v->next->p == v->next->next->next->p) { // a 'z' in the loop: z (a) b a b c -> remove a-b-a -> z (a) a b c -> remove a-a-b (next loop) -> z a b c // z --(a)-- b // / // / // a -- b -- d remove = true; } else { // a 'shard' in the loop: z (a) b a c d -> remove a-b-a -> z (a) a b c d -> remove a-a-b (next loop) -> z a b c d // z --(a)-- b // / // / // a -- c -- d // n.b. can only do this if the shard is pointing out of the polygon. i.e. b is outside z-a-c remove = !internalToAngle(v->next->next->next, v, v->prev, v->next->p); } } if (remove) { result.push_back(carve::triangulate::tri_idx(v->idx, v->next->idx, v->next->next->idx)); n = v->next; if (n == begin) begin = n->next; n->remove(); count++; remain--; delete n; } else { v = v->next; } } while (v != begin); return count; }
/** * \brief Determine whether p is internal to the anticlockwise * angle ac, with apex at (0,0). * * @param[in] a * @param[in] c * @param[in] p * * @return true, if p is contained in a0c. */ inline bool internalToAngle(const P2 &a, const P2 &c, const P2 &p) { return internalToAngle(a, P2::ZERO(), c, p); }