#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 105

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){

	}
};

struct Info{

	int num_points;
	double height;
	Polygon polygon;
};

int N;
Info info[SIZE];
double THETA,FAI;
double min_dist[SIZE][SIZE];
Point start,goal;


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -1;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}


Polygon ConvexHull(Polygon V){

	sort(V.begin(),V.end());

	vector<Point> UP,DOWN;

	UP.push_back(V[0]);
	DOWN.push_back(V[0]);

	for(int i = 1; i < V.size(); i++){

		while(UP.size() > 1 && ccw(UP[UP.size()-2],UP[UP.size()-1],V[i]) == COUNTER_CLOCKWISE){

			UP.pop_back();
		}

		while(DOWN.size() > 1 && ccw(DOWN[DOWN.size()-2],DOWN[DOWN.size()-1],V[i]) ==  CLOCKWISE){

			DOWN.pop_back();
		}

		UP.push_back(V[i]);
		DOWN.push_back(V[i]);
	}

	Polygon ret;

	for(int i = 0; i < UP.size(); i++){

		ret.push_back(UP[i]);
	}

	for(int i = DOWN.size()-1; i >= 0; i--){

		ret.push_back(DOWN[i]);
	}

	return ret;
}



Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[0].y-A.p[1].y)/(A.p[0].x-A.p[1].x);
	}
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

//★★線分ではなく直線と点の距離★★
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//★★点と線分の距離★★
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//★★線分と線分の距離★★
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

double calc_dist(Polygon A,Polygon B){

	double ret = HUGE_NUM;

	for(int i = 0; i < A.size(); i++){
		Line a = Line(A[i],A[(i+1)%A.size()]);
		for(int k = 0; k < B.size(); k++){
			Line b = Line(B[k],B[(k+1)%B.size()]);
			ret = min(ret,getDistance(a,b));
		}
	}
	return ret;
}

double calc_dist(Polygon polygon,Point point){

	if(contains(polygon,point) == 2)return 0;

	double ret = HUGE_NUM;
	for(int i = 0; i < polygon.size(); i++){

		Line tmp_line = Line(polygon[i],polygon[(i+1)%polygon.size()]);
		ret = min(ret,getDistanceSP(tmp_line,point));
	}

	return ret;
}

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

void func(){

	for(int i = 0; i < N; i++){

		info[i].polygon.clear();
	}

	for(int i = 0; i < N; i++){

		scanf("%d %lf",&info[i].num_points,&info[i].height);

		for(int loop = 0; loop < info[i].num_points; loop++){

			double x,y;
			scanf("%lf %lf",&x,&y);

			info[i].polygon.push_back(Point(x,y));
		}
	}

	scanf("%lf %lf",&THETA,&FAI);
	double theta = THETA*M_PI/180; //ラジアンにする
	double fai = FAI*M_PI/180;

	scanf("%lf %lf %lf %lf",&start.x,&start.y,&goal.x,&goal.y);

	for(int i = 0; i < N; i++){

		Polygon tmp;

		for(int k = 0; k < info[i].polygon.size(); k++){

			double L = info[i].height/tan(fai);
			tmp.push_back(Point(info[i].polygon[k].x-L*cos(theta),info[i].polygon[k].y-L*sin(theta)));

		}

		for(int k = 0; k < tmp.size(); k++){

			info[i].polygon.push_back(tmp[k]);
		}

		info[i].polygon = ConvexHull(info[i].polygon);
	}

	int START = N,GOAL = N+1;

	for(int i = 0; i <= N+1; i++){
		for(int k = 0; k <= N+1; k++){
			if(k == i){

				min_dist[i][k] = 0;

			}else{

				min_dist[i][k] = HUGE_NUM;
			}
		}
	}

	//スタートとゴールの距離
	min_dist[START][GOAL] = calc_dist(start,goal);
	min_dist[GOAL][START] = calc_dist(start,goal);

	//スタートと各建物の距離
	for(int i = 0; i < N; i++){

		min_dist[START][i] = calc_dist(info[i].polygon,start);
		min_dist[i][START] = min_dist[START][i];
	}

	//ゴールと各建物の距離
	for(int i = 0; i < N; i++){

		min_dist[GOAL][i] = calc_dist(info[i].polygon,goal);
		min_dist[i][GOAL] = min_dist[GOAL][i];
	}

	//建物同士の距離
	for(int i = 0; i < N-1; i++){
		for(int k = i+1; k < N; k++){
			min_dist[i][k] = calc_dist(info[i].polygon,info[k].polygon);
			min_dist[k][i] = min_dist[i][k];
		}
	}

	for(int mid = 0; mid <= N+1; mid++){
		for(int st = 0; st <= N+1; st++){
			if(fabs(min_dist[st][mid]-HUGE_NUM) < EPS)continue;
			for(int gl = 0; gl <= N+1; gl++){
				if(fabs(min_dist[mid][gl]-HUGE_NUM) < EPS)continue;

				min_dist[st][gl] = min(min_dist[st][gl],min_dist[st][mid]+min_dist[mid][gl]);
			}
		}
	}

	printf("%.10lf\n",min_dist[START][GOAL]);
}

int main(){

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}



Measured memory_bytes: 3856