#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;
}

Measured memory_bytes: 1344