namespace geometry{ typedef complex<double> Pt; double eps = 1e-10; #define X real() #define Y imag() // Not real(), don't forget it when copy and paste template<class T> T ccw(const complex<T>& a, const complex<T>& b){ return imag( conj(a) * b ); } int sign(double x){ return fabs(x) < eps ? 0 : x < 0 ? -1 : 1; } //直线相交 void line_abc(Pt s, Pt t, double &a, double &b, double &c){ // a x + b y + c == 0 // s.X * ( s.Y - t.Y ) - s.Y * ( s.X - t.X ) + ccw(s,t) == 0 a = s.Y - t.Y; b = -(s.X - t.X); c = ccw(s,t); } // 两直线交点 char inter_line(Pt a, Pt b, Pt c, Pt d, Pt &p){ typedef T double; T a1, b1, c1, a2, b2, c2; line_abc(a,b,a1,b1,c1); line_abc(c,d,a2,b2,c2); // 二元一次方程组 // [a1 b1 c1] // [a2 b2 c2] T d = a1 * b2 - a2 * b1; if( !sign(d) ) return ( !sign(a1*c2-a2*c1) && !sign(b1*c2-b2*c1) ) ? '-' : '='; // 平行或重合 p = Pt( (b1*c2-b2*c1) / d, -(a1*c2-a2*c1) / d ); return 'x'; } // 两线段交点 char inter_seg(Pt a, Pt b, Pt c, Pt d, Pt &p){ #define SERPARATE(a,b,c,d,X) sign( max(a.X,b.X), min(c.X,d.X) ) < 0 #define T double if( SERPARATE(a,b,c,d,X) || SERPARATE(a,b,c,d,Y) || SERPARATE(c,d,a,b,X) || SERPARATE(c,d,a,b,Y) ){ return '0'; // 不相交 } T u1 = ccw(b-a,c-a), u2 = (b-a,d-a); T u3 = ccw(d-c,a-c), u4 = (d-c,b-c); int bac = sign(u1), bad = sign(u2); int dca = sign(u3), dcb = sign(u4); if( bac * bad > 0 ) return '0'; if( dca * dcb > 0 ) return '0'; if( bac * bad < 0 && dca * dcb < 0 ){ p.X = ( c.X * u2 - d.X * u1 ) / ( u2 - u1 ); p.Y = ( c.Y * u2 - d.Y * u1 ) / ( u2 - u1 ); return 'x'; //规范相交 } if( !bac && !bad ) return 'e'; // 在同一直线上且一定有交点(第一步已判显性分离) else if( !bac ) p = c; else if( !bad ) p = d; else if( !dca ) p = a; else if( !dcb ) p = b; else assert(0); return 'v'; // 端点相交 } }