#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

#include <complex>
typedef complex<double> Point;
struct Line : public vector<Point> {
  Line() {;}
  Line(Point a, Point b) { push_back(a); push_back(b); }
};
namespace std {
  bool operator<(const Point &lhs, const Point &rhs) {
    if (round(lhs.real()) == round(rhs.real()) &&
        round(lhs.imag()) == round(rhs.imag())) { return false; }
    if (round(lhs.real()) != round(rhs.real())) { return lhs.real() < rhs.real(); }
    return lhs.imag() < rhs.imag();
  }
  bool operator<(const Line &lhs, const Line &rhs) {
    if (lhs[0] < rhs[0] || rhs[0] < lhs[0]) { return lhs[0] < rhs[0]; }
    return lhs[1] < rhs[1];
  }
};

typedef double Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight) : src(src), dest(dest), weight(weight) {;}
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) { return weight > rhs.weight; }
    if (src != rhs.src) { return src < rhs.src; }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void PrintMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%f ", matrix[y][x]);
    }
    puts("");
  }
}

Weight Dijkstra(const Graph &g, int s, int t) {
  const int n = g.size();
  vector<bool> visit(n, false);
  Array dist(n, 2000000000LL);
  priority_queue<Edge> que;
  que.push(Edge(s, s, 0));
  Weight ans = -1;
  dist[s] = 0;
  while (!que.empty()) {
    Edge edge = que.top();
    que.pop();
    int from = edge.dest;
    if (visit[from]) { continue; }
    visit[from] = true;
    if (from == t) {
      ans = edge.weight;
      break;
    }   
    for (int i = 0; i < (int)g[from].size(); i++) {
      int to = g[from][i].dest;
      Weight ncost = edge.weight + g[from][i].weight;
      if (visit[to] || ncost - dist[to] >= -EPS) { continue; }
      dist[to] = ncost;
      que.push(Edge(from, to, ncost));
    }   
  }
  return ans;
}

//============================================

int n, m;
int mapto[60][30];
vector<Point> ps[60];
map<Point, int> pmapto[60];
vector<Line> ls1[60];
set<Line> ls2[60];
vector<int> fs[60];
vector<int> ts[60];

vector<int> wfl;
vector<int> wfn;
vector<int> wtl;
vector<int> wtn;

void Merge(Graph &g, int from, int to) {
  REP(i, ls1[to].size()) {
    Point c = ls1[to][i][0];
    Point vect = ls1[to][i][0] - ls1[from][0][0];
    //cout << from << " " << to << " " << i << " " << vect << endl;
    vector<Line> ls = ls1[from];
    FORIT(it, ls) {
      REP(iter, 2) {
        (*it)[iter] += vect;
        //cout << (*it)[iter] << endl;
      }
    }
    //cout << ls1[to][i][1] << " " << ls[0][1] << endl;
    double angle = arg(ls1[to][i][1] - c) - arg(ls[0][1] - c);
    Point rot = Point(cos(angle), sin(angle));
    FORIT(it, ls) {
      REP(iter, 2) {
        (*it)[iter] = ((*it)[iter] - c) * rot + c;
      }
      if (!ls2[to].count(*it)) { goto next; }
    }
    REP(j, ps[from].size()) {
      Point p = (ps[from][j] + vect - c) * rot + c;
      assert(pmapto[to].count(p));
      int f = mapto[from][j];
      int t = pmapto[to][p];
      //int t = mapto[to][nj];
      g[f].push_back(Edge(f, t, 0));
      g[t].push_back(Edge(t, f, 0));
    }
    return;
next:;
  }
}

int main() {
  while (scanf("%d", &n), n) {
    MEMSET(mapto, 0xdf);
    REP(i, 60) {
      ps[i].clear();
      pmapto[i].clear();
      ls1[i].clear();
      ls2[i].clear();
      fs[i].clear();
      ts[i].clear();
    }
    wfl.clear();
    wfn.clear();
    wtl.clear();
    wtn.clear();
    m = 0;
    REP(i, n) {
      int k;
      scanf("%d", &k);
      REP(j, k) {
        int x, y;
        scanf("%d %d", &x, &y);
        Point p = Point(x, y);
        ps[i].push_back(p);
        mapto[i][j] = m;
        pmapto[i][p] = m;
        m++;
      }
      scanf("%d", &k);
      REP(j, k) {
        int f, t;
        scanf("%d %d", &f, &t);
        f--; t--;
        fs[i].push_back(f);
        ts[i].push_back(t);
      }
      scanf("%d", &k);
      REP(j, k) {
        int f1 = i;
        int f2, t1, t2;
        scanf("%d %d %d", &f2, &t1, &t2);
        f2--; t1--; t2--;
        wfl.push_back(f1);
        wfn.push_back(f2);
        wtl.push_back(t1);
        wtn.push_back(t2);
      }
    }
    Graph g(m);
    REP(i, n) {
      REP(j, fs[i].size()) {
        int f = mapto[i][fs[i][j]];
        int t = mapto[i][ts[i][j]];
        double d = abs(ps[i][fs[i][j]] - ps[i][ts[i][j]]);
        g[f].push_back(Edge(f, t, d));
        g[t].push_back(Edge(t, f, d));
        Line l1 = Line(ps[i][fs[i][j]], ps[i][ts[i][j]]);
        Line l2 = Line(ps[i][ts[i][j]], ps[i][fs[i][j]]);
        ls1[i].push_back(l1);
        ls1[i].push_back(l2);
        ls2[i].insert(l1);
        ls2[i].insert(l2);
      }
    }
    REP(i, wfl.size()) {
      int f = mapto[wfl[i]][wfn[i]];
      int t = mapto[wtl[i]][wtn[i]];
      g[f].push_back(Edge(f, t, 0.0));
    }
    REP(i, n) {
      REP(j, i) {
        Merge(g, i, j);
      }
    }
    int sl, sn, dl, dn;
    scanf("%d %d %d %d", &sl, &sn, &dl, &dn);
    sl--; sn--; dl--; dn--;
    double ans = Dijkstra(g, mapto[sl][sn], mapto[dl][dn]);
    printf("%.8f\n", ans);
  }
}

Measured memory_bytes: 0