Problem:
全自動円形掃除機
English text is not available in this practice contest.
Automatic Cleaning Machine (ACM) 社は画期的な全自動円形掃除機 Intelligent Circular Perfect Cleaner(ICPC) を開発した．
なんとこの ICPC は人がいない日中に自動で動き出し，自分が通り過ぎた場所のゴミを掃除する機能を備えている．
全自動という特性を活かすためにも ICPC の集塵機の容積を大きくし，人手でゴミを捨てる回数を減らしたい．
しかしながら ICPC が大型化すればするほど ICPC が円形故に部屋の隅の掃除できない部分の面積も大きくなってしまう．(図G-1)
図G-1
また廊下の幅よりも大きくしてしまうと廊下を通ることができなくなってしまう．(図G-2)
図G-2
ACM 社は凄腕プログラマーのあなたに，部屋の見取り図とICPCの中心座標と半径からその部屋の中でICPCが掃除可能な面積を出力するプログラムの作成を依頼した．
Input
入力は複数のデータセットからなり，各データセットは以下の形式をしている．
n
x
y
r
x
1
y
1
x
2
y
2
...
x
n
y
n
データセットの1行目には４つの整数
n
,
x
,
y
,
r
が記されており，それぞれ部屋を構成する多角形の頂点数(3 ≤
n
≤ 20)，
ICPCの初期位置の中心座標 (-100 ≤
x
,
y
≤ 100)， ICPCの半径 (1 ≤
r
≤ 100)を表している．
続く
n
行には多角形の頂点の座標が反時計回りに記されており，以下の条件を満たす．
-100 ≤
x
i
,
y
i
≤ 100
全ての壁は，x軸かy軸に並行
ICPCの初期位置は必ず部屋の内側にあり，どの部屋の壁とも10
-3
以上離れている
任意の部屋の頂点同士の距離，任意の部屋の頂点と部屋の辺の距離，任意の部屋の辺同士の距離は 2
r
+10
-3
より大きいかもしくは 2
r
-10
-3
より小さい
四つのゼロのみからなる行が入力の終わりを表す．
Output
各データセットに対し，ICPCが掃除可能な領域の面積を1行に出力せよ．答えには10
-6
を超える誤差があってはならない．
Sample Input
4 5 5 1
0 0
10 0
10 10
0 10
8 5 5 1
0 0
9 0
9 1
10 1
10 9
9 9
9 10
0 10
12 25 5 1
0 0
10 0
10 4
20 4
20 0 
40 0
40 10
20 10
20 5
10 5
10 10
0 10
0 0 0 0
Output for the Sample Input
99.1415926535897
96.7123889804
199.2321787

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

const int nrep = 50;

/********************* Geometry Library *****************/
const double EPS = 1e-9;
const double INF = 1e12;
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP{
    L(const P& a, const P& b){ resize(2); at(0)=a; at(1)=b; }
    L(){ resize(2); }
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r) : p(p), r(r) {}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X != b.X) ? a.X<b.X : a.Y<b.Y;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}

int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) <-EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}

P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
bool intersectSP(const L &s, const P &p) {
    return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS;
}
double distanceLP(const L &l, const P &p) {
    return abs(p - projection(l, p));
}
double distanceSP(const L &s, const P &p) {
    const P r = projection(s, p);
    if (intersectSP(s, r)) return abs(r - p);
    return min(abs(s[0] - p), abs(s[1] - p));
}

VP crosspointLC(const L &l, const C &c){
    VP ret;
    P mid = projection(l, c.p);
    double dlp = distanceLP(l, c.p);
    if(EQ(dlp, c.r)){
        ret.push_back(mid);
        return ret;
    }
    if(dlp > c.r){
        return ret;
    }
    P d = sqrt(c.r*c.r -dlp*dlp)/abs(l[1]-l[0]) *(l[1]-l[0]);
    ret.push_back(mid+d);
    ret.push_back(mid-d);
    return ret;
}
VP crosspointSC(const L &s, const C &c){
    VP ret;
    VP cp = crosspointLC(s,c);
    for(int i=0; i<(int)cp.size(); i++){
        if(dot(s[1]-s[0], cp[i]-s[0]) < EPS) continue;
        if(norm(s[1]-s[0]) < norm(cp[i]-s[0]) +EPS) continue;
        ret.push_back(cp[i]);
    }
    return ret;
}

double getangle(P p, P a, P b){
    a -= p;
    b -= p;
    return acos(dot(a,b)/(abs(a)*abs(b)));
}
double getarea(const VP &p) {
    double ret = 0;
    for (int i=0; i<(int)p.size(); i++){ 
        ret += cross(p[i], p[(i+1)%p.size()]);
    }
    return ret*0.5;
}
/********************* end Library ***********************/

int main(){
    while(1){
        /******************* Input ************************/
        int n,x,y,r;
        cin >> n >> x >> y >> r;
        if(n==0) break;
    
        C robot(P(x,y), r);
        VP v(n);
        for(int i=0; i<n; i++){
            int vx,vy;
            cin >> vx >> vy;
            v[i] = P(vx, vy);
        }
        //rotate the order of vertices to start from horizontal edge
        if(v[0].X == v[1].X){ 
            v.push_back(v[0]);
            v.erase(v.begin());
        }
        /****************** end Input **********************/

        /*********** Move to the initial state ***********/
        //go right until touch the wall
        while(1){
            robot.p += P(1.0, 0);
            bool reach = false;
            for(int i=0; i<n; i++){
                if(distanceSP(L(v[i],v[(i+1)%n]), robot.p) < r){
                    reach = true;
                    break;
                }
            }
            if(reach) break;
        }
        //binary search
        P s = robot.p -P(1.0, 0);
        P e = robot.p;
        for(int i=0; i<nrep; i++){
            robot.p = (s+e)*0.5;
            bool reach = false;
            for(int i=0; i<n; i++){
                if(distanceSP(L(v[i],v[(i+1)%n]), robot.p) < r){
                    reach = true;
                }
            }
            if(reach) e = robot.p;
            else s = robot.p;
        }

        bool onedge;
        int sidx;
        for(int i=0; i<n; i++){
            if(abs(robot.p -v[i]) < r+EPS){
                sidx = i;
                onedge = false;
                break;
            }
            if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r+EPS){
                if(abs(robot.p -v[i]) > r+EPS && abs(robot.p -v[(i+1)%n]) > r+EPS){
                    sidx = i;
                    onedge = true;
                    break;
                }
            }
        }
        /********************* end initial state **********************/

        /************************* Main Loop **************************/
        //move along the wall
        VP vlist;
        double area = 0.0;
        while(1){
            /******** Case 1. contact with the edge (parallel displacement) *******/
            if(onedge){
                //search the limit
                P dir = (v[(sidx+1)%n]-v[sidx])/abs(v[(sidx+1)%n]-v[sidx]);
                P limit = (sidx%2==0)? P(v[(sidx+1)%n].X, robot.p.Y) :P(robot.p.X, v[(sidx+1)%n].Y);
                P s,e;
                s = e = robot.p;
                while(1){
                    e += dir;
                    if(dot(limit-e, dir) < 0){
                        e = limit;
                        break;
                    }
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        if(distanceSP(L(v[i],v[(i+1)%n]), e) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) break;
                }
        
                //binary search
                for(int i=0; i<nrep; i++){
                    robot.p = (s+e)*0.5;
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        //if turn left (avoid errors)
                        if(i==(sidx+1)%n && cross(v[(sidx+1)%n]-v[sidx],v[(sidx+2)%n]-v[sidx])<0){
                            continue;
                        }
                        if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) e = robot.p;
                    else s = robot.p;
                }

                //calculate ridx and last;
                P last;
                double eval = -INF;
                int ridx;
                bool n_onedge;
                bool terminate = false;
                P cpedge = (sidx%2==0)? P(robot.p.X, v[sidx].Y) :P(v[sidx].X, robot.p.Y);
                for(int i=0; i<n; i++){
                    if(i==sidx || i==(sidx-1+n)%n) continue;                
                    if(abs(robot.p -v[i]) < r+EPS){
                        if(!vlist.empty() && EQ(vlist[0], v[i])){
                            last = v[i];
                            terminate = true;
                            break;
                        }
                        if(dot(robot.p-cpedge, v[i]-cpedge) > eval) {
                            last = v[i];
                            eval = dot(robot.p-cpedge, v[i]-cpedge);
                            ridx = i;
                            n_onedge = false;
                        }
                    }
                    if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r +EPS){
                        if(abs(robot.p -v[i])>r+EPS && abs(robot.p -v[(i+1)%n])>r+EPS){
                            //except vertices
                            VP cp = crosspointSC(L(v[i], v[(i+1)%n]), robot);
                            if(!vlist.empty() && EQ(vlist[0], cp[0])){
                                last = cp[0];
                                terminate = true;
                                break;
                            }
                            if(dot(robot.p-cpedge, cp[0]-cpedge) > eval) {
                                last = cp[0];
                                eval = dot(robot.p-cpedge, cp[0]-cpedge);
                                ridx = i;
                                n_onedge = true;
                            }
                        }
                    }
                }
                                                 
                //calculate area ...
                if(!vlist.empty() && EQ(vlist[0], cpedge)){
                    terminate = true;
                    last = cpedge;
                }
                double a = getangle(robot.p, last, cpedge);
                area += r*r*M_PI*a/(2*M_PI) -r*r*sin(a)*0.5;
                vlist.push_back(cpedge);
                vlist.push_back(last);
                if(terminate){
                    break;
                }else{
                    onedge = n_onedge;
                    sidx = ridx;
                }
            }
            
            /************ Case 2. contact with the vertex (rotate) ************/
            else{
                double d;
                double dxy;
                P s, e;
                s = e = robot.p;
                //search limit
                if(sidx%2==1){
                    d = (v[sidx].X-v[(sidx-1+n)%n].X > 0)? 1: -1;
                    dxy = fabs(e.X -v[sidx].X);
                    if(abs(2*e.X -round(2*e.X)) > EPS){
                        dxy = floor(2*dxy) *0.5;
                    }
                }else{
                    d = (v[sidx].Y-v[(sidx-1+n)%n].Y > 0)? 1: -1;
                    dxy = fabs(e.Y -v[sidx].Y);
                    if(abs(2*e.Y -round(2*e.Y)) > EPS){
                        dxy = floor(2*dxy) *0.5;
                    }
                }

                P start = (v[sidx] -v[(sidx+1)%n]) *(r / abs(v[sidx] -v[(sidx+1)%n]));
                while(1){
                    dxy += 0.5;
                    if(dxy +EPS > r){
                        e = v[sidx] + start*P(0,-1);
                        break;
                    }
                    if(sidx%2==1){
                        e = v[sidx] +d*P(dxy, sqrt(fabs(r*r-dxy*dxy)));
                    }else{
                        e = v[sidx] +d*P(-sqrt(fabs(r*r-dxy*dxy)), dxy);
                    }
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        if(distanceSP(L(v[i], v[(i+1)%n]), e) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) break;
                }

                //binary search
                for(int i=0; i<nrep; i++){
                    double angle_s = getangle(v[sidx],start+v[sidx],s);
                    double angle_e = getangle(v[sidx],start+v[sidx],e);
                    double midangle = (angle_s +angle_e)*0.5;
                    robot.p = v[sidx] + start*P(cos(midangle), -sin(midangle));
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) e = robot.p;
                    else s = robot.p;
                }

                //calculate ridx, last
                P last;
                double eval = -INF;
                int ridx;
                bool n_onedge;
                bool terminate = false;
                for(int i=0; i<n; i++){
                    if(abs(robot.p -v[i]) < r+EPS){
                        if(cross(robot.p-v[sidx], v[i]-v[sidx]) < EPS){
                            if(i!=sidx && !vlist.empty() && EQ(vlist[0], v[i])){
                                last = v[i];
                                terminate = true;
                                break;
                            }
                            if(dot(robot.p-v[sidx], v[i]-v[sidx]) > eval) {
                                last = v[i];
                                eval = dot(robot.p-v[sidx], v[i]-v[sidx]);
                                ridx = i;
                                n_onedge = false;
                            }
                        }
                    }
                    if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r +EPS){
                        if(abs(robot.p -v[i])>r+EPS && abs(robot.p -v[(i+1)%n])>r+EPS){
                            //except vertices
                            VP cp = crosspointSC(L(v[i], v[(i+1)%n]), robot);
                            if(cross(robot.p-v[sidx], v[i]-v[sidx]) < EPS){
                                if(!vlist.empty() && EQ(vlist[0], cp[0])){
                                    last = cp[0];
                                    terminate = true;
                                    break;
                                }
                                if(dot(robot.p-v[sidx], cp[0]-v[sidx]) > eval){
                                    last = cp[0];
                                    eval = dot(robot.p-v[sidx], cp[0]-v[sidx]);
                                    ridx = i;
                                    n_onedge = true;
                                }
                            }
                        }
                    }
                }
                if(last == v[sidx]){
                    onedge = true;
                    continue;
                }
                
                //calculate area ...
                if(!vlist.empty()){
                    double a = getangle(robot.p, last, v[sidx]);
                    area += r*r*M_PI*a/(2*M_PI) -r*r*sin(a)*0.5;
                }
                vlist.push_back(last);
                if(terminate){
                    break;
                }else{
                    onedge = n_onedge;
                    sidx = ridx;
                }
            }
        }

        area += getarea(vlist);
        cout << fixed;
        cout << setprecision(10);
        cout << area << endl;
    }
    /*********************** end Main Loop ************************/
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3580
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

