#include <iostream>
#include <vector>
#include <complex>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cstdio>

using namespace std;

const double EPS = 1e-7;
typedef complex<double> P;
typedef vector<P> G;

namespace std{
	bool operator < (const P &a, const P &b){
		return make_pair(real(a), imag(a)) < make_pair(real(b), imag(b));
	}
}

struct L { P p, q; L(P p, P q) : p(p), q(q) {} };

double dot(P a, P b) { return real(conj(a)*b); }
double cross(P a, P b) { return imag(conj(a)*b); }
double angle(P a, P b) { return arg(conj(a)*b); }

bool ssIntersect(const L& a, const L& b){
	if(abs(imag((a.q-a.p)/(b.q-b.p))) < EPS) return false;
	return cross(a.q-a.p, b.p-a.p)*cross(a.q-a.p, b.q-a.p) < EPS &&
    	   cross(b.q-b.p, a.p-b.p)*cross(b.q-b.p, a.q-b.p) < EPS;
}

bool spIntersect(const L& l, const P& p){
	return abs(abs(l.p-p)+abs(l.q-p)-abs(l.p-l.q)) < EPS;
}

P ssCrosspoint(const L& a, const L& b){
	double A = cross(a.q-a.p, b.q-b.p);
	double B = cross(a.q-a.p, a.q-b.p);
	return b.p + B/A * (b.q-b.p);
}

bool contains(const G& g, const P& p){
	double sumAgl = 0;
	for(int i=0;i<g.size();i++){
		int next = (i+1)%g.size();
		if(spIntersect(L(g[i], g[next]), p)) return true;
		sumAgl += angle(g[next]-p, g[i]-p);
	}
	return abs(sumAgl) > 1;
}

// lの両端点がg内部にあることは予め調べておく
bool containSegment(const G& g, const L& l){
	int n = g.size();
	vector<P> cp;
	for(int i=0;i<n;i++){
		int next = (i+1)%n;
		L seg(g[i], g[next]);
		if(ssIntersect(seg, l))
			cp.push_back(ssCrosspoint(seg, l));
	}
	sort(cp.begin(), cp.end());
	for(int i=0;i+1<cp.size();i++)
		if(!contains(g, 0.5*(cp[i]+cp[i+1]))) return false;
	return true;
}

P footPerp(const L& l, const P& p) {
	return l.p + (l.q-l.p)*(dot(l.q-l.p, p-l.p) / (abs(l.q-l.p)*abs(l.q-l.p)));
}

P lineShadow(const L& l, const P& p){
	return 2.0*footPerp(l, p)-p;
}

int main(){
	int n;
	while(cin >> n && n){
		vector<G> g(n);
		for(int i=0;i<n;i++){
			int m; cin >> m;
			for(int j=0;j<m;j++){
				int x, y; cin >> x >> y;
				g[i].push_back(P(x, y));
			}
		}
		P start, goal, l1, l2;
		cin >> start.real() >> start.imag() >> goal.real() >> goal.imag();
		cin >> l1.real() >> l1.imag() >> l2.real() >> l2.imag();
		L l(l1, l2);

		P startM = lineShadow(l, start);
		P goalM  = lineShadow(l, goal);

		int idxA = -1, idxB = -1;
		for(int i=0;i<n;i++){
			if(contains(g[i], start) && contains(g[i], goal)) idxA = i;
			if(contains(g[i], startM) && contains(g[i], goalM)) idxB = i;
		}
		if(idxA == -1 || idxB == -1){
			printf("impossible\n");
			continue;
		}
		for(int i=0;i<g[idxB].size();i++)
			g[idxB][i] = lineShadow(l, g[idxB][i]);
		vector<P> vp;
		vp.push_back(start);
		vp.push_back(goal);
		for(int i=0;i<g[idxA].size();i++)
			if(contains(g[idxB], g[idxA][i])) vp.push_back(g[idxA][i]);
		for(int i=0;i<g[idxB].size();i++)
			if(contains(g[idxA], g[idxB][i])) vp.push_back(g[idxB][i]);
		vector<int> mark(vp.size(), 0);
		vector<double> dist(vp.size(), 1e12);

		priority_queue< pair<double, int> > qu; qu.push(make_pair(0, 0));
		while(!qu.empty()){
			pair<double, int> pr = qu.top(); qu.pop();
			double d = -pr.first;
			int idx = pr.second;
			if(mark[idx]) continue;
			mark[idx] = 1;
			for(int i=0;i<vp.size();i++){
				if(mark[i]) continue;
				if(containSegment(g[idxA], L(vp[idx], vp[i])) && containSegment(g[idxB], L(vp[idx], vp[i]))){
					double nd = d + abs(vp[idx]-vp[i]);
					if(nd < dist[i]){
						dist[i] = nd;
						qu.push(make_pair(-nd, i));
					}
				}
			}
		}
		if(dist[1] < 1e11) printf("%.9lf\n", dist[1]);
		else               printf("impossible\n");
	}
}

Measured memory_bytes: 1376