#include #include #include #include #include #include #include using namespace std; // 点 typedef complex point; istream& operator>>( istream& is, point& pt ) { double x, y; is >> x >> y; pt = point(x,y); return is; } // 光線 : a-->b struct ray { point a, b; ray( point a, point b ) : a(a), b(b) {} }; // 辺 : a-->b : 左が内側 struct edge { point a, b; edge( point a, point b ) : a(a), b(b) {} vector cross; // 辺に関して点を鏡像反転 point flip( point p ) const { point v = (b-a)/abs(b-a); return conj((p-a)/v)*v + a; } // 光線との交点計算 bool cross_impl( const ray& r, double* cp=0, double* rp=0 ) const { // ra-->rb と 0-->len の交点があれば、という問題に変換 double len = abs(b-a); point ra = (r.a-a) / ((b-a)/len); point rb = (r.b-a) / ((b-a)/len); // 自明にダメな例をはじく if( ra.imag() <= 0 ) return false; // 始点が壁の裏 if( (rb-ra).imag() >= 0 ) return false; // 光線が逆方向 // 実軸との交点を計算 double p = (-ra.imag() * (rb-ra).real() / (rb-ra).imag() + ra.real()) / len; if(cp) *cp=p; if(rp) *rp=(-ra.imag() / (rb-ra).imag()); double eps = numeric_limits::epsilon(); return (0-eps<=p && p<=1+eps); } bool rayseg_crosses( const ray& r, point* pt=0 ) const { double p, q; if( !cross_impl(r,&p,&q) || !(0& es, point src, double pp ) { point p = a+(b-a)*pp; if( !is_ray_collides(es,ray(src,p)) ) { cerr << "direct" << endl; return true; } for(int j=0; j!=es.size(); ++j) if( &es[j] != this ) { point q; if( es[j].rayseg_crosses( ray(src,es[j].flip(p)), &q ) ) if( !is_ray_collides(es,ray(src,q)) ) if( !is_ray_collides(es,ray(q,p)) ) { cerr << "reflection at: " << src << "===" << q << "===>" << es[j].flip(p) << endl; return true; } } return false; } // 光線分が壁にぶつかるか? bool is_ray_collides( const vector& es, const ray& r ) { for(int j=0; j!=es.size(); ++j) if( es[j].rayseg_crosses(r) ) return true; return false; } }; double solve( vector& es, const vector& ps, point src ) { // 0回反射、1回反射で出現しうる全光線を列挙 vector rs; for(int i=0; i!=ps.size(); ++i) rs.push_back( ray(src,ps[i]) ); for(int j=0; j!=es.size(); ++j) for(int i=0; i!=ps.size(); ++i) rs.push_back( ray(es[j].flip(src),ps[i]) ), rs.push_back( ray(es[j].flip(src),es[j].flip(ps[i])) ); // 全光線から出現しうる全交点を列挙 for(int j=0; j!=es.size(); ++j) for(int k=0; k!=rs.size(); ++k) es[j].add_cross(rs[k]); // 列挙した交点をSortして重複除去 for(int j=0; j!=es.size(); ++j) es[j].manip_cross(); // 各区間が見えるか見えないか判定して和を取る double sum = 0.0; for(int j=0; j!=es.size(); ++j) for(int k=0; k+1>N,N; ) { // 入力 vector ps(N); for(int i=0; i!=N; ++i) cin >> ps[i]; point src; cin >> src; // 加工 vector es; for(int i=0; i!=N; ++i) es.push_back( edge(ps[i%N],ps[(i+1)%N]) ); // 出力 cout << setiosflags(ios::fixed) << setprecision(8) << solve(es,ps,src) << endl; } }