const int nrep = 50; //num of reptition of binary search

/********************* Geometry Library *****************/
const double EPS = 1e-9;
const double INF = 1e12;
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP{
    L(const P& a, const P& b){ resize(2); at(0)=a; at(1)=b; }
    L(){ resize(2); }
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r) : p(p), r(r) {}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X != b.X) ? a.X<b.X : a.Y<b.Y;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}

int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) <-EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}

P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
bool intersectSP(const L &s, const P &p) {
    return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS;
}
double distanceLP(const L &l, const P &p) {
    return abs(p - projection(l, p));
}
double distanceSP(const L &s, const P &p) {
    const P r = projection(s, p);
    if (intersectSP(s, r)) return abs(r - p);
    return min(abs(s[0] - p), abs(s[1] - p));
}

VP crosspointLC(const L &l, const C &c){
    VP ret;
    P mid = projection(l, c.p);
    double dlp = distanceLP(l, c.p);
    if(EQ(dlp, c.r)){
        ret.push_back(mid);
        return ret;
    }
    if(dlp > c.r){
        return ret;
    }
    P d = sqrt(c.r*c.r -dlp*dlp)/abs(l[1]-l[0]) *(l[1]-l[0]);
    ret.push_back(mid+d);
    ret.push_back(mid-d);
    return ret;
}
VP crosspointSC(const L &s, const C &c){
    VP ret;
    VP cp = crosspointLC(s,c);
    for(int i=0; i<(int)cp.size(); i++){
        if(dot(s[1]-s[0], cp[i]-s[0]) < EPS) continue;
        if(norm(s[1]-s[0]) < norm(cp[i]-s[0]) +EPS) continue;
        ret.push_back(cp[i]);
    }
    return ret;
}

double getangle(P p, P a, P b){
    a -= p;
    b -= p;
    return acos(dot(a,b)/(abs(a)*abs(b)));
}
double getarea(const VP &p) {
    double ret = 0;
    for (int i=0; i<(int)p.size(); i++){ 
        ret += cross(p[i], p[(i+1)%p.size()]);
    }
    return ret*0.5;
}
/********************* end Library ***********************/

int main(){
    while(1){
        /******************* Input ************************/
        int n,x,y,r;
        cin >> n >> x >> y >> r;
        if(n==0) break;
    
        C robot(P(x,y), r);
        VP v(n);
        for(int i=0; i<n; i++){
            int vx,vy;
            cin >> vx >> vy;
            v[i] = P(vx, vy);
        }
        //rotate the order of vertices to start from horizontal edge
        if(v[0].X == v[1].X){ 
            v.push_back(v[0]);
            v.erase(v.begin());
        }
        /****************** end Input **********************/

        /*********** Move to the initial state ***********/
        //go right until touch the wall
        while(1){
            robot.p += P(1.0, 0);
            bool reach = false;
            for(int i=0; i<n; i++){
                if(distanceSP(L(v[i],v[(i+1)%n]), robot.p) < r){
                    reach = true;
                    break;
                }
            }
            if(reach) break;
        }
        //binary search
        P s = robot.p -P(1.0, 0);
        P e = robot.p;
        for(int i=0; i<nrep; i++){
            robot.p = (s+e)*0.5;
            bool reach = false;
            for(int i=0; i<n; i++){
                if(distanceSP(L(v[i],v[(i+1)%n]), robot.p) < r){
                    reach = true;
                }
            }
            if(reach) e = robot.p;
            else s = robot.p;
        }

        bool onedge;
        int sidx;
        for(int i=0; i<n; i++){
            if(abs(robot.p -v[i]) < r+EPS){
                sidx = i;
                onedge = false;
                break;
            }
            if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r+EPS){
                if(abs(robot.p -v[i]) > r+EPS && abs(robot.p -v[(i+1)%n]) > r+EPS){
                    sidx = i;
                    onedge = true;
                    break;
                }
            }
        }
        /********************* end initial state **********************/

        /************************* Main Loop **************************/
        //move along the wall
        VP vlist;
        double area = 0.0;
        int step=0;
        cerr << fixed;
        cerr << setprecision(10);
        while(1){
            if(step++ ==50) break;
            /*
            cerr << robot.p << endl;
            if(onedge) cerr << "edge ";
            else cerr << "vertex ";
            cerr << sidx << endl;
            //cerr << "area " << area << endl;
            */
            
            /****************** Case 1. contact with the edge *************/
            if(onedge){
                //search the limit
                P dir = (v[(sidx+1)%n]-v[sidx])/abs(v[(sidx+1)%n]-v[sidx]);
                P limit = (sidx%2==0)? P(v[(sidx+1)%n].X, robot.p.Y) :P(robot.p.X, v[(sidx+1)%n].Y);
                P s,e;
                s = e = robot.p;
                while(1){
                    e += dir;
                    if(dot(limit-e, dir) < 0){
                        e = limit;
                        break;
                    }
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        if(distanceSP(L(v[i],v[(i+1)%n]), e) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) break;
                }
        
                //binary search
                //cerr << s << " " << e << endl;
                for(int i=0; i<nrep; i++){
                    robot.p = (s+e)*0.5;
                    //cerr << robot.p << endl;
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        //if turn left (avoid errors)
                        if(i==(sidx+1)%n && cross(v[(sidx+1)%n]-v[sidx],v[(sidx+2)%n]-v[sidx])<0){
                            continue;
                        }
                        if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) e = robot.p;
                    else s = robot.p;
                }

                //calculate ridx and last;
                P last;
                double eval = -INF;
                int ridx;
                bool n_onedge;
                bool terminate = false;
                P cpedge = (sidx%2==0)? P(robot.p.X, v[sidx].Y) :P(v[sidx].X, robot.p.Y);
                for(int i=0; i<n; i++){
                    if(i==sidx || i==(sidx-1+n)%n) continue;                
                    if(abs(robot.p -v[i]) < r+EPS){
                        if(!vlist.empty() && EQ(vlist[0], v[i])){
                            last = v[i];
                            terminate = true;
                            break;
                        }
                        if(dot(robot.p-cpedge, v[i]-cpedge) > eval) {
                            last = v[i];
                            eval = dot(robot.p-cpedge, v[i]-cpedge);
                            ridx = i;
                            n_onedge = false;
                        }
                    }
                    if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r +EPS){
                        if(abs(robot.p -v[i])>r+EPS && abs(robot.p -v[(i+1)%n])>r+EPS){
                            //except vertices
                            VP cp = crosspointSC(L(v[i], v[(i+1)%n]), robot);
                            if(!vlist.empty() && EQ(vlist[0], cp[0])){
                                last = cp[0];
                                terminate = true;
                                break;
                            }
                            if(dot(robot.p-cpedge, cp[0]-cpedge) > eval) {
                                last = cp[0];
                                eval = dot(robot.p-cpedge, cp[0]-cpedge);
                                ridx = i;
                                n_onedge = true;
                            }
                        }
                    }
                }
                                                 
                //calculate area ...
                if(!vlist.empty() && EQ(vlist[0], cpedge)){
                    terminate = true;
                    last = cpedge;
                }
                double a = getangle(robot.p, last, cpedge);
                area += r*r*M_PI*a/(2*M_PI) -r*r*sin(a)*0.5;
                vlist.push_back(cpedge);
                vlist.push_back(last);
                if(terminate){
                    break;
                }else{
                    onedge = n_onedge;
                    sidx = ridx;
                }
            }
            /************************* end Case 1. *********************/
            /************ Case 2. contact with the vertex *********************/
            else{
                //rotate
                double d;
                double dxy;
                P s, e;
                s = e = robot.p;
                //search limit
                if(sidx%2==1){
                    d = (v[sidx].X-v[(sidx-1+n)%n].X > 0)? 1: -1;
                    dxy = fabs(e.X -v[sidx].X);
                    if(abs(2*e.X -round(2*e.X)) > EPS){
                        dxy = floor(2*dxy) *0.5;
                    }
                }else{
                    d = (v[sidx].Y-v[(sidx-1+n)%n].Y > 0)? 1: -1;
                    dxy = fabs(e.Y -v[sidx].Y);
                    if(abs(2*e.Y -round(2*e.Y)) > EPS){
                        dxy = floor(2*dxy) *0.5;
                    }
                }

                P start = (v[sidx] -v[(sidx+1)%n]) *(r / abs(v[sidx] -v[(sidx+1)%n]));
                while(1){
                    dxy += 0.5;
                    if(dxy +EPS > r){
                        e = v[sidx] + start*P(0,-1);
                        break;
                    }
                    if(sidx%2==1){
                        e = v[sidx] +d*P(dxy, sqrt(fabs(r*r-dxy*dxy)));
                    }else{
                        e = v[sidx] +d*P(-sqrt(fabs(r*r-dxy*dxy)), dxy);
                    }
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        if(distanceSP(L(v[i], v[(i+1)%n]), e) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) break;
                }

                //binary search
                //cerr << s << " " << e << endl;
                for(int i=0; i<nrep; i++){
                    double angle_s = getangle(v[sidx],start+v[sidx],s);
                    double angle_e = getangle(v[sidx],start+v[sidx],e);
                    double midangle = (angle_s +angle_e)*0.5;
                    robot.p = v[sidx] + start*P(cos(midangle), -sin(midangle));
                    //cerr << robot.p << endl;
                    bool reach = false;
                    for(int i=0; i<n; i++){
                        if(i==sidx || i==(sidx-1+n)%n) continue;
                        if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r){
                            reach = true;
                            break;
                        }
                    }
                    if(reach) e = robot.p;
                    else s = robot.p;
                }

                //calculate ridx, last
                P last;
                double eval = -INF;
                int ridx;
                bool n_onedge;
                bool terminate = false;
                for(int i=0; i<n; i++){
                    if(abs(robot.p -v[i]) < r+EPS){
                        if(cross(robot.p-v[sidx], v[i]-v[sidx]) < EPS){
                            if(i!=sidx && !vlist.empty() && EQ(vlist[0], v[i])){
                                last = v[i];
                                terminate = true;
                                break;
                            }
                            if(dot(robot.p-v[sidx], v[i]-v[sidx]) > eval) {
                                last = v[i];
                                eval = dot(robot.p-v[sidx], v[i]-v[sidx]);
                                ridx = i;
                                n_onedge = false;
                            }
                        }
                    }
                    if(distanceSP(L(v[i], v[(i+1)%n]), robot.p) < r +EPS){
                        if(abs(robot.p -v[i])>r+EPS && abs(robot.p -v[(i+1)%n])>r+EPS){
                            //except vertices
                            VP cp = crosspointSC(L(v[i], v[(i+1)%n]), robot);
                            if(cross(robot.p-v[sidx], v[i]-v[sidx]) < EPS){
                                if(!vlist.empty() && EQ(vlist[0], cp[0])){
                                    last = cp[0];
                                    terminate = true;
                                    break;
                                }
                                if(dot(robot.p-v[sidx], cp[0]-v[sidx]) > eval){
                                    last = cp[0];
                                    eval = dot(robot.p-v[sidx], cp[0]-v[sidx]);
                                    ridx = i;
                                    n_onedge = true;
                                }
                            }
                        }
                    }
                }
                if(last == v[sidx]){
                    onedge = true;
                    continue;
                }
                
                //calculate area ...
                if(!vlist.empty()){
                    double a = getangle(robot.p, last, v[sidx]);
                    area += r*r*M_PI*a/(2*M_PI) -r*r*sin(a)*0.5;
                }
                vlist.push_back(last);
                if(terminate){
                    break;
                }else{
                    onedge = n_onedge;
                    sidx = ridx;
                }
            }
            /************************ end Case 2. *********************/
        }

        /*
        for(int i=0; i<(int)vlist.size(); i++){
            cerr << vlist[i] << endl;
        }
        cerr << getarea(vlist) << endl;
        */
        area += getarea(vlist);
        cout << fixed;
        cout << setprecision(10);
        cout << area << endl;
    }
    /*********************** end Main Loop ************************/
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3548
final_rank: 6

