programming-examples/c++/Basic/FindIntersection.cpp
2019-11-18 14:44:36 +01:00

104 lines
3.0 KiB
C++

#include <algorithm>
#include <vector>
#include <set>
using namespace std;
typedef pair<int, int> pii;
int cross(int ax, int ay, int bx, int by, int cx, int cy) {
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
}
int cross(pii a, pii b, pii c) {
return cross(a.first, a.second, b.first, b.second, c.first, c.second);
}
class segment {
public:
pii a, b;
int id;
segment(pii a, pii b, int id) :
a(a), b(b), id(id) {
}
bool operator<(const segment &o) const {
if (a.first < o.a.first) {
int s = cross(a, b, o.a);
return (s > 0 || s == 0 && a.second < o.a.second);
} else if (a.first > o.a.first) {
int s = cross(o.a, o.b, a);
return (s < 0 || s == 0 && a.second < o.a.second);
}
return a.second < o.a.second;
}
};
class event {
public:
pii p;
int id;
int type;
event(pii p, int id, int type) :
p(p), id(id), type(type) {
}
bool operator<(const event &o) const {
return p.first < o.p.first || p.first == o.p.first && (type > o.type || type == o.type && p.second < o.p.second);
}
};
bool intersect(segment s1, segment s2) {
int x1 = s1.a.first, y1 = s1.a.second, x2 = s1.b.first, y2 = s1.b.second;
int x3 = s2.a.first, y3 = s2.a.second, x4 = s2.b.first, y4 = s2.b.second;
if (max(x1, x2) < min(x3, x4) || max(x3, x4) < min(x1, x2) || max(y1, y2) < min(y3, y4) || max(y3, y4) < min(y1, y2)) {
return false;
}
int z1 = (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1);
int z2 = (x4 - x1) * (y2 - y1) - (y4 - y1) * (x2 - x1);
if (z1 < 0 && z2 < 0 || z1 > 0 && z2 > 0) {
return false;
}
int z3 = (x1 - x3) * (y4 - y3) - (y1 - y3) * (x4 - x3);
int z4 = (x2 - x3) * (y4 - y3) - (y2 - y3) * (x4 - x3);
if (z3 < 0 && z4 < 0 || z3 > 0 && z4 > 0) {
return false;
}
return true;
}
pii findIntersection(vector<segment> s) {
int n = s.size();
vector<event> e;
for (int i = 0; i < n; ++i) {
if (s[i].a > s[i].b)
swap(s[i].a, s[i].b);
e.push_back(event(s[i].a, i, 1));
e.push_back(event(s[i].b, i, -1));
}
sort(e.begin(), e.end());
set<segment> q;
for (int i = 0; i < n * 2; ++i) {
int id = e[i].id;
if (e[i].type == 1) {
set<segment>::iterator it = q.lower_bound(s[id]);
if (it != q.end() && intersect(*it, s[id]))
return make_pair(it->id, s[id].id);
if (it != q.begin() && intersect(*--it, s[id]))
return make_pair(it->id, s[id].id);
q.insert(s[id]);
} else {
set<segment>::iterator it = q.lower_bound(s[id]), next = it, prev = it;
if (it != q.begin() && it != --q.end()) {
++next, --prev;
if (intersect(*next, *prev))
return make_pair(next->id, prev->id);
}
q.erase(it);
}
}
return make_pair(-1, -1);
}
int main() {
}