#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
#define G_SIZE 2005

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;

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

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

struct Edge{
	Edge(int arg_to,double arg_cost){
		to = arg_to;
		cost = arg_cost;
	}
	int to;
	double cost;
};

struct Info{
	Info(int arg_node_id,double arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct Info &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}

	int node_id;
	double sum_dist;
};


int N;
int base_index,rev_index;
double min_dist[G_SIZE];
Polygon POLYGON[SIZE],REV,BASE;
Point start,goal,rev_start,rev_goal;
Line LINE;
vector<Edge> G[G_SIZE];



Point calc_Reflection_Point(double x1,double y1,double x2,double y2,double xp,double yp){

	Point ret;

	bool X_FLG = false,Y_FLG = false;
	double slope;

	if(y1 == y2){
		X_FLG = true;
	}else if(x1 == x2){
		Y_FLG = true;
	}else{
		slope = (y2-y1)/(x2-x1);
	}

	if(X_FLG){
		ret.x = xp,ret.y=y1;
	}else if(Y_FLG){
		ret.x = x1,ret.y = yp;
	}else{
		ret.x = (yp*(x2-x1)*(y2-y1)+xp*(x2-x1)*(x2-x1)-y1*(y2-y1)*(x2-x1)+x1*(y2-y1)*(y2-y1))/((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1));
		ret.y = ((x1-x2)*ret.x+yp*(y2-y1)+xp*(x2-x1))/(y2-y1);
	}
	ret.x = 2*ret.x-xp;
	ret.y = 2*ret.y-yp;

	return ret;
}

Point calc_Reflection_Point(Line line,Point point){

	return calc_Reflection_Point(line.p[0].x,line.p[0].y,line.p[1].x,line.p[1].y,point.x,point.y);
}




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


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 cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

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

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

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

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


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(l.p[1]-l.p[0],p-l.p[0]) < 0.0) return abs(p-l.p[0]);
	if(dot(l.p[0]-l.p[1],p-l.p[1]) < 0.0) return abs(p-l.p[1]);
	return getDistanceLP(l,p);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.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);
}


bool contains(Polygon g,Line l){

	if(contains(g,l.p[0]) == 0 || contains(g,l.p[1]) == 0){

		return false;
	}

	Polygon TMP;

	TMP.push_back(l.p[0]);
	TMP.push_back(l.p[1]);

	for(int i = 0; i < g.size(); i++){
		Line tmp_line = Line(g[i],g[(i+1)%g.size()]);

		if(is_Cross(tmp_line,l)){

			TMP.push_back(calc_Cross_Point(l,tmp_line));
		}
	}

	sort(TMP.begin(),TMP.end());
	TMP.erase(unique(TMP.begin(),TMP.end()),TMP.end());

	for(int i = 0; i < TMP.size()-1; i++){

		Point mid = Point((TMP[i].x+TMP[i+1].x)/2,(TMP[i].y+TMP[i+1].y)/2);
		if(contains(g,mid) == 0){

			return false;
		}
	}

	return true;
}

bool is_OK(Line A){

	return contains(POLYGON[base_index],A) && contains(REV,A);
}

void func(){

	REV.clear();
	BASE.clear();

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

		POLYGON[i].clear();
	}

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

		G[i].clear();
	}

	int num_points;
	double X,Y;

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

		scanf("%d",&num_points);

		for(int loop = 0; loop < num_points; loop++){

			scanf("%lf %lf",&X,&Y);

			POLYGON[i].push_back(Point(X,Y));
		}
	}

	scanf("%lf %lf %lf %lf",&start.x,&start.y,&goal.x,&goal.y);
	scanf("%lf %lf %lf %lf\n",&LINE.p[0].x,&LINE.p[0].y,&LINE.p[1].x,&LINE.p[1].y);

	//startがあるポリゴンを探す
	for(int i = 0; i < N; i++){

		if(contains(POLYGON[i],start) != 0){

			base_index = i;
			break;
		}
	}

	//少なくとも、rev_startとrev_goalが同じポリゴンの中にあるか調べる
	rev_start = calc_Reflection_Point(LINE,start);
	rev_goal = calc_Reflection_Point(LINE,goal);

	int rev_start_index = -1,rev_goal_index = -1;

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

		if(contains(POLYGON[i],rev_start) != 0){

			rev_start_index = i;
			break;
		}
	}

	if(rev_start_index == -1){

		printf("impossible\n");
		return;
	}

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

		if(contains(POLYGON[i],rev_goal) != 0){

			rev_goal_index = i;
			break;
		}
	}

	if(rev_start_index != rev_goal_index){

		printf("impossible\n");
		return;
	}

	rev_index = rev_start_index;

	//POLYGON[rev_index]の線対称ポリゴン作成
	for(int i = 0; i < POLYGON[rev_index].size(); i++){

		REV.push_back(calc_Reflection_Point(LINE,POLYGON[rev_index][i]));
	}

	BASE.push_back(start);
	BASE.push_back(goal);

	for(int i = 0; i < POLYGON[base_index].size(); i++){

		BASE.push_back(POLYGON[base_index][i]);
	}

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

		BASE.push_back(REV[i]);
	}

	//POLYGON[base_index]と、REVの交点を追加する
	for(int i = 0; i < POLYGON[base_index].size(); i++){
		Line A = Line(POLYGON[base_index][i],POLYGON[base_index][(i+1)%POLYGON[base_index].size()]);
		for(int k = 0; k < REV.size(); k++){
			Line B = Line(REV[k],REV[(k+1)%REV.size()]);

			if(!is_Cross(A,B))continue;

			BASE.push_back(calc_Cross_Point(A,B));
		}
	}

	sort(BASE.begin(),BASE.end());
	BASE.erase(unique(BASE.begin(),BASE.end()),BASE.end());

	int V = BASE.size();

	int start_index,goal_index;

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

		if(BASE[i] == start){

			start_index = i;

		}else if(BASE[i] == goal){

			goal_index = i;
		}
	}

	//エッジをあらかじめ計算しておく
	for(int i = 0; i < V-1; i++){
		for(int k = i+1; k < V; k++){

			double tmp_dist = calc_dist(BASE[i],BASE[k]);

			if(is_OK(Line(BASE[i],BASE[k]))){

				G[i].push_back(Edge(k,tmp_dist));
				G[k].push_back(Edge(i,tmp_dist));
			}
		}
	}

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

		min_dist[i] = HUGE_NUM;
	}

	min_dist[start_index] = 0;

	priority_queue<Info> Q;
	Q.push(Info(start_index,0));

	int next_node;
	double next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]+EPS){

			Q.pop();

		}else if(Q.top().node_id == goal_index){

			printf("%.10lf\n",Q.top().sum_dist);
			return;

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = Q.top().sum_dist+G[Q.top().node_id][i].cost;

				if(min_dist[next_node] > next_dist+EPS){
					min_dist[next_node] = next_dist;
					Q.push(Info(next_node,next_dist));
				}
			}

			Q.pop();
		}
	}

	printf("impossible\n");
}

int main(){

	while(true){

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

		func();
	}

	return 0;
}



Measured memory_bytes: 3452