code_snippet: #include<cstdio>
#include<vector>
#include<complex>
#include<cmath>
#include<utility>
#include<map>
#include<algorithm>

using namespace std;

typedef double Real;
typedef complex<Real> Point;
typedef pair<Point,Point> Segment;
typedef pair<Point,Point> Line;
typedef vector<Point> Polygon;

const Real eps=1e-8;
const Real PI=acos(-1.0);
const Point NPoint=Point(NAN,NAN);

template<class T> bool eq(T a, T b){
	return abs(a-b)<eps;
}

template<class T> int sgn(T a){
	if(eq(a,(T)0)) return 0;
	if(a>0) return 1;
	return -1;
}

void print(Point p,char ch='\n'){
	printf("(%f %f)%c",p.real(),p.imag(),ch);
}

bool onSeg(Point a,Point b,Point c){
	return eq(abs(a-b),abs(a-c)+abs(c-b));
}

bool onSeg(Segment s,Point p){
	return onSeg(s.first,s.second,p);
}

struct Circle:vector<Real>{
	Point c;
	Real r;
	Circle(){}
	Circle(Point c,Real r):c(c),r(r){}
};

struct Segs:Segment{
	vector<Point> pts;
	Segs(){}
	Segs(Point p,Point q){
		this->first=p;
		this->second=q;
	}
	Segs(Segment seg){
		this->first=seg.first;
		this->second=seg.second;
	}
};

Real arg(Point p){
	return atan2(p.imag(),p.real());
}

Real normalize(Real theta){
	while(theta>PI) theta-=PI*2;
	while(theta<-PI) theta+=PI*2;
	return theta;
}

Point getPoint(Point c,Real r,Real ang){
	return c+r*Point(cos(ang),sin(ang));
}

Real doP(Point a,Point b){
	return (conj(a)*b).real();
}

Real crP(Point a,Point b){
	return (conj(a)*b).imag();
}

Point proj(Point p,Point b){
	return b*doP(p,b)/norm(b);
}

Point perp(Line l,Point a){
	Point p=l.first,q=l.second;
	return p+proj(a-p,q-p);
}

Real dLP(Line l,Point p){
	Point h=perp(l,p);
	return abs(h-p);
}

Real dPS(Point p,Segment s){
	Point h=perp(s,p);
	if(onSeg(s,h)) return abs(h-p);
	return min(abs(s.first-p),abs(s.second-p));
}

bool isPara_(Point p,Point q){
	return sgn(crP(p,q))==0;
}

Point iLL(Line l1,Line l2){
	if(isPara_(l1.second-l1.first,l2.second-l2.first)) return NPoint;
	Point a1=l1.first,b1=l1.second;
	Point a2=l2.first,b2=l2.second;
	Real num=crP(a2-a1,b1-a1);
	Real den=crP(b1-a1,b2-a2);
	return a2+(b2-a2)*(num/den);
}

void iCL(Circle &c,Line l){//lが中心をとおるときに注意!!
	Point h=perp(l,c.c);
	Real d=abs(h-c.c);
	if(sgn(d)==0){
		Point p=l.first;
		if(eq(p,c.c)) p=l.second;
		Real ang=arg(p-c.c);
		c.push_back(normalize(ang));
		c.push_back(normalize(ang+PI));
		return;
	}
	if(sgn(d-c.r)>0) return;
	else if(sgn(d-c.r)==0){
		c.push_back(arg(h-c.c));
	}else{
		Real ang=arg(h-c.c);
		Real ang2=acos(d/c.r);
		c.push_back(normalize(ang+ang2));
		c.push_back(normalize(ang-ang2));
	}
}

void iCC(Circle &c,Circle &c2){
	if(eq(c.c,c2.c)) return;
	Real d=abs(c.c-c2.c);
	Real r=c.r,r2=c2.r;
	if(sgn(d-(r+r2))>0) return;
	else if(sgn(d-(r+r2))==0){//out tangent
		Real ang=normalize(arg(c2.c-c.c));
		c.push_back(ang);
	}else if(sgn(d-abs(r-r2))>0){//intersect two points
		Real ang=arg(c2.c-c.c);
		Real ang2=acos((r*r+d*d-r2*r2)/(2*r*d));
		c.push_back(normalize(ang+ang2));
		c.push_back(normalize(ang-ang2));
	}else if(sgn(d-abs(r-r2))==0){//in tangent
		if(r>r2){
			c.push_back(normalize(arg(c2.c-c.c)));
		}else{
			c.push_back(normalize(-arg(c2.c-c.c)));
		}
	}else{//contained
		return;
	}
}

bool inPoly_(Polygon poly,Point p){//ON is OUT
	bool in=false;
	for(int i=0;i+1<poly.size();i++){
		Point a=poly[i],b=poly[i+1];
		if(onSeg(a,b,p)) return false;
		a-=p,b-=p;
		if(sgn(a.imag()-b.imag())>0) swap(a,b);
		if(sgn(a.imag())<=0&&sgn(b.imag())>0){
			int s=sgn(crP(a,b));
			if(s==-1) in=!in;
		}
	}
	return in;
}

bool isCounter_(Polygon poly){
	Real a=0;
	for(int i=0;i+1<poly.size();i++){
		Real tmp=crP(poly[i],poly[i+1]);
		a+=tmp;
	}
	return a>0;
}

struct Edge{
	Point to;
	Point c;
	bool used;
	Edge(){}
	Edge(Point p):to(p){
		c=NPoint;
		used=false;
	}
	Edge(Point p,Point q):to(p),c(q){
		used=false;
	}
};

typedef vector<Edge> Shape;

void print(Shape sh){
	for(int i=0;i<sh.size();i++){
		print(sh[i].to);
	}
	printf("\n");
}

struct PLexCmp{
	bool operator()(const Point &p1,const Point &p2) const {
		if(p1.real()!=p2.real()) return p1.real()<p2.real();
		return p1.imag()<p2.imag();
	}
};

vector<Point> pts;
vector<Point> pts2;
map<Point,Point,PLexCmp> merged_pts;

Polygon poly;
Real R;
Point init_point;

vector<Circle> cs;
vector<Segs> segss;

void getCs(){
	for(int i=0;i+1<poly.size();i++){
		cs.push_back(Circle(poly[i],R));
	}
}

void getSegss(){
	for(int i=0;i+1<poly.size();i++){
		Point p1=poly[i],p2=poly[i+1];
		//R内側にずらす 
		Point dir=(p2-p1)/abs(p2-p1);
		dir*=(Point(0,1));
		dir*=R;
		Point q1=p1+dir,q2=p2+dir;
		Segment tmp=Segment(q1,q2);
		Point mid=(q1+q2)/(Real)2;
//		if(inPoly_(poly,mid)==false) continue;
		//Segment tmp=Segment(poly[i],poly[i+1]);
		Segs segs=tmp;
//		if(sgn(R*2-abs(segs.second-segs.first))>0) continue;
		Point bVec=poly[i+1]-poly[i];
		bVec/=abs(bVec);
		Point p=segs.first+bVec*R;
		if(onSeg(q1,q2,p)){
			segs.pts.push_back(p);
		}
		p=segs.second-bVec*R;
		if(onSeg(q1,q2,p)){
			segs.pts.push_back(p);
		}
		segss.push_back(segs);
//		print(segs.first,' ');
//		print(segs.second);
	}
}

void processCircle(){
	for(int i=0;i<cs.size();i++){
		for(int j=0;j<cs.size();j++){
			if(i==j) continue;
			iCC(cs[i],cs[j]);
		}
	}
	for(int i=0;i<cs.size();i++){
		for(int j=0;j<segss.size();j++){
			Circle tmp=Circle(cs[i].c,cs[i].r);
			iCL(tmp,segss[j]);
			for(int k=0;k<tmp.size();k++){
				Point p=getPoint(tmp.c,tmp.r,tmp[k]);
				if(onSeg(segss[j].first,segss[j].second,p)){
					Point dir=p-tmp.c;
					Real ang=arg(dir);
					cs[i].push_back(ang);
				}
			}
		}
	}
	for(int i=0;i<cs.size();i++){
		for(int j=0;j+1<poly.size();j++){
			Segment seg=Segment(poly[j],poly[j+1]);
			Circle tmp=Circle(cs[i].c,cs[i].r);
			iCL(tmp,seg);
			for(int k=0;k<tmp.size();k++){
				Point p=getPoint(tmp.c,tmp.r,tmp[k]);
				if(onSeg(seg.first,seg.second,p)){
					Point dir=p-tmp.c;
					Real ang=arg(dir);
					cs[i].push_back(ang);
				}
			}
		}
	}
}

void processSegs(){
	for(int i=0;i<segss.size();i++){
		Point p1=segss[i].first,p2=segss[i].second;
		for(int j=0;j<poly.size();j++){
			Circle tmp=Circle(poly[j],R);
			iCL(tmp,segss[i]);
			for(int k=0;k<tmp.size();k++){
				Point p=getPoint(tmp.c,tmp.r,tmp[k]);
				if(onSeg(p1,p2,p)&&(!eq(p1,p))&&(!eq(p2,p))){
					segss[i].pts.push_back(p);
				}
			}
		}
		for(int j=0;j+1<poly.size();j++){
			Segment seg=Segment(poly[j],poly[j+1]);
			Point p=iLL(seg,segss[i]);
			if(onSeg(p1,p2,p)&&onSeg(poly[j],poly[j+1],p)){
				Circle tmp=Circle(p,R);
				iCL(tmp,segss[i]);
				for(int k=0;k<tmp.size();k++){
					Point p=getPoint(tmp.c,tmp.r,tmp[k]);
					if(onSeg(p1,p2,p)){
						segss[i].pts.push_back(p);
					}
				}
			}
		}
		segss[i].pts.push_back(p1);
		segss[i].pts.push_back(p2);
	}
/*	for(int i=0;i<segss.size();i++){
		printf("i=%d\n",i);
		for(int j=0;j<segss[i].pts.size();j++){
			print(segss[i].pts[j],' ');
		}
		printf("\n");
	}*/
}

Point cmp_c;
bool p_cmp_dis(const Point &p1,const Point &p2){
	Real d1=abs(cmp_c-p1);
	Real d2=abs(cmp_c-p2);
	if(eq(d1,d2)) return true;
	return d1<d2;
}

