118 const std::function<
bool()>& running = {}) {
120 if (p.size() > 1 && p.front().x == p.back().x && p.front().y == p.back().y)
123 return "Missing polygon (unmapped).";
125 if (!std::isfinite(v.x) || !std::isfinite(v.y))
126 return "Non-finite polygon coordinate.";
128 for (std::size_t i = 0; i < p.size(); ++i) {
129 if (running && !running())
130 return "Preview cancelled.";
131 const auto j = (i + 1) % p.size();
132 if (p[i].x == p[j].x && p[i].
y == p[j].
y)
133 return "Duplicate polygon vertex.";
134 for (std::size_t k = i + 1; k < p.size(); ++k) {
135 const auto l = (k + 1) % p.size();
136 if (j == k || l == i)
139 return "Self-intersecting polygon; holes/multipart rings are unsupported.";
143 return "Degenerate polygon.";
145 std::reverse(p.begin(), p.end());
148 while (changed && p.size() > 3) {
150 for (std::size_t i = 0; i < p.size(); ++i) {
151 if (std::abs(
cross(p[(i + p.size() - 1) % p.size()], p[i], p[(i + 1) % p.size()])) <=
153 p.erase(p.begin() + i);
159 std::vector<int> ids(p.size());
160 std::iota(ids.begin(), ids.end(), 0);
161 while (ids.size() > 3) {
162 if (running && !running())
163 return "Preview cancelled.";
165 for (std::size_t k = 0; k < ids.size(); ++k) {
166 const int a = ids[(k + ids.size() - 1) % ids.size()], b = ids[k],
167 c = ids[(k + 1) % ids.size()];
168 if (
cross(p[a], p[b], p[c]) <= eps)
172 if (d != a && d != b && d != c &&
cross(p[a], p[b], p[d]) >= -eps &&
173 cross(p[b], p[c], p[d]) >= -eps &&
cross(p[c], p[a], p[d]) >= -eps) {
179 triangles.push_back({p[a], p[b], p[c]});
180 ids.erase(ids.begin() + k);
185 return "Polygon triangulation failed; repair topology.";
187 triangles.push_back({p[ids[0]], p[ids[1]], p[ids[2]]});
203 for (std::size_t i = 0; i < clip.size() && !subject.empty(); ++i) {
204 const auto a = clip[i], b = clip[(i + 1) % clip.size()];
206 for (std::size_t k = 0; k < subject.size(); ++k) {
207 const auto p = subject[k], q = subject[(k + 1) % subject.size()];
208 const auto sp =
cross(a, b, p), sq =
cross(a, b, q);
211 if ((sp >= 0) != (sq >= 0)) {
212 const auto t = sp / (sp - sq);
213 next.push_back({p.x + t * (q.x - p.x), p.y + t * (q.y - p.y)});
216 subject = std::move(next);