#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
using namespace std;
static const double EPS = 1e-10;
typedef long long ll;
#define rep(i,n) for(int i=0;i<n;i++)
#define rev(i,n) for(int i=n-1;i>=0;i--)
#define sz(a) a.size()
#define all(a) a.begin(),a.end()
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define SS stringstream
#define DBG1(a) rep(_X,sz(a)){printf("%d ",a[_X]);}puts("");
#define DBG2(a) rep(_X,sz(a)){rep(_Y,sz(a[_X]))printf("%d ",a[_X][_Y]);puts("");}
#define bitcount(b) __builtin_popcount(b)
#define REP(i, s, e) for ( int i = s; i <= e; i++ )  
 
const double INF = 1e12;
typedef complex<long double> P,point;
typedef vector<P> G,polygon;
namespace std {bool operator < (const P& a, const P& b) {return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);} }
long double cross(const P& a, const P& b) {return imag(conj(a)*b);}
long double dot(const P& a, const P& b) {return real(conj(a)*b);}
struct L : public vector<P> {L(const P &a, const P &b) {push_back(a); push_back(b);} };
struct C {P p; double r;C(const P &p, double r) : p(p), r(r) { } C(){} };
int ccw(P a, P b, P c) {
	b -= a; c -= a;
	if (cross(b, c) > 0)   return +1;
	if (cross(b, c) < 0)   return -1;
	if (dot(b, c) < 0) return +2;
	if (norm(b) < norm(c)) return -2;
	return 0;
}
 
// Check Funcs //
bool intersectLL(const L &l, const L &m) {return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;}
bool intersectLS(const L &l, const L &s) {return cross(l[1]-l[0], s[0]-l[0])*cross(l[1]-l[0], s[1]-l[0]) < EPS;}
bool intersectLP(const L &l, const P &p) {return abs(cross(l[1]-p, l[0]-p)) < EPS;}
bool intersectSS(const L &s, const L &t) {return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 && ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;}
bool intersectSP(const L &s, const P &p) {return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS;}
 
// Where is Point in Polygon? //
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
enum { OUT, ON, IN };
int contains(const polygon& P, const point& p) {
	bool in = false;
	for (int i = 0; i < P.size(); ++i) {
		point a = curr(P,i) - p, b = next(P,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 ON;
	}
	return in ? IN : OUT;
}
// Totsuhou! Andrew's Monotone Chain //
 
vector<point> convex_hull(vector<point> ps) {
  int n = ps.size(), k = 0;
  sort(ps.begin(), ps.end());
  vector<point> ch(2*n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  ch.resize(k-1);
  return ch;
}
 
P projection(const L &l, const P &p) {long double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);return l[0] + (long double)t*(l[0]-l[1]);}
P reflection(const L &l, const P &p) {return p + (long double)2.0 * (projection(l, p) - p);}
 
long double distanceSP(const L &s, const P &p) {
	const P r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
long double distanceSS(const L &s, const L &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
 
P crosspoint(const L &l, const L &m) {
	long double A = cross(l[1] - l[0], m[1] - m[0]);
	long double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0];
	return m[0] + B / A * (m[1] - m[0]);
}
 

typedef long double Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;




std::istream& operator>>(std::istream& is,P& p)
{
	is >> p.real() >> p.imag();
	return is;
}



map<P,int> rdic;
vector<P> dic;
int put(P x){
	if( rdic.count(x) ) return rdic[x];
	rdic[x] = dic.size();
	dic.push_back(x);
	return rdic[x];
}
P get(int id){ return dic[id]; }

#define in()
int main(){
	int N;
	while(cin >> N && N){
		rdic.clear();
		dic.clear();
		vector<G> building;
		for(int i = 0 ; i < N ; i++){
			int M;
			cin >> M;
			G g(M);
			for(int j = 0 ; j < M ; j++) cin >> g[j];
			building.push_back(g);
		}
		P s,t;
		P A,B;
		P ms,mt;
		cin >> s >> t;
		cin >> A >> B;
		ms = reflection(L(A,B),s);
		mt = reflection(L(A,B),t);
		int idx = -1 , midx = -1;
		for(int i = 0 ; i < N ; i++){
			if( contains(building[i],s) != OUT && contains(building[i],t) != OUT ) idx = i;
			if( contains(building[i],ms) != OUT && contains(building[i],mt) != OUT ) midx = i;
		}
		if( min(idx,midx) == -1 ){
			cout << "impossible" << endl;
			continue;
		}
		G ba = building[idx] , bb = building[midx];
		
		priority_queue<Edge> Q;
		put(s);
		Q.push(Edge(0,-1,0));
		map<int,int> done;
		//cout << s << "  "<< t << endl;
		while( Q.size() ){
			Edge q = Q.top(); Q.pop();
			if( done[q.src]++ ) continue;
			P cur = get(q.src);
			P rcur = reflection(L(A,B),cur);
			//cout << cur << "-" << rcur << ": " << q.weight << endl;
			if( abs(cur-t) < EPS ){
				printf("%.20Lf\n",q.weight);
				goto success;
			}
			for(int k = 0 ; k < 2 ; k++){
				for(int i = 0 ; i < (k==0?1:0) + ba.size() ; i++){
					L l1(P(0,0),P(0,0)),l3(P(0,0),P(0,0));
					P target = i == ba.size() ? t : ba[i];
					l1 = L(cur,target);
					l3 = L(rcur,reflection(L(A,B),target));
				
					int bad = 0;
					
					vector< pair<double,P> > hit,hit2;
					for(int j = 0 ; j < ba.size() ; j++){
						L l2 = L(ba[j],ba[(j+1)%ba.size()]);
						P cp = crosspoint(l1,l2);
						if( intersectSS(l1,l2) ) hit.push_back(make_pair(abs(cur-cp),cp));
					}
					for(int j = 0 ; j < bb.size() ; j++){
						L l4 = L(bb[j],bb[(j+1)%bb.size()]);
						P cp = crosspoint(l3,l4);
						if( intersectSS(l3,l4) ) hit2.push_back(make_pair(abs(rcur-cp),cp));
					}
					
					P next = !k ? l1[1] : l3[1];
					sort(hit.begin(),hit.end());
					sort(hit2.begin(),hit2.end());
					
					
					for(int j = 1 ; j < hit.size() ; j++){
						//cout << hit[j].second <<  endl;
						P m = (long double)0.5 * (hit[j].second + hit[j-1].second);
						if( contains(ba,m) == OUT ) bad = 1;
					}
					for(int j = 1 ; j < hit2.size() ; j++){
						P m = (long double)0.5 * (hit2[j].second + hit2[j-1].second);
						if( contains(bb,m) == OUT ) bad = 1;
					}
					
					if( contains(bb,l3[1]) == OUT || contains(ba,l1[1]) == OUT) bad = 1; 
					if( bad ) continue;
					//if( abs(next-P(6,2)) < EPS ) cout << "ABS" << endl;
					long double len = !k ? abs(l1[0]-l1[1]) : abs(l3[0]-l3[1]);
					//if( hit.size() == 2 ) cout << k << "  "<< next << " " << hit.size() << " " << hit2.size() << "<" << bad << ">" << " " << hit[0] << " " << hit[1] << endl;
					int w = put(next);
					Q.push(Edge(w,-1,q.weight+len));
				}
				swap(rcur,cur);
				swap(ba,bb);
			}
		}
		cout << "impossible" << endl;
		success:;
	}
}

Measured memory_bytes: 1400