void getAllPoint(){
	for(int i=0;i<cs.size();i++){
		sort(cs[i].begin(),cs[i].end());
		if(cs[i].empty()) continue;
		if(eq(cs[i].front(),-PI)&&eq(cs[i].back(),PI)){
			cs[i].pop_back();
		}
		for(int j=0;j<cs[i].size();j++){
			Point p=getPoint(cs[i].c,cs[i].r,cs[i][j]);
			pts.push_back(p);
		}
	}
	for(int i=0;i<segss.size();i++){
		cmp_c=segss[i].first;
		sort(segss[i].pts.begin(),segss[i].pts.end(),p_cmp_dis);
		for(int j=0;j<segss[i].pts.size();j++){
			pts.push_back(segss[i].pts[j]);
		}
	}
}

void mergePoints(){
	for(int i=0;i<pts.size();i++){
		Point p=NPoint;
		for(int j=0;j<pts2.size();j++){
			if(eq(pts[i],pts2[j])){
				p=pts2[j];
				break;
			}
		}
		if(isnan(p.real())){
			p=pts[i];
			pts2.push_back(p);
			merged_pts[p]=p;
		}else{
			merged_pts[pts[i]]=p;
		}
	}/*
	for(int i=0;i<pts2.size();i++){
		print(pts2[i]);
	}
	printf("\n");*/
}

map<Point,vector<Edge>,PLexCmp> edges;

bool check(Point p){
	for(int i=0;i+1<poly.size();i++){
		Point p1=poly[i],p2=poly[i+1];
		Segment seg=Segment(p1,p2);
		Real d=dPS(p,seg);
		if(sgn(d-R)<0) return false;
		d=abs(p1-p);
		if(sgn(d-R)<0) return false;
	}
	if(inPoly_(poly,p)==false) return false;
	return true;
}

void getEdges(){
	for(int i=0;i<cs.size();i++){
		sort(cs[i].begin(),cs[i].end());
//		printf("center=");
//		print(cs[i].c);
		for(int j=0;j<cs[i].size();j++){
			Real ang1=cs[i][j];
			Real ang2=cs[i][j+1<cs[i].size()?j+1:0];
//			printf("%f %f\n",ang1,ang2);
			Point p1=getPoint(cs[i].c,cs[i].r,cs[i][j]);
			Point p2=getPoint(cs[i].c,cs[i].r,ang2);
			if(ang2<ang1) ang2+=PI*2;
			Point mid=getPoint(cs[i].c,cs[i].r,(ang1+ang2)/2);
			bool flg=check(mid);
			if(eq(p1,p2)) continue;
			if(flg){
				Point mp1=merged_pts[p1];
				Point mp2=merged_pts[p2];
				Edge e=Edge(mp2,cs[i].c);
				edges[mp1].push_back(e);
				e=Edge(mp1,cs[i].c);
				edges[mp2].push_back(e);
/*				printf("circle, ");
				print(mp1,' ');
				print(mp2);
				printf("mid=");
				print(mid);*/
			//	printf("%f %f\n",ang1,cs[i][j+1<cs[i].size()?j+1:0]);
			}
		}
	}
	for(int i=0;i<segss.size();i++){
		vector<Point> &pts=segss[i].pts;
		cmp_c=segss[i].first;
		sort(pts.begin(),pts.end(),p_cmp_dis);
		for(int j=0;j+1<pts.size();j++){
			Point p1=pts[j];
			Point p2=pts[j+1];
			if(eq(p1,p2)) continue;
			Point mid=(p1+p2)/(Real)2;
			bool flg=check(mid);
			if(flg){
				Point mp1=merged_pts[p1];
				Point mp2=merged_pts[p2];
				Edge e=Edge(mp1);
				edges[mp2].push_back(e);
				e=Edge(mp2);
				edges[mp1].push_back(e);
/*				printf("segment, ");
				print(mp1,' ');
				print(mp2);*/
			}
		}
	}
}

void stroke(vector<Edge> &es,Point cur,Point prv){
	vector<Edge> &cur_es=edges[cur];
	for(int i=0;i<cur_es.size();i++){
		Edge &e=cur_es[i];
		if(eq(e.to,prv)) continue;
		if(e.used){
			return;
		}
		es.push_back(e);
		e.used=true;
		stroke(es,e.to,cur);
	}
}

bool inShape_(Shape sh,Point p){
	Polygon poly;
	for(int i=0;i<sh.size();i++){
		poly.push_back(sh[i].to);
	}
	poly.push_back(poly[0]);
	bool flg=inPoly_(poly,p);
	for(int i=0;i<sh.size();i++){
		Edge e=sh[i];
		if(isnan(e.c.real())) continue;
		Point p1=sh[i==0?sh.size()-1:i-1].to;
		Point p2=sh[i].to;
		Point c=sh[i].c;
		int s1=sgn(crP(c-p1,p2-p1));
		int s2=sgn(crP(p-p1,p2-p1));
		if(s1*s2<0){
			Real d=abs(c-p);
			if(sgn(d-R)<0){
				flg=!flg;
			}
		}
	}
	return flg;
}

Real getInArea(Shape sh){
	Real res=0;
	Real dec=0;
	for(int i=0;i<sh.size();i++){
		Point p1=sh[i==0?sh.size()-1:i-1].to;
		Point p2=sh[i].to;
		Point c=sh[i].c;
		Real tmp=crP(p1,p2)/2.0;
		res+=tmp;
		if(isnan(c.real())==false){
			Real ang1=arg(p1-c);
			Real ang2=arg(p2-c);
			Real ang=ang2-ang1;
			while(ang<0) ang+=PI*2;
			if(ang>PI) ang=PI*2-ang;
			Real tmp2=R*R*sin(ang)/(Real)2.0;
			Real tmp3=R*R*ang/2.0;
			dec+=(tmp3-tmp2);
		}
	}
	if(res<0) res*=-1;
//	printf("%f %f\n",res,dec);
	return res-dec;
}

Real getOutArea(Shape sh){
	Real res1=0,res2=0;
	for(int i=0;i<sh.size();i++){
		Edge e=sh[i];
		if(isnan(e.c.real())){
			Point t=e.to;
			Point s=sh[i==0?sh.size()-1:i-1].to;
			Real l=abs(t-s);
			Real area=l*R;
			res1+=area;
		}
	}
	for(int i=0;i<sh.size();i++){
		int j=i==0?sh.size()-1:i-1;
		int k=j==0?sh.size()-1:j-1;
		Point p1,p2,p3,c1,c2;
		p3=sh[i].to;
		p2=sh[j].to;
		p1=sh[k].to;
		c2=sh[i].c;
		c1=sh[j].c;
		Point q1=isnan(c1.real())?p1:c1;
		Point q2=isnan(c2.real())?p3:c2;
		Real ang=arg(q2-p2)-arg(q1-p2);
//		print(p2);
//		print(q1);
//		print(q2);
//		printf("%f %f\n",arg(q2-p2),arg(q1-p2));
		while(sgn(ang)<0) ang+=PI*2;
		if(isnan(c1.real())) ang-=PI/2;
		if(isnan(c2.real())) ang-=PI/2;
		Real area=R*R*ang/2;
//		printf("+=%f\n",ang);
		res2+=area;
/*		if(isnan(c1.real())!=isnan(c2.real())){
			Real ang1,ang2;
			if(isnan(c1.real())==false){
				ang1=arg(c1-p2);
				ang2=arg(p3-p2);
			}else{
				ang1=arg(p1-p2);
				ang2=arg(c2-p2);
			}
			Real ang=ang2-ang1;
			while(ang<PI/2) ang+=PI*2;
			if(sgn(ang-PI)>0) ang=PI*2-ang;
			ang-=PI/2;
			Real area=R*R*ang/2;
			res2+=area;
			printf("+=%f\n",ang);
		}else if(isnan(c1.real())==true){
			Point v2=p3-p2;
			Point v1=p2-p1;
			if(sgn(crP(v1,v2))==0) continue;
			Real ang=PI/2;
			Real area=R*R*ang/2;
			printf("+=%f\n",ang);
			res2+=area;
		}else{
			Real ang1=arg(c2-p2);
			Real ang2=arg(c1-p2);
			Real ang=ang2-ang1;
			while(ang<0) ang+=PI*2;
			if(ang>PI) ang=PI*2-ang;
			Real area=R*R*ang/2;
			printf("+=%f\n",ang);
			res2+=area;
		}*/
	}
	Real res3=0;
	for(int i=0;i<sh.size();i++){
		Point p2=sh[i].to;
		Point p1=sh[i==0?sh.size()-1:i-1].to;
		Point c=sh[i].c;
		if(isnan(c.real())==false){
			Real ang1=arg(p2-c);
			Real ang2=arg(p1-c);
			Real ang=ang2-ang1;
			while(ang<0) ang+=PI*2;
			if(ang>PI) ang=PI*2-ang;
			Real tmp=R*R*ang/(Real)2;
			res3+=tmp;
		}
	}
//	printf("%f %f %f\n",res1,res2,res3);
	return res1+res2+res3;
}

Shape reverse_shape(Shape sh){
	Shape res;
	if(sh.size()==0) return sh;
	for(int i=sh.size()-1;i>0;i--){
		Edge e=Edge(sh[i-1].to,sh[i].c);
		res.push_back(e);
	}
	res.push_back(Edge(sh.back().to,sh[0].c));
	return res;
}

Polygon toPoly(Shape sh){
	Polygon res;
	if(sh.size()==0) return res;
	for(int i=0;i<sh.size();i++){
		res.push_back(sh[i].to);
	}
	res.push_back(res[0]);
	return res;
}


Real getArea(Shape sh){
/*	for(int i=0;i<sh.size();i++){
		print(sh[i].to);
	}*/
	Polygon tmp=toPoly(sh);
//	print(sh);
	if(!isCounter_(tmp)){
		sh=reverse_shape(sh);
	}
//	print(sh);
	Real area1=getInArea(sh);
	Real area2=getOutArea(sh);
	return area1+area2;
}

Real solve(){
	getCs();
	getSegss();
	processCircle();
	processSegs();
	getAllPoint();
	mergePoints();
	getEdges();
	map<Point,vector<Edge>,PLexCmp> ::iterator it=edges.begin();
	for(;it!=edges.end();it++){
		vector<Edge> &vec=it->second;
		for(int i=0;i<vec.size();i++){
			if(vec[i].used==false){
				Point prv=it->first;
				Point cur=vec[i].to;
				vector<Edge> sh;
				sh.push_back(vec[i]);
				vec[i].used=true;
				stroke(sh,cur,prv);
	//			print(sh);
				if(inShape_(sh,init_point)){
					Real res=getArea(sh);
					return res;
				}
			}
		}
	}
	return -1;
}

int test_cnt=0;

void input(){
	test_cnt++;
	int n,x,y,r;
	scanf("%d%d%d%d",&n,&x,&y,&r);
	if(n==0) exit(0);
	init_point=Point(x,y);
	R=r;
	for(int i=0;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		poly.push_back(Point(x,y));
	}
	poly.push_back(poly[0]);
}

void init(){
	pts.clear();
	pts2.clear();
	map<Point,Point,PLexCmp> tmp_merged_pts;
	swap(merged_pts,tmp_merged_pts);
	map<Point,vector<Edge>,PLexCmp> tmp_edges;
	swap(edges,tmp_edges);
	cs.clear();
	segss.clear();
	poly.clear();
}

int main(){
	while(true){
		init();
		input();
		Real ans=solve();
		printf("%.10f\n",ans);
	//	break;
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1344
final_rank: 3

code_snippet: #include <cmath>
#include <algorithm>
#include <vector>
#include <iostream>
#include <complex>
using namespace std;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define ALL(container) (container).begin(), (container).end()
#define mp(a,b) make_pair(a, b)

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef long double R;
	const R INF = 1e10;
	R EPS = 1e-10;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
	};
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
	};
	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
#undef SELF
#undef at
}

using namespace geom;

namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
}

int n;

C icpc;
G g;

