Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cassert>
- #include <algorithm>
- #include <functional>
- #include <iostream>
- #include <limits>
- #include <queue>
- #include <set>
- #include <string>
- #include <tuple>
- #include <vector>
- using namespace std;
- template <typename T> int sgn(T val) {
- return (T(0) < val) - (val < T(0));
- }
- const double EPS = 0.0001;
- inline bool eq(double d1, double d2) {
- const double d = d1-d2;
- return d > (-EPS) && d < EPS;
- }
- inline bool le(double d1, double d2) {
- return d1-d2 < -EPS;
- }
- inline bool ge(double d1, double d2) {
- return d1-d2 > EPS;
- }
- struct Pt {
- double x, y;
- Pt(double _x, double _y) : x(_x), y(_y) {}
- Pt(const Pt &rr) : x(rr.x), y(rr.y) {}
- bool operator<(const Pt& rr) const {
- return make_pair(x, y) < make_pair(rr.x, rr.y);
- }
- bool operator>(const Pt& rr) const {
- return make_pair(x, y) > make_pair(rr.x, rr.y);
- }
- friend bool operator==(const Pt &a, const Pt &b);
- friend ostream& operator<<(ostream &stream, const Pt &p);
- };
- bool operator==(const Pt &a, const Pt &b) {
- return !(a<b || a>b);
- }
- ostream& operator<<(ostream &stream, const Pt &p) {
- stream << "(" << p.x << "," << p.y << ")";
- return stream;
- }
- enum Side {
- ONLEFT = 0, // explicit for a reason -- don't change!
- ONLINE = 1,
- ONRIGHT = 3
- };
- inline double det(double px, double py, double qx, double qy, double rx, double ry) {
- return (px-rx)*(qy-ry)-(qx-rx)*(py-ry);
- }
- inline double det(const Pt &p, const Pt &q, const Pt &r) {
- return det(p.x, p.y, q.x, q.y, r.x, r.y);
- }
- inline Side whichSide(const Pt &a, const Pt &b, const Pt &c) {
- const double d = det(a,b,c);
- if(le(d,0.0))
- return ONRIGHT;
- if(ge(d,0.0))
- return ONLEFT;
- return ONLINE;
- }
- struct Seg {
- Pt a, b;
- char name;
- Seg(const Pt _a, const Pt _b, const char _name = '_') : a(_a), b(_b), name(_name) {}
- bool contains(const Pt& rr) const {
- if(whichSide(a,b,rr) != ONLINE)
- return false;
- return ( min(a.x,b.x) <= rr.x && rr.x <= max(a.x,b.x)
- && min(a.y,b.y) <= rr.y && rr.y <= max(a.y,b.y) );
- }
- bool operator^(const Seg& rr) const { // przecięcie
- const Pt& p1 = a;
- const Pt& p2 = b;
- const Pt& p3 = rr.a;
- const Pt& p4 = rr.b;
- Side d1 = whichSide(p3, p4, p1);
- Side d2 = whichSide(p3, p4, p2);
- Side d3 = whichSide(p1, p2, p3);
- Side d4 = whichSide(p1, p2, p4);
- if(d1+d2 == ONLEFT+ONRIGHT
- && d3+d4 == ONLEFT+ONRIGHT) return true;
- if(d1 == ONLINE && rr.contains(p1)) return true;
- if(d2 == ONLINE && rr.contains(p2)) return true;
- if(d3 == ONLINE && contains(p3)) return true;
- if(d4 == ONLINE && contains(p4)) return true;
- return false;
- }
- Pt getIntersection(const Seg& rr) const {
- assert(operator^(rr));
- const double &x1 = a.x;
- const double &x2 = b.x;
- const double &x3 = rr.a.x;
- const double &x4 = rr.b.x;
- const double &y1 = a.y;
- const double &y2 = b.y;
- const double &y3 = rr.a.y;
- const double &y4 = rr.b.y;
- const double dvsr = (x1-x2)*(y3-y4)-(x3-x4)*(y1-y2);
- const double x = ( x2*(x3*y4-x4*y3+(x4-x3)*y1)+x1*(x4*y3-x3*y4+(x3-x4)*y2) ) / dvsr;
- const double y = ( y2*(x3*y4-x4*y3)+y1*(x4*y3-x3*y4)+x2*y1*(y4-y3)+x1*y2*(y3-y4) ) / dvsr;
- return Pt(x,y);
- }
- bool operator<(const Seg &rr) const {
- if(whichSide(a, b, rr.a) == ONLINE)
- return whichSide(a,b, rr.b) == ONRIGHT;
- return whichSide(a, b, rr.a) == ONRIGHT;
- }
- bool operator>(const Seg &rr) const {
- if(whichSide(a, b, rr.a) == ONLINE)
- return whichSide(a,b, rr.b) == ONLEFT;
- return whichSide(a, b, rr.a) == ONLEFT;
- }
- bool operator==(const Seg &rr) const {
- return make_pair(a, b) == make_pair(rr.a, rr.b);
- }
- friend ostream& operator<<(ostream &stream, const Seg &p);
- };
- ostream& operator<<(ostream &stream, const Seg &l) {
- stream << "[" << l.name << ": " << l.a << " --> " << l.b << "]";
- return stream;
- }
- struct Event {
- enum Event_t { Begin, Intersection, Vertical, End } evt;
- Pt p;
- Seg l1, l2;
- Event(Event_t _evt, const Pt &_p, const Seg &_l1) : evt(_evt), p(_p), l1(_l1), l2(_l1) {}
- Event(Event_t _evt, const Pt &_p, const Seg &_l1, const Seg &_l2) : evt(_evt), p(_p), l1(_l1), l2(_l2) {}
- bool operator<(const Event &rr) const {
- if(make_pair(p.x,evt) == make_pair(rr.p.x, rr.evt))
- return make_pair(p.y, l1) < make_pair(rr.p.y, rr.l1);
- return make_pair(p.x,evt) < make_pair(rr.p.x, rr.evt);
- }
- bool operator>(const Event &rr) const {
- if(make_pair(p.x,evt) == make_pair(rr.p.x, rr.evt))
- return make_pair(p.y, l1) > make_pair(rr.p.y, rr.l1);
- return make_pair(p.x,evt) > make_pair(rr.p.x, rr.evt);
- }
- bool operator==(const Event &rr) const {
- return make_pair(p.x,evt) == make_pair(rr.p.x, rr.evt) && make_pair(p.y, l1) < make_pair(rr.p.y, rr.l1);
- }
- friend ostream& operator<<(ostream &stream, const Event &e);
- };
- ostream& operator<<(ostream &stream, const Event &e) {
- switch(e.evt) {
- case Event::Begin:
- stream << "{beg " << e.p << ": " << e.l1 << " }";
- break;
- case Event::End:
- stream << "{end " << e.p << ": " << e.l1 << " }";
- break;
- case Event::Intersection:
- stream << "{int " << e.p << ": " << e.l1 << " x " << e.l2 << " }";
- break;
- case Event::Vertical:
- default:
- stream << "{vrt " << e.p << ": " << e.l1 << " }";
- }
- return stream;
- }
- struct segcmp {
- bool operator()(const Seg &p, const Seg &q) const {
- bool less = p > q;
- cout << " " << p << (less ? " < " : " >= ") << q << "\n";
- return less;
- }
- };
- typedef set<Seg, segcmp> tree;
- typedef set<Seg, segcmp>::iterator tree_iterator;
- typedef priority_queue<const Event, vector<Event>, greater<Event> > pqueue; // TODO usunąć drugi argument templatki
- void printset(const char* msg, const tree &t) {
- cout << " " << msg << "SL→ ";
- for(tree_iterator it = t.begin(); it!=t.end(); ++it)
- cout << *it << " , ";
- cout << "\n";
- }
- int main() {
- assert( det(0,0,0,1,1,1) < 0);
- assert( det(0,0,0,1,-1,1) > 0);
- assert( (Seg(Pt(0,0),Pt(0,1)) ^ Seg(Pt(0,0),Pt(1,0))) == true);
- assert( (Seg(Pt(0,0),Pt(0,3)) ^ Seg(Pt(-1,1),Pt(1,1))) == true);
- assert( (Seg(Pt(0,0),Pt(4,4))).contains(Pt(2,2)) );
- assert( (Seg(Pt(0,0),Pt(4,4))).getIntersection(Seg(Pt(4,4),Pt(0,0))) == Pt(2,2) );
- assert( (Seg(Pt(3,7),Pt(7,7)) ^ Seg(Pt(7,7),Pt(8,7))) == true );
- assert( make_pair(5,1) > make_pair(3,7) );
- int N;
- pqueue ksi;
- scanf(" %d ", &N);
- for(int i=0; i<N; ++i) {
- char n;
- double ax, ay, bx, by;
- scanf(" %c %lf %lf %lf %lf ", &n, &ax, &ay, &bx, &by);
- Pt a(ax,ay);
- Pt b(bx,by);
- if(eq(ax, bx)) {
- if(a < b)
- ksi.push(Event(Event::Vertical, a, Seg(a,b,n)));
- else
- ksi.push(Event(Event::Vertical, b, Seg(a,b,n)));
- } else {
- if(a < b) {
- ksi.push(Event(Event::Begin, a, Seg(a,b,n)));
- ksi.push(Event(Event::End, b, Seg(a,b,n)));
- } else {
- ksi.push(Event(Event::Begin, b, Seg(b,a,n)));
- ksi.push(Event(Event::End, a, Seg(b,a,n)));
- }
- }
- }
- tree SL;
- unsigned int tmp_size = 0;
- while(! ksi.empty()) {
- Event evt = ksi.top(); ksi.pop();
- cout << evt << "\n";
- pair<tree_iterator,bool> ins;
- tree_iterator pred, succ, it;
- const Seg &seg = evt.l1;
- printset("pre: ", SL);
- switch(evt.evt) {
- case Event::Begin:
- assert(SL.size() == tmp_size);
- ins = SL.insert(seg);
- pred = ins.first;
- succ = ins.first;
- assert(SL.size() == ++tmp_size);
- if((pred != SL.begin()) && (seg ^ (*(--pred)))) { // TODO: while ma być!
- ksi.push(Event(Event::Intersection, seg.getIntersection(*pred), *pred, seg));
- cout << " pusz intersection (1): " << *pred << " x " << seg << "\n";
- assert(!(seg == *pred));
- }
- if((++succ != SL.end()) && (seg ^ (*succ))) { // TODO: while ma być!
- ksi.push(Event(Event::Intersection, seg.getIntersection(*succ), seg, *succ));
- cout << " pusz intersection (1): " << seg << " x " << *succ << "\n";
- assert(!(seg == *succ));
- }
- assert(SL.size() == tmp_size);
- break;
- case Event::End:
- assert(SL.size() == tmp_size);
- it = SL.find(seg);
- assert(it != SL.end());
- pred = it;
- succ = it;
- if(pred != SL.begin() && succ != SL.end() && (*--pred)^(*++succ)) {
- const Pt I = (*pred).getIntersection(*succ);
- // tu sprawdzenie, czy I należy juz do ksi
- cout << " pusz intersection (2): " << *pred << " x " << *succ << "\n";
- ksi.push(Event(Event::Intersection, I, (*pred), (*succ)));
- assert(!(*pred == *succ));
- }
- tmp_size = SL.size();
- SL.erase(it);
- assert(SL.size() == --tmp_size);
- break;
- case Event::Vertical:
- // TODO: to be done
- break;
- case Event::Intersection:
- assert(SL.size() == tmp_size);
- Seg sA = evt.l1;
- Seg sB = evt.l2;
- cout << "\t\t\tUsuwam: " << sA << " oraz " << sB << "\n";
- assert( SL.find(sA) != SL.end() );
- assert( SL.find(sB) != SL.end() );
- SL.erase(SL.find(sA));
- SL.erase(SL.find(sB));
- printset("inter (1): ", SL);
- assert(tmp_size -2 == SL.size());
- sA.a = sB.a = evt.p;
- if(sB < sA)
- swap(sA, sB);
- cout << "\t\t\tPoprawione p, wstawiam: " << sA << " < " << sB << "\n";
- pred = SL.insert(sA).first;
- succ = SL.insert(sB).first;
- printset("inter (2): ", SL);
- assert( SL.find(sA) != SL.end() );
- assert( SL.find(sB) != SL.end() );
- assert( ((sA > sB) && (!((sB > sA)))) || ((sB > sA) && (!((sA > sB)))) );
- cout << "\t\t\tSize " << SL.size() << " =?= " << tmp_size << "\n";
- assert(SL.size() == tmp_size);
- if(pred != SL.begin() && sA ^ *--pred && !(sB == *pred)) {
- assert(!(sA == *pred));
- assert(!(sB == *pred));
- ksi.push(Event(Event::Intersection, sA.getIntersection(*pred), *pred, sA));
- cout << " pusz intersection (3a): " << *pred << " x " << sA << "\n";
- }
- if(++succ != SL.end() && sB ^ *succ && !(sA == *succ)) {
- assert(!(sA == *succ));
- assert(!(sB == *succ));
- ksi.push(Event(Event::Intersection, sB.getIntersection(*succ), *succ, sB));
- cout << " pusz intersection (3b): " << *succ << " x " << sB << "\n";
- }
- }
- printset("post: ", SL);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement