#include <iostream>
#include <cstdio>
#include <complex>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

typedef complex<double> point;
typedef vector<point> polygon;

struct line : public vector<point>
{
	line(const point &a, const point &b) { push_back(a); push_back(b); }
};

const double eps = 1e-10;
double dot  (const point &a, const point &b) { return (a*conj(b)).real(); }
double cross(const point &a, const point &b) { return (conj(a)*b).imag(); }
point  vec  (const line  &l)   { return (l[1]-l[0]); }
point  unit (const point &v)   { return (v/abs(v)); }
point  curr (const polygon &g, int i) { return g[i]; }
point  next (const polygon &g, int i) { return g[(i+1)%g.size()]; }

namespace std
{
	bool operator<(const point& a, const point& b)
	{
		if(abs(a.real() - b.real()) > eps) return a.real() < b.real();
		if(abs(a.imag() - b.imag()) > eps) return a.imag() < b.imag();
		return false;
	}
}

int ccw(const point &a, const point &b, const point &c)
{
	point u=b-a, v=c-a;
	if(cross(u,v) > 0) return +1;
	if(cross(u,v) < 0) return -1;
	if(  dot(u,v) < 0 ) return +2; // c<a<b
	if(abs(u) < abs(v)) return -2; // a<b<c
	return 0;
}

int ccw(const line& s, const point& p)
{
	return ccw(s[0], s[1], p);
}

point projection(const line &l, const point &p)
{
	double t = dot(p-l[0], vec(l)) / norm(vec(l));
	return l[0] + t*vec(l);
}

point reflection(const line &l, const point &p)
{
	return p + 2.0*(projection(l,p) - p);
}

point crosspointLL(const line& l, const line& m)
{
	double A = cross(vec(l), vec(m));
	double B = cross(vec(l), l[1]-m[0]);
	if(abs(A)<eps) return l[0];
	return m[0] + B/A*vec(m);
}

bool intersectSP(const line& s, const point& p)
{
	return abs(s[0]-p)+abs(s[1]-p) < abs(s[1]-s[0])+eps;
}

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

bool containGP(const polygon &g, const point &p)
{
	bool in = false;
	for(int i=0; i<g.size(); i++)
	{
		point a = curr(g,i) - p;
		point b = next(g,i) - p;
		if(imag(a) > imag(b)) swap(a,b);
		if(imag(a) <= 0 && 0 < imag(b))
		{
			if(cross(a,b) < 0) in = !in;
		}
		if(cross(a,b) == 0 && dot(a,b) <= 0) return true;
	}
	return in;
}

bool containGS(const polygon &g, const line &l)
{
	point v = unit(vec(l));
	vector<pair<double,point> > cp;

	cp.push_back( make_pair(dot(v, l[0]-l[0]), l[0]) );
	cp.push_back( make_pair(dot(v, l[1]-l[0]), l[1]) );
	for(int i=0; i<g.size(); i++)
	{
		line edge(curr(g,i), next(g,i));
		if( intersectSS(l,edge) )
		{
			point c = crosspointLL(l,edge);
			cp.push_back( make_pair(dot(v, c-l[0]), c) );
		}
	}
	sort(cp.begin(), cp.end());
	
	for(int i=1; i<cp.size(); i++)
	{
		point p = (cp[i-1].second + cp[i].second) / 2.0;
		if( !containGP(g, p) ) return false;
	}

	return true;
}

struct Node
{
	point pos;
	vector<int> to;	
	vector<double> cost;
};

struct Data
{
	double d;
	int c,p;
	Data(double d, int c, int p) : d(d), c(c), p(p) {}
	bool operator<(const Data &x) const { return d>x.d; }
};


int main()
{
	int N,M;
	while(cin >> N, N)
	{
		//入力
		polygon building[100];

		for(int i=0; i<N; i++)
		{
			cin >> M;
			for(int j=0; j<M; j++)
			{
				int x,y;
				cin >> x >> y;
				building[i].push_back( point(x,y) );
			}
		}

		int sx,sy,gx,gy;
		cin >> sx >> sy >> gx >> gy;
		
		int ax,ay,bx,by;
		cin >> ax >> ay >> bx >> by;

		point start(sx,sy);
		point goal (gx,gy);
		line  mirror( point(ax,ay), point(bx,by) );
		point mirror_start = reflection(mirror, start);
		point mirror_goal  = reflection(mirror, goal );

		//経路を含む建物の選択
		int b1=-1, b2=-1;
		for(int i=0; i<N; i++)
		{
			if(containGP(building[i], start)
			&& containGP(building[i], goal))
			{
				b1 = i;
			}

			if(containGP(building[i], mirror_start)
			&& containGP(building[i], mirror_goal))
			{
				b2 = i;
			}
		}

		if(b1==-1 || b2==-1)
		{
			cout << "impossible" << endl;
			continue;
		}

		for(int i=0; i<building[b2].size(); i++)
		{
			building[b2][i] = reflection(mirror, building[b2][i]);
		}
		reverse(building[b2].begin(), building[b2].end());

		int  gsize = 0;		
		Node nodes[102];

		nodes[gsize++].pos = start;
		nodes[gsize++].pos = goal;
		for(int i=0; i<building[b1].size(); i++)
		{
			nodes[gsize++].pos = building[b1][i];
		}
		for(int i=0; i<building[b2].size(); i++)
		{
			nodes[gsize++].pos = building[b2][i];
		}

		for(int i=0; i<gsize; i++)
		for(int j=0; j<gsize; j++)
		{
			line edge(nodes[i].pos, nodes[j].pos);
			if(containGS(building[b1], edge)
			&& containGS(building[b2], edge))
			{
				double d = abs(nodes[i].pos - nodes[j].pos);
				nodes[i].to.push_back(j);
				nodes[j].to.push_back(i);
				nodes[i].cost.push_back(d);
				nodes[j].cost.push_back(d);
			}
		}

		priority_queue<Data> q;
		bool visit[102] = {false};
		int prev[102] = {0};

		bool ok = false;
		q.push(Data(0, 0, 0));
		while(!q.empty())
		{
			Data t = q.top(); q.pop();

			if(visit[t.c]) continue;
			visit[t.c] = true;
			prev[t.c] = t.p;

			if(t.c == 1)
			{
				ok = true;
				printf("%.10lf\n", t.d);
				break;
			}

			for(int i=0; i<nodes[t.c].to.size(); i++)
			{
				int to = nodes[t.c].to[i];
				if(visit[to]) continue;
				q.push( Data( t.d+nodes[t.c].cost[i], to, t.c) );
			}
		}

		if(!ok)
		{
			cout << "impossible" << endl;
		}
	}
}

Measured memory_bytes: 1396