Half-plane Intersection

From EOJ Wiki
Revision as of 00:54, 11 March 2018 by Ultmaster (talk | contribs) (Created page with "<syntaxhighlight lang='cpp'> struct Line { PT p, v; double ang; Line() {} Line(PT from, PT to) : p(from), v(to - from) { ang = atan2(v.y, v.x); } friend b...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
struct Line {
    PT p, v;
    double ang;

    Line() {}
    Line(PT from, PT to) : p(from), v(to - from) { ang = atan2(v.y, v.x); }
    friend bool operator<(Line a, Line b) {
        return a.ang < b.ang;
    }
};

bool OnLeft(Line L, PT p) {
    return dcmp(cross(L.v, p - L.p)) >= 0;
}

PT GetIntersection(Line a, Line b) {
    PT u = a.p - b.p;
    ld t = cross(b.v, u) / cross(a.v, b.v);
    return a.p + a.v * t;
}

vector<PT> HalfplaneIntersection(vector<Line>& L) {
    int n = L.size();
    sort(L.begin(), L.end());

    int first, last;
    vector<PT> p(n);
    vector<Line> q(n);
    q[first = last = 0] = L[0];
    for (int i = 1; i < n; i++) {
        while (first < last && !OnLeft(L[i], p[last - 1])) last--;
        while (first < last && !OnLeft(L[i], p[first])) first++;
        q[++last] = L[i];
        if (dcmp(cross(q[last].v, q[last - 1].v)) == 0) {
            last--;
            if (OnLeft(q[last], L[i].p)) q[last] = L[i];
        }
        if (first < last) p[last - 1] = GetIntersection(q[last - 1], q[last]);
    }
    while (first < last && !OnLeft(q[first], p[last - 1])) last--;
    if (last - first <= 1) return vector<PT>();
    p[last] = GetIntersection(q[last], q[first]);

    return vector<PT>(p.begin() + first, p.begin() + last + 1);
}

vector<PT> convexIntersection(const vector<PT> &v1, const vector<PT> &v2) {
    vector<Line> h;
    int n = v1.size(), m = v2.size();
    for (int i = 0; i < n; ++i)
        h.push_back(Line(v1[i], v1[(i + 1) % n]));
    for (int i = 0; i < m; ++i)
        h.push_back(Line(v2[i], v2[(i + 1) % m]));
    return HalfplaneIntersection(h);
}

ld ComputeSignedArea(const vector<PT> &p) {
    ld area = 0;
    for (unsigned i = 0; i < p.size(); i++) {
        unsigned j = (i + 1) % p.size();
        area += p[i].x * p[j].y - p[j].x * p[i].y;
    }
    return area / 2.0;
}

ld ComputeArea(const vector<PT> &p) {
    return fabs(ComputeSignedArea(p));
}