result lineIntersectsPolygon(line & l, polygon & P, size_t sz, int k) { int n = (sz + k - 1) / k; double minDist = numeric_limits<double>::max(); int minPoint = -1; unordered_set<int> points; if (n <= 50) { point prev = P->get(0); for (size_t i = k; i < sz; i += k) { point cur = P->get(i); segment s = {prev, cur}; if (lineIntersectsSegment(l, s)) { points.insert(i - k); } else { double dist = fabs(l.dist(cur)); if (minDist > dist) { minDist = dist; minPoint = i; } } prev = cur; } } else { auto ind = lineIntersectsPolygon(l, P, sz, 2 * k); if (ind.points.size() != 0) { for (int i : ind.points) { point p1 = P->get(i - k); point p2 = P->get(i); segment s = {p1, p2}; if (lineIntersectsSegment(l, s)) { points.insert((i - k + sz) % sz); } else { points.insert(i); } } } else { int i = ind.closest; point p1 = P->get(i - 2 * k); point p2 = P->get(i - k); point p3 = P->get(i); point p4 = P->get(i + k); point p5 = P->get(i + 2 * k); point pts[] = {p1, p2, p3, p4, p5}; segment segs[] = {{p1, p2}, {p2, p3}, {p3, p4}, {p4, p5}}; for (int j = 0; j < 4; j++) { if (lineIntersectsSegment(l, segs[j])) { points.insert((i + k * (j - 2) + sz) % sz); } } for (int j = 0; j < 5; j++) { double dist = fabs(l.dist(pts[j])); if (minDist > dist) { minDist = dist; minPoint = (i + k * (j - 2) + sz) % sz; } } } } return {points, minPoint}; }
CGALPolygon toCGALPolygon(polygon p) { vector<CGALPoint> pnts; for (auto v : p.get()) pnts.push_back(CGALPoint(v[0], v[1])); return CGALPolygon( &pnts[0], &pnts[pnts.size()-1] ); }