pair<P, R> getType(const P &p){
	REP(i, n){
		const S s = g.edge(i);
		if(s.online(p) == TRUE) return mp(s.dir(), abs(s[1] - p));
	}
	REP(i, n){
		const P q = g[i];
		if(!sig(abs(q - p))){
			P tar = q + unit(g.edge(i).dir())*P(0, 1)*icpc.r;
			if(!sig(abs(icpc - tar))) return mp(g.edge(i).dir(), abs(g.edge(i).dir()));
			return mp(tar, arg((tar - p)/(icpc - p)));
		}
	}
}

P getNavigator(){
	vector<pair<R, P>> isc;
	REP(i, n){
		const S s = g.edge(i);
		P q = proj(icpc, s);
		if(s.online(q) == TRUE && !sig(abs(q - icpc) - icpc.r))
			isc.emplace_back(arg(q - icpc), q);
	}
	REP(i, n){
		const P q = g[i];
		if(!sig(abs(q - icpc) - icpc.r)) isc.emplace_back(arg(q - icpc), q);
	}
	sort(ALL(isc));
	pair<R, P> pp(.0, P(0, 0));
	REP(i, isc.size()){
		const auto cur = isc[i];
		const auto nxt = isc[(i+1)%isc.size()];
		R nxtarg = i+1 == isc.size() ? nxt.first + 2*PI : nxt.first;
		pp = max(pp, mp(nxtarg - cur.first, cur.second));
	}
	
	return pp.second;
}

R straight(P dir, R d = INF){
	REP(i, n){
		const S s = g.edge(i);
		if(sig(arg(dir*P(0, 1)/s.dir())) || inp(proj(icpc, s) - icpc, dir) < EPS || s.online(proj(icpc, s)) != TRUE) continue;
		d = min(d, abs(proj(icpc, s) - icpc) - icpc.r);
	}
	REP(i, n){
		const P q = g[i];
		R r = abs(q - proj(q, L(icpc, icpc+dir)));
		if(r + EPS > icpc.r || inp(q - icpc, dir) < EPS) continue;
		d = min(d, abs(proj(q, L(icpc, icpc+dir)) - icpc) - sqrt(icpc.r*icpc.r-r*r));
	}
	return d;
}

