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

using namespace std;

#define rep(i, n) for (int i = 0; i < int(n); ++i)

#define X real()
#define Y imag()

typedef complex<double> P;
typedef pair<P, P> L;
typedef vector<P> Pol;

const double INF = 1e40;
const double EPS = 1e-8;

int sig(double r) {return (r < -EPS) ? -1 : (r > EPS) ? 1: 0;}
bool eq(double a, double b) {return abs(a - b) < EPS;}
bool near(P a, P b) {return abs(b - a) < EPS;}

// 内積
double dot(P a, P b) {return a.X * b.X + a.Y * b.Y;}
// 外積
double cross(P a, P b) {return a.X * b.Y - a.Y * b.X;}

// 線分のベクトル
P vec(L a) {return a.second - a.first;}

// 線分abに対する点xの位置
enum CCW{FRONT = 1, RIGHT = 2, BACK = 4, LEFT = 8, ON = 16};
int ccw(L s, P p) {
  P a = vec(s);
  p -= s.first;
  double cr = cross(a, p);
  if (eq(cr, 0)) {
    if (sig(dot(a, p)) < 0) return BACK;
    if (sig(norm(a) - norm(p)) < 0) return FRONT;
    return ON;
  }
  return (cr > 0) ? LEFT : RIGHT;
}

// 交差判定
bool iLL(L a, L b) {return !eq(cross(vec(a), vec(b)), 0);}
bool eqL(L a, L b) {return !iLL(a, b) && eq(cross(vec(a), b.first - a.first), 0);}
bool iLSs(L a, L b) {return sig(cross(vec(a), b.first - a.first)) * sig(cross(vec(a), b.second - a.first)) < 0;}

// 交点
P pLL(L a, L b) {return a.first + vec(a) * (cross(vec(b), b.first - a.first) / cross(vec(b), vec(a)));}

// x座標でソート
bool lessX(P a, P b){
  if(!eq(a.X, b.X)) return a.X < b.X;
  return a.Y < b.Y;
}

// 多角形の内外判定 内部:1、周上:0、外部:-1
int sGP(Pol pol, P p) {
  int side = -1;
  rep (i, pol.size()) {
    P p0 = pol[i] - p, p1 = pol[(i + 1) % pol.size()] - p;
    if (sig(cross(p0, p1)) == 0 && sig(dot(p0, p1)) <= 0) return 0;
    if (p0.Y > p1.Y) swap(p0, p1);
    if (sig(p0.Y) <= 0 && 0 < sig(p1.Y) && sig(cross(p0, p1)) > 0) side *= -1;
  }
  return side;
}

// 凸包カット
Pol convexCut(Pol p, L l) {
  vector<P> q;
  rep (i, p.size()) {
    if (ccw(l, p[i]) & (LEFT | BACK | ON | FRONT)) q.push_back(p[i]);
    if (iLSs(l, L(p[i], p[(i + 1) % p.size()]))) q.push_back(pLL(l, L(p[i], p[(i + 1) % p.size()])));
  }
  return q;
}

int main() {
  int n, m;
  cin >> n;
  vector<Pol> vpol;
  vector<L> vl;
  rep (i, n) {
    cin >> m;
    Pol pol;
    rep (j, m) {
      P p;
      cin >> p.X >> p.Y;
      pol.push_back(p);
    }
    vpol.push_back(pol);
  }
  rep (i, n) rep (j, vpol[i].size()) {
    vl.push_back(L(vpol[i][j], vpol[i][(j + 1) % vpol[i].size()]));
  }
  vector<Pol> convex;
  Pol sq;
  sq.push_back(P(-1001, -1001));
  sq.push_back(P(1001, -1001));
  sq.push_back(P(1001, 1001));
  sq.push_back(P(-1001, 1001));
  convex.push_back(sq);
  rep (i, vl.size()) {
    vector<Pol> next;
    rep (j, convex.size()) {
      Pol pol = convexCut(convex[j], vl[i]);
      if (pol.size() >= 3) next.push_back(pol);
      pol = convexCut(convex[j], L(vl[i].second, vl[i].first));
      if (pol.size() >= 3) next.push_back(pol);
    }
    convex = next;
  }
  vector<vector<int> > edge(convex.size());
  rep (i, convex.size()) rep (j, i) {
    rep (ii, convex[i].size()) rep (jj, convex[j].size()) {
      L l1 = L(convex[i][ii], convex[i][(ii + 1) % convex[i].size()]);
      L l2 = L(convex[j][jj], convex[j][(jj + 1) % convex[j].size()]);
      if (eqL(l1, l2) && (ccw(l1, l2.first) | ccw(l1, l2.first) | ccw(l2, l1.first) | ccw(l2, l1.second)) & ON) {
	vector<P> vp;
	vp.push_back(l1.first);
	vp.push_back(l1.second);
	vp.push_back(l2.first);
	vp.push_back(l2.second);
	sort(vp.begin(), vp.end(), lessX);
	if (near(vp[1], vp[2])) continue;
	edge[i].push_back(j);
	edge[j].push_back(i);
      }
    }
  }
  vector<int> c;
  rep (i, convex.size()) {
    P g = 0;
    rep (j, convex[i].size()) g += convex[i][j];
    g /= convex[i].size();
    int cc = 0;
    rep (j, vpol.size()) {
      if (sGP(vpol[j], g) > 0) ++cc;
    }
    c.push_back(cc);
  }
  int q;
  cin >> q;
  while (q--) {
    P start, goal;
    cin >> start.X >> start.Y >> goal.X >> goal.Y;
    int startI, goalI;
    rep (i, convex.size()) {
      if (sGP(convex[i], start) >= 0) startI = i;
      if (sGP(convex[i], goal) >= 0) goalI = i;
    }
    vector<int> dis;
    rep (i, convex.size()) dis.push_back(1000000000);
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
    que.push(make_pair(0, startI));
    while (!que.empty()) {
      pair<int, int> now = que.top();
      que.pop();
      if (dis[now.second] <= now.first) continue;
      dis[now.second] = now.first;
      rep (i, edge[now.second].size()) {
	que.push(make_pair(now.first + abs(c[now.second] - c[edge[now.second][i]]), edge[now.second][i]));
      }
    }
    cout << dis[goalI] << endl;
  }
  return 0;
}

Measured memory_bytes: 1348