// * template

#include <bits/stdc++.h>
#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }
template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

template<class T, class U> inline void fill_array(T &e, const U &v) { e = v; }
template<class T, class U, size_t s> inline void fill_array(T (&a)[s], const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U, size_t s> inline void fill_array(array<T, s> &a, const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U> inline void fill_array(vector<T> &a, const U &v) {for(auto&e:a)fill_array(e,v);}

struct range {
	typedef int Int;
	struct iter {
		Int i;
		const Int s;
		iter(const Int &i_, const Int &s_):i(i_), s(s_) {}
		bool operator!=(const iter &r) const { return s > 0 ? i < r.i : i > r.i; }
		const Int &operator*() const { return i; }
		iter &operator++() { i += s; return *this; }
	};
	const Int f, l, s;
	range(const Int &f_, const Int &l_, const Int &s_):f(f_), l(l_), s(s_) {}
	range(const Int &f_, const Int &l_):f(f_), l(l_), s(1) {}
	range(const Int &num):f(0), l(num), s(1) {}
	iter begin() const { return iter(f, s); }
	iter end() const { return iter(l, s); }
};

// * geometry library

typedef double Real;
constexpr Real EPS = 1e-7;
const Real PI = acos((Real)-1);
inline int sign(Real d) { return d > EPS ? 1 : d < -EPS ? -1 : 0; }

struct point {
	Real x, y;
	explicit point():x(0), y(0) {}
	explicit point(Real x_, Real y_):x(x_), y(y_) {}
	point operator+(const point &p) const { return point(x + p.x, y + p.y); }
	point operator-(const point &p) const { return point(x - p.x, y - p.y); }
	point operator*(const point &p) const { return point(x * p.x - y * p.y, x * p.y + y * p.x); }
	point operator*(Real s) const { return point(x * s, y * s); }
	point operator/(Real s) const { return point(x / s, y / s); }
	bool operator<(const point &p) const { return sign(x - p.x) == -1 || (sign(x - p.x) == 0 && sign(y - p.y) == -1); }
	bool operator==(const point &p) const { return sign(x - p.x) == 0 && sign(y - p.y) == 0; }
	bool operator!=(const point &p) const { return !(*this == p); }
};

inline istream &operator>>(istream &is, point &p) {
	return is >> p.x >> p.y;
}

inline ostream &operator<<(ostream &os, const point &p) {
	return os << '(' << p.x << ", " << p.y << ')';
}

struct line : public array<point, 2> {
	line(const point &a, const point &b) { at(0) = a; at(1) = b; }
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) { at(0) = a; at(1) = b; }
};

typedef vector<point> polygon;

inline Real norm(const point &p) {
	return p.x * p.x + p.y * p.y;
}

inline Real abs(const point &p) {
	return sqrt(norm(p));
}

inline Real dot(const point &a, const point &b) {
	return a.x * b.x + a.y * b.y;
}

inline Real cross(const point &a, const point &b) {
	return a.x * b.y - a.y * b.x;
}

enum { CCW = 1, CW = -1, BACK = 2, FRONT = -2, ON = 0};
inline int ccw(const point &a, const point &b, const point &c) {
	const point p = b - a;
	const point q = c - a;
	const int sign_cross = sign(cross(p, q));
	if(sign_cross == 1) return CCW;
	if(sign_cross == -1) return CW;
	if(sign(dot(p, q)) == -1) return BACK;
	if(sign(norm(p) - norm(q)) == -1) return FRONT;
	return ON;
}

// ??????????§??????¨??????????????????a, b, c???????????????
// c??????a??????b??????????¨?????????§???????§????????????¨?????????????????¨?????????????????????
// + : ?????¨
// 0 : ?????? or A = B
// - : ?????¨
inline int judge(const point &a, const point &b, const point &c) {
	return sign(cross(a, c)) - sign(cross(b, c)) - sign(cross(a, b));
}

inline point project(const line &l, const point &p) {
	const point a = p - l[0];
	const point b = l[1] - l[0];
	return l[0] + b * (dot(a, b) / norm(b));
}

inline point reflect(const line &l, const point &p) {
	const point t = project(l, p);
	return t + (t - p);
}

inline bool intersect(const segment &s, const point &p) {
	return ccw(s[0], s[1], p) == ON;
}

inline bool intersect(const segment &a, const segment &b) {
	return ccw(a[0], a[1], b[0]) * ccw(a[0], a[1], b[1]) <= 0
		&& ccw(b[0], b[1], a[0]) * ccw(b[0], b[1], a[1]) <= 0;
}

inline Real dist(const point &a, const point &b) {
	return abs(a - b);
}

inline bool contain(const polygon &P, const point &p) {
	bool res = false;
	for(int i = 0; i < P.size(); ++i) {
		point v1 = P[i] - p;
		point v2 = P[(i + 1) % P.size()] - p;
		if(v1.y > v2.y) swap(v1, v2);
		if(sign(cross(v1, v2)) == 0 && sign(dot(v1, v2)) <= 0) return true; // on edge
		if(sign(v1.y) <= 0 && sign(v2.y) == 1 && sign(cross(v1, v2)) == 1) res = !res;
	}
	return res;
}

inline bool contain(const polygon &P, const segment &s) {
	const Real c = (EPS * 100);

	if(!contain(P, s[0] + (s[1] - s[0]) * c)) return false;
	if(!contain(P, s[1] + (s[0] - s[1]) * c)) return false;

	const int n = P.size();
	for(int i = 0; i < n; ++i) {
		const point &curr = P[i];
		const point &next = P[(i + 1) % n];

		const int c1 = ccw(curr, next, s[0]);
		const int c2 = ccw(curr, next, s[1]);
		if(c1 == ON && c2 == ON) return true;
		if(c1 * c2 == -1 && ccw(s[0], s[1], curr) * ccw(s[0], s[1], next) == -1) return false;
	}

	for(int i = 0; i < n; ++i) {
		const point &prev = P[(i - 1 + n) % n];
		const point &curr = P[i];
		const point &next = P[(i + 1) % n];

		if(curr != s[0] && curr != s[1] && intersect(s, curr)) {
			if(judge(prev - curr, next - curr, s[0] - curr) > 0) return false;
			if(judge(prev - curr, next - curr, s[1] - curr) > 0) return false;
		}
	}

	return true;
}

// * solve

typedef pair<int, Real> edge;
typedef vector<vector<edge>> graph;

vector<Real> dijkstra(int s, const graph &G) {
	typedef pair<Real, int> P;
	const int n = G.size();

	vector<Real> dis(n, numeric_limits<Real>::max());
	priority_queue<P, vector<P>, greater<P>> que;

	dis[s] = 0;
	que.emplace(0, s);

	while(!que.empty()) {
		const auto d = que.top().first;
		const auto v = que.top().second;
		que.pop();

		if(dis[v] < d) continue;

		for(const auto &e : G[v]) {
			const auto next_dis = d + e.second;
			if(dis[e.first] > next_dis) {
				dis[e.first] = next_dis;
				que.emplace(next_dis, e.first);
			}
		}
	}

	return dis;
}

Real dijkstra(int s, int g, const graph &G) {
	return dijkstra(s, G)[g];
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(10);

	for(int n; cin >> n && n;) {
		vector<polygon> building;
		building.reserve(n);

		for(const int i : range(n)) {
			int m;
			cin >> m;

			polygon P;
			P.reserve(m);

			for(const int j : range(m)) {
				point p;
				cin >> p;
				P.emplace_back(p);
			}
			building.emplace_back(P);
		}

		point s, g, l1, l2;
		cin >> s >> g >> l1 >> l2;

		const line L(l1, l2);
		const point r_s = reflect(L, s);
		const point r_g = reflect(L, g);

		int idx = -1, r_idx = -1;
		for(const int i : range(n)) {
			if(contain(building[i], s) && contain(building[i], g)) {
				idx = i;
			}
			else if(contain(building[i], r_s) && contain(building[i], r_g)) {
				r_idx = i;
			}
		}

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

		const polygon &P = building[idx];
		const polygon &r_P = building[r_idx];

		vector<point> points;
		for(const auto &p : P) {
			points.emplace_back(p);
		}

		for(const auto &p : r_P) {
			points.emplace_back(reflect(L, p));
		}

		sort(begin(points), end(points));
		points.erase(unique(begin(points), end(points)), end(points));
		points.emplace_back(s);
		points.emplace_back(g);

		const int V = points.size();
		graph G(V);

		for(const int i : range(V)) {
			for(const int j : range(i + 1, V)) {
				const segment seg(points[i], points[j]), r_seg(reflect(L, points[i]), reflect(L, points[j]));

				if(contain(P, seg) && contain(r_P, r_seg)) {
					const Real d = dist(points[i], points[j]);
					G[i].emplace_back(j, d);
					G[j].emplace_back(i, d);
				}
			}
		}

		const auto ans = dijkstra(V - 2, V - 1, G);
		if(ans == numeric_limits<Real>::max()) {
			cout << "impossible" << endl;
		}
		else {
			cout << ans << endl;
		}
	}

	return EXIT_SUCCESS;
}

Measured memory_bytes: 1364