R rot(P nav, R r){
	REP(i, n){
		const S s = g.edge(i);
		if(abs(proj(nav, s) - nav) < EPS) continue;
		R t = arg((proj(nav, s) - nav)/(icpc - nav));
		if(t > 0 && t < PI) continue;
		R d = abs(proj(nav, s) - nav);
		if(d > 2*icpc.r - EPS) continue;
		R x = arg(s.dir()) - asin((d-icpc.r) / icpc.r) - arg(icpc-nav);
		if(d-icpc.r < 0) x = arg(s.dir()) - arg(icpc-nav)  + asin((icpc.r-d) / icpc.r);
		if(x < -PI) x += 2*PI;
		if(x > PI)  x -= 2*PI;
		if(x < -EPS) r = max(r, x);
	}
	REP(i, n){
		const P q = g[i];
		R d = abs(q-nav);
		if(d > 2*icpc.r - EPS || d < EPS) continue;
		P med = (nav + q) * (R).5;
		R d2 = sqrt(max((R).0, icpc.r*icpc.r - d*d*(R).25));
		P p1 = med + unit(med - nav)*P(0, 1)*d2;
		P p2 = med + unit(med - nav)*P(0, -1)*d2;

		if(arg((p1 - nav)/(icpc-nav)) < -EPS) r = max(r, arg((p1 - nav)/(icpc-nav)));
		if(arg((p2 - nav)/(icpc-nav)) < -EPS) r = max(r, arg((p2 - nav)/(icpc-nav)));
	}
	return r;
}
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> icpc, n){
		g.resize(n);
		REP(i, n) cin >> g[i];
		R d = straight(P(1, 0));
		icpc += P(1, 0)*d;
		R ans = 0;
		G root;
		P prev = getNavigator();
		P start = icpc;
		while(1){
			P nav = getNavigator();
			if(sig(abs(prev-nav))){
				root.push_back(prev);
				root.push_back(icpc);
				ans += icpc.r * icpc.r * arg((nav-icpc)/(prev-icpc)) * .5;
			}
			if(!sig(abs(icpc-start)) && sig(root.area())) break;
			root.push_back(nav);
			prev = nav;
			auto t = getType(nav);
			if(t.second > 0){
				P picpc = icpc;
				prev += unit(t.first) * straight(t.first, t.second);
				icpc += unit(t.first) * straight(t.first, t.second);
				if(S(picpc, icpc).online(start) == TRUE && sig(root.area())) break;
			}else{
				(P &)icpc = nav + (icpc - nav)*polar((R)1., rot(nav, t.second));
				if(sig(abs(icpc-start)) && !sig(abs(start - nav) - icpc.r) && sig(root.area())) break;
			}
		}
		printf("%.10f\n", (double)(ans + root.area()));
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1316
final_rank: 1

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef long double R;
	const R INF = 1e10;
	R EPS = 1e-10;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	struct C : public P{
		C(){}
		C(const P& p, const R r):P(p), r(r){}
		R r;
		BOOL inside(const P& p)const { return less(norm(p-SELF), r*r);}
	};
	struct F : public C{
		R s, t;
		F(const C &c, R ss, R tt):C(c), s(ss), t(tt){
			if(PI < s) s -= 2*PI;
			if(PI < t) t -= 2*PI;
		}
		BOOL inside(const P& p)const {
			P v = p - SELF;
			if(!sig(norm(v))) return BORDER;
			R a = arg(v);
			if(t < s){
				if((!less(s, a) && !less(a, t)) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}else{
				if(!less(s, a) || !less(a, t) || !less(norm(v), r*r)) return FALSE;
				return less(s, a) | less(a, t) | less(norm(v), r*r);
			}
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
		BOOL contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(S(at(i), at((i+1)%size())).online(p)) return BORDER;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return !!sig(sum);
		}
		R area()const {
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
		P gp()const {
			P r(.0, .0);
			REP(i, size()){
				const S &s = edge(i);
				r += (s[0]+s[1])*outp(s[0], s[1]);
			}
			return r / (6*area());
		}
		G convex_hull(bool online = false) {
			if(size() < 2) return *this;
			sort(ALL(*this));
			G r;
			r.resize((int)size()*2);
			int k=0;
			for(int i=0;i<size();r[k++]=at(i++))
				while(k>1 && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			int t = k;
			for(int i=(int)size()-1;i>=0;r[k++]=at(i--))
				while(k>t && ccw(r[k-2], r[k-1], at(i)) < 1-online) k--;
			r.resize(k-1);
			return r;
		}
		G cut(const L &l)const {
			G g;
			REP(i, size()){
				const S &s = edge(i);
				if(ccw(l[0], l[1], s[0], 0) >= 0) g.push_back(s[0]);
				if(ccw(l[0], l[1], s[0], 0) * ccw(l[0], l[1], s[1], 0) < 0)
					g.push_back(crosspoint(s, l));
			}
			return g;
		}
		G Voronoi(const vector<P> &p, const int t)const {
			G g = *this;
			REP(i, p.size())if(i!=t){
				const P m = (p[t]+p[i])*(R)0.5;
				g = g.cut(L(m, m+(p[i]-p[t])*P(0, 1)));
			}
			return g;
		}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return (R)2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: テ・ツ??ゥツδィテ」ツ?ォテ・ツョツ古・ツ?ィテ」ツ?ォテ・ツ青ォテ」ツ?セテ」ツつ古」ツつ凝・ツ?エテ・ツ青?
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline BOOL intersect(const C &a, const C &b){
		return less((a.r-b.r)*(a.r-b.r), norm(a-b)) + less(norm(a-b), (a.r+b.r)*(a.r+b.r)) - 1;
	}

#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
	istream& operator>>(istream &is, L &l){l.resize(2);return is >> l[0] >> l[1];}
	istream& operator>>(istream &is, C &c){return is >> (P &)c >> c.r;}
	const R B = 500;
	const R Z = 30;
	ostream& operator<<(ostream &os, const C &c){return os << "circle("<<B+Z*(c.X)<<", "<<1000-B-Z*(c.Y)<<", "<<Z*(c.r)<<")";}
	ostream& operator<<(ostream &os, const P &p){return os << C(p, 2./Z);}
	ostream& operator<<(ostream &os, const S &s){return os << "line("<<B+Z*(s[0].X)<<", "<<1000-B-Z*(s[0].Y)<<", "<<B+Z*(s[1].X)<<", "<<1000-B-Z*(s[1].Y)<<")";}
	ostream& operator<<(ostream &os, const G &g){REP(i, g.size()) cout << g.edge(i) << endl;return os;}

}

int n;

C icpc;
G g;

pair<P, R> getType(const P &p){
	REP(i, n){
		const S s = g.edge(i);
		if(s.online(p) == TRUE) return mp(s.dir(), abs(s[1] - p));
	}
	REP(i, n){
		const P q = g[i];
		if(!sig(abs(q - p))){
			P tar = q + unit(g.edge(i).dir())*P(0, 1)*icpc.r;
			if(!sig(abs(icpc - tar))) return mp(g.edge(i).dir(), abs(g.edge(i).dir()));
			return mp(tar, arg((tar - p)/(icpc - p)));
		}
	}
	assert(false);
}

P getNavigator(){
	vector<pair<R, P>> isc;
	REP(i, n){
		const S s = g.edge(i);
		P q = proj(icpc, s);
		if(s.online(q) == TRUE && !sig(abs(q - icpc) - icpc.r))
			isc.emplace_back(arg(q - icpc), q);
	}
	REP(i, n){
		const P q = g[i];
		if(!sig(abs(q - icpc) - icpc.r)) isc.emplace_back(arg(q - icpc), q);
	}
	sort(ALL(isc));
	pair<R, P> pp(.0, P(0, 0));
	REP(i, isc.size()){
		const auto cur = isc[i];
		const auto nxt = isc[(i+1)%isc.size()];
		R nxtarg = i+1 == isc.size() ? nxt.first + 2*PI : nxt.first;
		pp = max(pp, mp(nxtarg - cur.first, cur.second));
	}
	
	return pp.second;
}

R straight(P dir, R d = INF){
	REP(i, n){
		const S s = g.edge(i);
		if(sig(arg(dir*P(0, 1)/s.dir())) || inp(proj(icpc, s) - icpc, dir) < EPS || s.online(proj(icpc, s)) != TRUE) continue;
		d = min(d, abs(proj(icpc, s) - icpc) - icpc.r);
	}
	REP(i, n){
		const P q = g[i];
		R r = abs(q - proj(q, L(icpc, icpc+dir)));
		if(r + EPS > icpc.r || inp(q - icpc, dir) < EPS) continue;
		d = min(d, abs(proj(q, L(icpc, icpc+dir)) - icpc) - sqrt(icpc.r*icpc.r-r*r));
	}
	return d;
}

R rot(P nav, R r){
	REP(i, n){
		const S s = g.edge(i);
		if(abs(proj(nav, s) - nav) < EPS) continue;
		R t = arg((proj(nav, s) - nav)/(icpc - nav));
		if(t > 0 && t < PI) continue;
		R d = abs(proj(nav, s) - nav);
		if(d > 2*icpc.r - EPS) continue;
		R x = arg(s.dir()) - asin((d-icpc.r) / icpc.r) - arg(icpc-nav);
		if(d-icpc.r < 0) x = arg(s.dir()) - arg(icpc-nav)  + asin((icpc.r-d) / icpc.r);
		if(x < -PI) x += 2*PI;
		if(x > PI)  x -= 2*PI;
		if(x < -EPS) r = max(r, x);
	}
	REP(i, n){
		const P q = g[i];
		R d = abs(q-nav);
		if(d > 2*icpc.r - EPS || d < EPS) continue;
		P med = (nav + q) * (R).5;
		R d2 = sqrt(max((R).0, icpc.r*icpc.r - d*d*(R).25));
		P p1 = med + unit(med - nav)*P(0, 1)*d2;
		P p2 = med + unit(med - nav)*P(0, -1)*d2;

		if(arg((p1 - nav)/(icpc-nav)) < -EPS) r = max(r, arg((p1 - nav)/(icpc-nav)));
		if(arg((p2 - nav)/(icpc-nav)) < -EPS) r = max(r, arg((p2 - nav)/(icpc-nav)));
	}
	return r;
}
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> icpc, n){
		g.resize(n);
		REP(i, n) cin >> g[i];
		R d = straight(P(1, 0));
		icpc += P(1, 0)*d;
		R ans = 0;
		G root;
		P prev = getNavigator();
		P start = icpc;
		while(1){
			P nav = getNavigator();
			if(sig(abs(prev-nav))){
				root.push_back(prev);
				root.push_back(icpc);
				ans += icpc.r * icpc.r * arg((nav-icpc)/(prev-icpc)) * .5;
			}
			if(!sig(abs(icpc-start)) && sig(root.area())) break;
			root.push_back(nav);
			prev = nav;
			auto t = getType(nav);
			if(t.second > 0){
				P picpc = icpc;
				prev += unit(t.first) * straight(t.first, t.second);
				icpc += unit(t.first) * straight(t.first, t.second);
				if(S(picpc, icpc).online(start) == TRUE && sig(root.area())) break;
			}else{
				(P &)icpc = nav + (icpc - nav)*polar((R)1., rot(nav, t.second));
				if(sig(abs(icpc-start)) && !sig(abs(start - nav) - icpc.r) && sig(root.area())) break;
			}
		}
		printf("%.10f\n", (double)(ans + root.area()));
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1320
final_rank: 2

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#include <iomanip>
#include <fstream>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<b?(a=b,1):0)
#define chmin(a,b) (a>b?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
#define double long double
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;

typedef complex<double> P;
P pIN() { double x,y; cin >> x >> y; return P(x,y); }
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() { resize(2); }
};
typedef vector<P> G;
int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

bool parallel(const L &l, const L &m) {
  return abs(cross(l[1]-l[0],m[1]-m[0])) < EPS;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}

bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
double distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
P nearestSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return r;
  double a1 = abs(s[0] - p);
  double a2 = abs(s[1] - p);
  if (a1 < a2) return s[0];
  else return s[1];
}
double distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

// テ」ツδ凖」ツつッテ」ツδ暗」ツδォテ」ツ?ョテ・ツ崢榲ィツサツ「
P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}
// テ・ツ篠淌ァツつケテ・ツ堕ィテ」ツつ甘」ツ?ョテァツ崢エテァツキツ堙」ツ?ョテ・ツ崢榲ィツサツ「
L rotate(const L &l, double ang) {
  return L(rotate(l[0], ang),rotate(l[1], ang));
}
bool EQ(double a, double b) {
  return abs(a-b) < EPS;
}

vector<P> circleCentersFromTangent(L l1, L l2, double r) {
  vector<P> res;
  if (parallel(l1,l2)) return res;
  P cp = crosspoint(l1,l2);
  l1[0]-=cp; l1[1]-=cp;
  l2[0]-=cp; l2[1]-=cp;
  double ang = arg(l1[1]-l1[0]);
  l2 = rotate(l2, -ang+PI/2);
  double A = (l2[1]-l2[0]).imag() / (l2[1]-l2[0]).real();
  double sq = sqrt(A*A+1);
  res.push_back(P(r, r*(sq+A)));
  res.push_back(P(-r, r*(sq-A)));
  res.push_back(P(r, r*(-sq+A)));
  res.push_back(P(-r, r*(-sq-A)));  
  FOR(it, res) *it = rotate(*it,+ang-PI/2) + cp;
  return res;
}

vector<P> circleCentersFromPoints(const P &p1, const P &p2, double r) {
  vector<P> res;
  double len = abs(p1-p2);
  if (len < EPS) return res;
  if (len/2 >= r-EPS) return res;
  P v = p2-p1;
  v /= len;
  v *= sqrt(r*r-(len/2)*(len/2));
  P p = (p1+p2)*P(0.5,0);
  res.push_back(p+v*P(0,1));
  res.push_back(p+v*P(0,-1));
  return res;
}

void solve(vector<P> &v, double A, double B, double C, double x) {
  double D = B*B-4*A*C;
  if (D<0) return;
  double sqD = sqrt(max(D,(double)0.0));
  v.push_back(P(x, (-B+sqD)/(2*A)));
  v.push_back(P(x, (-B-sqD)/(2*A)));
}

vector<P> circleCentersFromTangentAndPoint(L l, P p, double r) {
  vector<P> res;
  P cp = l[0];
  l[1] -= cp; l[0] -= cp;
  p -= cp;
  double ang = arg(l[1]-l[0]);
  p = rotate(p, -ang+PI/2);
  double a = p.real();
  double b = p.imag();
  double A = 1;
  double B = -2*b;
  solve(res,A,B,b*b-2*r*a+a*a, r);
  solve(res,A,B,b*b+2*r*a+a*a, -r);
  FOR(it, res) *it = rotate(*it,+ang-PI/2) + cp;
  return res;
}

vector<P> circleCentersFromSegments(L s1, L s2, double r) {
  vector<P> tmp = circleCentersFromTangent(s1,s2,r);
  vector<P> res;
  FOR(it, tmp) {
    if (intersectSP(s1,projection(s1,*it)) &&
        intersectSP(s2,projection(s2,*it))) {
      res.push_back(*it);
    }
  }
  REP(i,2) {
    REP(j,2) {
      vector<P> tmp = circleCentersFromPoints(s1[i],s2[j],r);
      FOR(it, tmp) {
        res.push_back(*it);
      }
    }
  }
  REP(i,2) {
    vector<P> tmp1 = circleCentersFromTangentAndPoint(s1, s2[i], r);
    FOR(it, tmp1) {
      if (intersectSP(s1, projection(s1,*it))) {
        res.push_back(*it);
      }
    }
    vector<P> tmp2 = circleCentersFromTangentAndPoint(s2, s1[i], r);
    FOR(it, tmp2) {
      if (intersectSP(s2, projection(s2,*it))) {
        res.push_back(*it);
      }
    }
  }
  return res;
}

vector<P> endpointCircles(const L &l, double r) {
  P v = l[1]-l[0];
  v /= abs(v);
  v *= r;
  vector<P> res;
  res.push_back(l[0] + v * P(0,1));
  res.push_back(l[0] + v * P(0,-1));
  res.push_back(l[1] + v * P(0,1));
  res.push_back(l[1] + v * P(0,-1));
  return res;
}

double scale = 2;
// P diff(-90, 30);
P diff(300, 300);
void outputLine(L l) {
  return;
  l[0] = l[0]*P(scale,0)+diff;
  l[1] = l[1]*P(scale,0)+diff;
  printf("line(%Lf,%Lf,%Lf,%Lf);\n",l[0].real(),l[0].imag(),l[1].real(),l[1].imag());  
}
void outputCircle(C c) {
  return;
  c.p = c.p*P(scale,0) + diff;
  c.r *= scale;
  printf("circle(%Lf,%Lf,%Lf);\n", c.p.real(), c.p.imag(), c.r);
}
inline L line(const G &g, int i) {
  return L(g[i], g[(i+1)%g.size()]);
}

bool isVisible(const P &p1, const P &p2, const G &g, double r) {
  L seg(p1,p2);
  REP(i,g.size()) {
    if (distanceSS(seg,line(g,i)) <= r-EPS) return 0;
  }
  return 1;
}

double angle(const P &a, const P &b) {        // テ」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツ?」ツ?凝」ツつ嘉」ツ?ソテ」ツ?淌」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツづ」ツ?ョティツァツ津・ツコツヲテ」ツ?ョティツィツ暗ァツョツ夕0,2pi)
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
double angle2(const P &a, const P &b) { // テ」ツδ凖」ツつッテ」ツδ暗」ツδォaテ」ツ?ィテ」ツδ凖」ツつッテ」ツδ暗」ツδォbテ」ツ?ョテゥツ鳴禿」ツ?ョティツァツ津・ツコツヲ
  return min(angle(a,b), angle(b,a));
}

bool collide(const P &cent, const P &p1, const P &p2, const L seg, double r) {
  vector<P> v(2);
  v[0] = seg[0], v[1] = seg[1];
  if (intersectLS(L(cent,p1),seg)) {
    P cp = crosspoint(L(cent,p1),seg);
    v.push_back(cp);
  }
  if (intersectLS(L(cent,p2),seg)) {
    v.push_back(crosspoint(L(cent,p2),seg));
  }
  sort(ALL(v));
  REP(i,v.size()-1) {
    if (abs(v[i]-v[i+1])<EPS) continue;
    P p = (v[i]+v[i+1])*P(0.5,0);
    if (angle(p1-cent, p-cent) <= angle(p1-cent, p2-cent)) {
      if (distanceSP(L(v[i],v[i+1]), cent) <= r) {
        // cout << "NG" << " " << distanceSP(L(v[i],v[i+1]), cent) << endl;
        // cout << p << " " << p1 << " " << angle(p1-cent, p-cent) << endl;
        // cout << v[i] << " " << v[i+1] << " " << cent << endl;
        return 1;
      }
    }
  }
  return 0;
}

bool canRound2(const P &cent, const P &p1, const P &p2, const G &g, double r) {
  REP(i,g.size()) {
    if (collide(cent,p1,p2,line(g,i),r)) return 0;
  }
  return 1;
}

bool canRound(const P &p1, const P &p2, const G &g, double r, const vector<P> &ps) {
  REP(i,g.size()) {
    if (EQ(abs(p1-g[i]), r) &&
        EQ(abs(p2-g[i]), r)) {
      
      P a = g[i]+(p1-g[i])*P(2,0);
      P b = g[i]+(p2-g[i])*P(2,0);
      if (canRound2(g[i],b,a,g,2*r)) swap(a,b);
      if (canRound2(g[i],a,b,g,2*r)) {
        FOR(it, ps) {
          if (abs(p1-*it)<EPS || abs(p2-*it)<EPS) continue;
          if (EQ(abs(*it-g[i]), r)) {
            if (angle(a-g[i],*it-g[i]) < angle(a-g[i],b-g[i])) return 0;
          }
        }
        return 1;
      }
    }
  }
  return 0;
}

// テァツつケ-テ・ツ、ツ堙ィツァツ津・ツスツ「テ・ツ個?・ツ青ォテゥツ鳴「テ、ツソツ?
int contains(const G &g, const P &p) {
  bool in = 0;
  REP(i,g.size()) {
    P a = g[i] - p;
    P b = g[(i+1)%g.size()] - p;
    if (imag(a) > imag(b)) swap(a,b);
    if (imag(a) <= 0 && 0 < imag(b))
      if (cross(a,b) < 0) in = !in;
    if (abs(cross(a,b))< EPS && dot(a,b) <= EPS) return 0;
  }
  return in?1:-1;
}

bool check(const P &p, const G &g, double r) {
  if (contains(g,p) != 1) return 0;
  REP(i,g.size()) {
    if (distanceSP(line(g,i), p) <= r-EPS) return 0;
  }
  return 1;
}

G getCycle(const vector<vector<int> > &g, const vector<P> &ps, int a, int b) {
  vector<int> flag(g.size(), -1);
  G tmpres;
  int pre = a;
  int cur = b;
  tmpres.push_back(ps[a]);
  flag[a] = 0;
  int cnt = 1;
  while(1) {
    if (flag[cur] >= 0) {
      G res;
      for (int i=flag[cur]; i<tmpres.size(); ++i) {
        res.push_back(tmpres[i]);
      }
      return res;
    }
    flag[cur] = cnt++;
    tmpres.push_back(ps[cur]);
    P vec = ps[pre]-ps[cur];
    if (cnt == 2) {
      vec = ps[cur]-ps[pre];
    }
    double minang = INF;
    int dst = -1;
    FOR(it, g[cur]) {
      double tang = angle(vec, ps[*it]-ps[cur]);
      if (tang > EPS && chmin(minang, tang)) {
        dst = *it;
      } else if (EQ(minang,tang) && abs(ps[*it]-ps[cur])<abs(ps[dst]-ps[cur])) {
        dst = *it;
      }
      // cout << ps[cur] << " " << ps[*it] << endl;
    }
    // cout << dst << " " << minang << " " << ps[dst] << endl;
    if (dst == -1) return G();
    pre = cur;
    cur = dst;
  }
}
double area(const G& g) {
  double A = 0;
  for (int i = 0; i < g.size(); ++i) {
    A += cross(g[i], g[(i+1)%g.size()]);
  }
  return abs(A/2);
}

P O;
int quadrant(const P &a) {      // テヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?ソテ」ツ??・ツ債甘ヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?セテ」ツ?ェテ」ツ??
  if (a.real() > 0 && a.imag() >= 0) return 0;
  if (a.real() <= 0 && a.imag() > 0) return 1;
  if (a.real() < 0 && a.imag() <= 0) return 2;
  return 3;
}
bool cmpAngle(const P &a, const P&b) { // テ」ツδュテ」ツδ静」ツつケテ」ツδ暗」ツ?ェティツァツ津・ツコツヲテヲツッツ氾ィツシツ?
  int q1 = quadrant(a-O);
  int q2 = quadrant(b-O);
  if (q1 != q2) return q1 < q2;
  return cross(a-O,b-O)>0;
}


map<pair<P,P>, bool> mp;

double cornerArea(const P &p, const G &g, double r) {
  vector<P> ps;
  REP(i,g.size()) {
    L s = line(g,i);
    // P p1 = 
    // // L s(g[i],g[(i+1)%g.size()]);
    //L s(P(0,0),P(100,100));
    if (EQ(distanceSP(s,p), r)) {
      P q = nearestSP(s,p);
      // P p(0,0);
      bool f = 1;
      REP(j,ps.size()) {
        if (abs(ps[j]-q) < EPS) f = 0;
      }
      if (f) {
        ps.push_back(q);
      }
    }
  }
  O = p;
  sort(ALL(ps), cmpAngle);
  if (ps.size() <= 1) return 0;
  int cur = 0;
  double res = 0;
  G tmp;
  // cout << p << endl;
  for (int i=0; ; ++i) {
    if (cur == ps.size()+1) {
      // cout << res << endl;
      return res;
    }
    int ii = i%g.size();
    L s = line(g,ii);
    tmp.push_back(g[ii]);
    P cp = ps[cur%ps.size()];    
    if (intersectSP(s,cp)) {
      if (cur && angle(ps[cur-1]-p,cp-p) <= PI) {
        tmp.push_back(cp);
        tmp.push_back(p);
        // cout << p << " " << ps[cur-1] << " " << cp << " " << cur << " " << ps[cur%ps.size()] << endl;
        // FOR(it, tmp) cout << *it << " "; cout << endl;
        // cout << tmp.size() << endl;
        // REP(k,tmp.size()){
        //   outputLine(line(tmp,k));
        // }
        if (mp.count(make_pair(ps[cur-1],ps[cur%ps.size()])) == 0) {
          mp[make_pair(ps[cur-1],ps[cur&ps.size()])] = 1;
          res += area(tmp);
          res -= r*r*angle(ps[cur-1]-p,cp-p)/2;
        }
      }
      tmp.clear();
      tmp.push_back(cp);
      cur++;
    }
  }
}


int main() {
  outputLine(L(P(-1000,0),P(1000,0)));
  outputLine(L(P(-0,-1000),P(0,1000)));
  // L l1(P(100, 200), P(1000,500));
  // L l2(P(100, 300), P(700,300));
  // // L l1(P(0, 0), P(300,300));
  // // L l2(P(0, 0), P(700,300));
  
  // double r = 30;
  // vector<P> res = circleCentersFromTangent(l1,l2,r);
  // outputLine(l1);
  // outputLine(l2);
  // FOR(it, res) {
  //   outputCircle(C(*it, r));
  // }
  int n;
  double x,y,r;
  while(cin>>n>>x>>y>>r, n) {
    mp.clear();
    G poly;
    REP(i,n) poly.push_back(pIN());

    // move right(?)
    double minDist = INF;
    P right;
    P start(x,y);
    REP(i,n) {
      L l(start-P(0,r), P(x+1000,y-r));
      vector<P> tmp = circleCentersFromSegments(l, line(poly,i), r);
      FOR(it, tmp) {
        if (check(*it, poly, r)) {
          double dis = abs(*it-start);
          if (chmin(minDist, dis)) {
            right = *it;
          }
        }
      }
    }
    
    vector<P> ps;
    ps.push_back(start);
    ps.push_back(right);
    
    REP(i,n) {
      vector<P> tmp = endpointCircles(line(poly,i),r);
      FOR(it, tmp) {
        if (check(*it, poly, r))
          ps.push_back(*it);
      }
      REP(j,i) {
        vector<P> ret = circleCentersFromSegments(line(poly,i),line(poly,j),r);
        FOR(it, ret) {
          if (check(*it, poly, r)) {
            ps.push_back(*it);
          }
        }
      }
    }
    REP(i,n) {
      outputLine(line(poly,i));
    }
    vector<P> tmpps;
    REP(i,ps.size()) {
      bool ok = 1;
      REP(j,tmpps.size()) {
        if (abs(tmpps[j]-ps[i])<EPS) {
          ok = 0;
          break;
        }
      }
      if (ok)
        tmpps.push_back(ps[i]);      
    }
    ps = tmpps;
    // sort(ALL(ps));
    // ps.erase(unique(ALL(ps)), ps.end());

    int N = ps.size();

    int startID = -1;
    int rightID = -1;
    REP(i,N) {
      // cout << ps[i] << endl;
      if (EQ(abs(start-ps[i]),0)) startID = i;
      if (EQ(abs(right-ps[i]),0)) rightID = i;
    }
    
    vector<vector<int> > g(N);
    REP(i,N) {
      if (i != startID && i != rightID)
        outputCircle(C(ps[i],r));
      REP(j,i) {
        if (isVisible(ps[i], ps[j], poly, r) || canRound(ps[i], ps[j], poly, r, ps)) {          
          g[i].push_back(j);
          g[j].push_back(i);
          // outputLine(L(ps[i],ps[j]));
        }
      }
    }

    
    G cycle = getCycle(g, ps, startID, rightID);
    double ans = area(poly);
    REP(i,cycle.size()) {
      outputLine(line(cycle,i));
      L l1 = line(cycle,i);
      L l2 = line(cycle,(i+1)%cycle.size());
      // if (ccw(l1[0],l1[1],l2[1]) == 1) {
        ans -= cornerArea(l1[1],poly,r);
        // }
    }
    printf("%.10Lf\n", ans);
  }
}
accuracy: 1
time_ms: 60
memory_kb: 1332
final_rank: 5

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#include <iomanip>
#include <fstream>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<b?(a=b,1):0)
#define chmin(a,b) (a>b?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
#define double long double
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;

typedef complex<double> P;
P pIN() { double x,y; cin >> x >> y; return P(x,y); }
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() { resize(2); }
};
typedef vector<P> G;
int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

bool parallel(const L &l, const L &m) {
  return abs(cross(l[1]-l[0],m[1]-m[0])) < EPS;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}

bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
double distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
P nearestSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return r;
  double a1 = abs(s[0] - p);
  double a2 = abs(s[1] - p);
  if (a1 < a2) return s[0];
  else return s[1];
}
double distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

// テ」ツδ凖」ツつッテ」ツδ暗」ツδォテ」ツ?ョテ・ツ崢榲ィツサツ「
P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}
// テ・ツ篠淌ァツつケテ・ツ堕ィテ」ツつ甘」ツ?ョテァツ崢エテァツキツ堙」ツ?ョテ・ツ崢榲ィツサツ「
L rotate(const L &l, double ang) {
  return L(rotate(l[0], ang),rotate(l[1], ang));
}
bool EQ(double a, double b) {
  return abs(a-b) < EPS;
}

vector<P> circleCentersFromTangent(L l1, L l2, double r) {
  vector<P> res;
  if (parallel(l1,l2)) return res;
  P cp = crosspoint(l1,l2);
  l1[0]-=cp; l1[1]-=cp;
  l2[0]-=cp; l2[1]-=cp;
  double ang = arg(l1[1]-l1[0]);
  l2 = rotate(l2, -ang+PI/2);
  double A = (l2[1]-l2[0]).imag() / (l2[1]-l2[0]).real();
  double sq = sqrt(A*A+1);
  res.push_back(P(r, r*(sq+A)));
  res.push_back(P(-r, r*(sq-A)));
  res.push_back(P(r, r*(-sq+A)));
  res.push_back(P(-r, r*(-sq-A)));  
  FOR(it, res) *it = rotate(*it,+ang-PI/2) + cp;
  return res;
}

vector<P> circleCentersFromPoints(const P &p1, const P &p2, double r) {
  vector<P> res;
  double len = abs(p1-p2);
  if (len < EPS) return res;
  if (len/2 >= r-EPS) return res;
  P v = p2-p1;
  v /= len;
  v *= sqrt(r*r-(len/2)*(len/2));
  P p = (p1+p2)*P(0.5,0);
  res.push_back(p+v*P(0,1));
  res.push_back(p+v*P(0,-1));
  return res;
}

void solve(vector<P> &v, double A, double B, double C, double x) {
  double D = B*B-4*A*C;
  if (D<0) return;
  double sqD = sqrt(max(D,(double)0.0));
  v.push_back(P(x, (-B+sqD)/(2*A)));
  v.push_back(P(x, (-B-sqD)/(2*A)));
}

vector<P> circleCentersFromTangentAndPoint(L l, P p, double r) {
  vector<P> res;
  P cp = l[0];
  l[1] -= cp; l[0] -= cp;
  p -= cp;
  double ang = arg(l[1]-l[0]);
  p = rotate(p, -ang+PI/2);
  double a = p.real();
  double b = p.imag();
  double A = 1;
  double B = -2*b;
  solve(res,A,B,b*b-2*r*a+a*a, r);
  solve(res,A,B,b*b+2*r*a+a*a, -r);
  FOR(it, res) *it = rotate(*it,+ang-PI/2) + cp;
  return res;
}

vector<P> circleCentersFromSegments(L s1, L s2, double r) {
  vector<P> tmp = circleCentersFromTangent(s1,s2,r);
  vector<P> res;
  FOR(it, tmp) {
    if (intersectSP(s1,projection(s1,*it)) &&
        intersectSP(s2,projection(s2,*it))) {
      res.push_back(*it);
    }
  }
  REP(i,2) {
    REP(j,2) {
      vector<P> tmp = circleCentersFromPoints(s1[i],s2[j],r);
      FOR(it, tmp) {
        res.push_back(*it);
      }
    }
  }
  REP(i,2) {
    vector<P> tmp1 = circleCentersFromTangentAndPoint(s1, s2[i], r);
    FOR(it, tmp1) {
      if (intersectSP(s1, projection(s1,*it))) {
        res.push_back(*it);
      }
    }
    vector<P> tmp2 = circleCentersFromTangentAndPoint(s2, s1[i], r);
    FOR(it, tmp2) {
      if (intersectSP(s2, projection(s2,*it))) {
        res.push_back(*it);
      }
    }
  }
  return res;
}

vector<P> endpointCircles(const L &l, double r) {
  P v = l[1]-l[0];
  v /= abs(v);
  v *= r;
  vector<P> res;
  res.push_back(l[0] + v * P(0,1));
  res.push_back(l[0] + v * P(0,-1));
  res.push_back(l[1] + v * P(0,1));
  res.push_back(l[1] + v * P(0,-1));
  return res;
}

double scale = 10;
void outputLine(L l) {
  return;
  l[0] = l[0]*P(scale,0)+P(150,350);
  l[1] = l[1]*P(scale,0)+P(150,350);
  printf("line(%Lf,%Lf,%Lf,%Lf);\n",l[0].real(),l[0].imag(),l[1].real(),l[1].imag());  
}
void outputCircle(C c) {
  return;
  c.p = c.p*P(scale,0) + P(150,350);
  c.r *= scale;
  printf("circle(%Lf,%Lf,%Lf);\n", c.p.real(), c.p.imag(), c.r);
}
inline L line(const G &g, int i) {
  return L(g[i], g[(i+1)%g.size()]);
}

bool isVisible(const P &p1, const P &p2, const G &g, double r) {
  L seg(p1,p2);
  REP(i,g.size()) {
    if (distanceSS(seg,line(g,i)) <= r-EPS) return 0;
  }
  return 1;
}

double angle(const P &a, const P &b) {        // テ」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツ?」ツ?凝」ツつ嘉」ツ?ソテ」ツ?淌」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツづ」ツ?ョティツァツ津・ツコツヲテ」ツ?ョティツィツ暗ァツョツ夕0,2pi)
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
double angle2(const P &a, const P &b) { // テ」ツδ凖」ツつッテ」ツδ暗」ツδォaテ」ツ?ィテ」ツδ凖」ツつッテ」ツδ暗」ツδォbテ」ツ?ョテゥツ鳴禿」ツ?ョティツァツ津・ツコツヲ
  return min(angle(a,b), angle(b,a));
}

bool collide(const P &cent, const P &p1, const P &p2, const L seg, double r) {
  vector<P> v(2);
  v[0] = seg[0], v[1] = seg[1];
  if (intersectLS(L(cent,p1),seg)) {
    P cp = crosspoint(L(cent,p1),seg);
    v.push_back(cp);
  }
  if (intersectLS(L(cent,p2),seg)) {
    v.push_back(crosspoint(L(cent,p2),seg));
  }
  sort(ALL(v));
  REP(i,v.size()-1) {
    if (abs(v[i]-v[i+1])<EPS) continue;
    P p = (v[i]+v[i+1])*P(0.5,0);
    if (angle(p1-cent, p-cent) <= angle(p1-cent, p2-cent)) {
      if (distanceSP(L(v[i],v[i+1]), cent) <= r) {
        // cout << "NG" << " " << distanceSP(L(v[i],v[i+1]), cent) << endl;
        // cout << p << " " << p1 << " " << angle(p1-cent, p-cent) << endl;
        // cout << v[i] << " " << v[i+1] << " " << cent << endl;
        return 1;
      }
    }
  }
  return 0;
}

bool canRound2(const P &cent, const P &p1, const P &p2, const G &g, double r) {
  REP(i,g.size()) {
    if (collide(cent,p1,p2,line(g,i),r)) return 0;
  }
  return 1;
}

bool canRound(const P &p1, const P &p2, const G &g, double r, const vector<P> &ps) {
  REP(i,g.size()) {
    if (EQ(abs(p1-g[i]), r) &&
        EQ(abs(p2-g[i]), r)) {
      
      P a = g[i]+(p1-g[i])*P(2,0);
      P b = g[i]+(p2-g[i])*P(2,0);
      if (canRound2(g[i],b,a,g,2*r)) swap(a,b);
      if (canRound2(g[i],a,b,g,2*r)) {
        FOR(it, ps) {
          if (abs(p1-*it)<EPS || abs(p2-*it)<EPS) continue;
          if (EQ(abs(*it-g[i]), r)) {
            if (angle(a-g[i],*it-g[i]) < angle(a-g[i],b-g[i])) return 0;
          }
        }
        return 1;
      }
    }
  }
  return 0;
}

// テァツつケ-テ・ツ、ツ堙ィツァツ津・ツスツ「テ・ツ個?・ツ青ォテゥツ鳴「テ、ツソツ?
int contains(const G &g, const P &p) {
  bool in = 0;
  REP(i,g.size()) {
    P a = g[i] - p;
    P b = g[(i+1)%g.size()] - p;
    if (imag(a) > imag(b)) swap(a,b);
    if (imag(a) <= 0 && 0 < imag(b))
      if (cross(a,b) < 0) in = !in;
    if (abs(cross(a,b))< EPS && dot(a,b) <= EPS) return 0;
  }
  return in?1:-1;
}

bool check(const P &p, const G &g, double r) {
  if (contains(g,p) != 1) return 0;
  REP(i,g.size()) {
    if (distanceSP(line(g,i), p) <= r-EPS) return 0;
  }
  return 1;
}

G getCycle(const vector<vector<int> > &g, const vector<P> &ps, int a, int b) {
  vector<int> flag(g.size(), -1);
  G tmpres;
  int pre = a;
  int cur = b;
  tmpres.push_back(ps[a]);
  flag[a] = 0;
  int cnt = 1;
  while(1) {
    if (flag[cur] >= 0) {
      G res;
      for (int i=flag[cur]; i<tmpres.size(); ++i) {
        res.push_back(tmpres[i]);
      }
      return res;
    }
    flag[cur] = cnt++;
    tmpres.push_back(ps[cur]);
    P vec = ps[pre]-ps[cur];
    if (cnt == 2) {
      vec = ps[cur]-ps[pre];
    }
    double minang = INF;
    int dst = -1;
    FOR(it, g[cur]) {
      double tang = angle(vec, ps[*it]-ps[cur]);
      if (tang > EPS && chmin(minang, tang)) {
        dst = *it;
      } else if (EQ(minang,tang) && abs(ps[*it]-ps[cur])<abs(ps[dst]-ps[cur])) {
        dst = *it;
      }
      // cout << ps[cur] << " " << ps[*it] << endl;
    }
    // cout << dst << " " << minang << " " << ps[dst] << endl;
    if (dst == -1) return G();
    pre = cur;
    cur = dst;
  }
}
double area(const G& g) {
  double A = 0;
  for (int i = 0; i < g.size(); ++i) {
    A += cross(g[i], g[(i+1)%g.size()]);
  }
  return abs(A/2);
}

P O;
int quadrant(const P &a) {      // テヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?ソテ」ツ??・ツ債甘ヲツ卍づィツィツ暗・ツ崢榲」ツつ甘・ツ?エテ」ツ?ッテ・ツ青ォテ」ツ?セテ」ツ?ェテ」ツ??
  if (a.real() > 0 && a.imag() >= 0) return 0;
  if (a.real() <= 0 && a.imag() > 0) return 1;
  if (a.real() < 0 && a.imag() <= 0) return 2;
  return 3;
}
bool cmpAngle(const P &a, const P&b) { // テ」ツδュテ」ツδ静」ツつケテ」ツδ暗」ツ?ェティツァツ津・ツコツヲテヲツッツ氾ィツシツ?
  int q1 = quadrant(a-O);
  int q2 = quadrant(b-O);
  if (q1 != q2) return q1 < q2;
  return cross(a-O,b-O)>0;
}


map<pair<P,P>, bool> mp;

double cornerArea(const P &p, const G &g, double r) {
  vector<P> ps;
  REP(i,g.size()) {
    L s = line(g,i);
    // P p1 = 
    // // L s(g[i],g[(i+1)%g.size()]);
    //L s(P(0,0),P(100,100));
    if (EQ(distanceSP(s,p), r)) {
      P q = nearestSP(s,p);
      // P p(0,0);
      bool f = 1;
      REP(j,ps.size()) {
        if (abs(ps[j]-q) < EPS) f = 0;
      }
      if (f) {
        ps.push_back(q);
      }
    }
  }
  O = p;
  sort(ALL(ps), cmpAngle);
  if (ps.size() <= 1) return 0;
  int cur = 0;
  double res = 0;
  G tmp;
  // cout << p << endl;
  for (int i=0; ; ++i) {
    if (cur == ps.size()+1) {
      // cout << res << endl;
      return res;
    }
    int ii = i%g.size();
    L s = line(g,ii);
    tmp.push_back(g[ii]);
    P cp = ps[cur%ps.size()];    
    if (intersectSP(s,cp)) {
      if (cur && angle(ps[cur-1]-p,cp-p) <= PI) {
        tmp.push_back(cp);
        tmp.push_back(p);
        // cout << p << " " << ps[cur-1] << " " << cp << " " << cur << " " << ps[cur%ps.size()] << endl;
        // FOR(it, tmp) cout << *it << " "; cout << endl;
        // cout << tmp.size() << endl;
        // REP(k,tmp.size()){
        //   outputLine(line(tmp,k));
        // }
        if (mp.count(make_pair(ps[cur-1],ps[cur%ps.size()])) == 0) {
          mp[make_pair(ps[cur-1],ps[cur&ps.size()])] = 1;
          res += area(tmp);
          res -= r*r*angle(ps[cur-1]-p,cp-p)/2;
        }
      }
      tmp.clear();
      tmp.push_back(cp);
      cur++;
    }
  }
}


int main() {
  outputLine(L(P(-1000,0),P(1000,0)));
  outputLine(L(P(-0,-1000),P(0,1000)));
  // L l1(P(100, 200), P(1000,500));
  // L l2(P(100, 300), P(700,300));
  // // L l1(P(0, 0), P(300,300));
  // // L l2(P(0, 0), P(700,300));
  
  // double r = 30;
  // vector<P> res = circleCentersFromTangent(l1,l2,r);
  // outputLine(l1);
  // outputLine(l2);
  // FOR(it, res) {
  //   outputCircle(C(*it, r));
  // }
  int n;
  double x,y,r;
  while(cin>>n>>x>>y>>r, n) {
    mp.clear();
    G poly;
    REP(i,n) poly.push_back(pIN());

    // move right(?)
    double minDist = INF;
    P right;
    P start(x,y);
    REP(i,n) {
      L l(start-P(0,r), P(x+1000,y-r));
      vector<P> tmp = circleCentersFromSegments(l, line(poly,i), r);
      FOR(it, tmp) {
        if (check(*it, poly, r)) {
          double dis = abs(*it-start);
          if (chmin(minDist, dis)) {
            right = *it;
          }
        }
      }
    }
    
    vector<P> ps;
    ps.push_back(start);
    ps.push_back(right);
    
    REP(i,n) {
      vector<P> tmp = endpointCircles(line(poly,i),r);
      FOR(it, tmp) {
        if (check(*it, poly, r))
          ps.push_back(*it);
      }
      REP(j,i) {
        vector<P> ret = circleCentersFromSegments(line(poly,i),line(poly,j),r);
        FOR(it, ret) {
          if (check(*it, poly, r)) {
            ps.push_back(*it);
          }
        }
      }
    }
    REP(i,n) {
      outputLine(line(poly,i));
    }
    vector<P> tmpps;
    REP(i,ps.size()) {
      bool ok = 1;
      REP(j,tmpps.size()) {
        if (abs(tmpps[j]-ps[i])<EPS) {
          ok = 0;
          break;
        }
      }
      if (ok)
        tmpps.push_back(ps[i]);      
    }
    ps = tmpps;
    // sort(ALL(ps));
    // ps.erase(unique(ALL(ps)), ps.end());

    int N = ps.size();

    int startID = -1;
    int rightID = -1;
    REP(i,N) {
      // cout << ps[i] << endl;
      if (EQ(abs(start-ps[i]),0)) startID = i;
      if (EQ(abs(right-ps[i]),0)) rightID = i;
    }
    
    vector<vector<int> > g(N);
    REP(i,N) {
      if (i != startID && i != rightID)
        outputCircle(C(ps[i],r));
      REP(j,i) {
        if (isVisible(ps[i], ps[j], poly, r) || canRound(ps[i], ps[j], poly, r, ps)) {          
          g[i].push_back(j);
          g[j].push_back(i);
          // outputLine(L(ps[i],ps[j]));
        }
      }
    }

    
    G cycle = getCycle(g, ps, startID, rightID);
    double ans = area(poly);
    REP(i,cycle.size()) {
      outputLine(line(cycle,i));
      L l1 = line(cycle,i);
      L l2 = line(cycle,(i+1)%cycle.size());
      if (ccw(l1[0],l1[1],l2[1]) == 1) {
        ans -= cornerArea(l1[1],poly,r);
      }
    }
    printf("%.10Lf\n", ans);
  }
}
accuracy: 0.5
time_ms: 60
memory_kb: 1332
final_rank: 7