#include <bits/stdc++.h>
using namespace std;
int dcmp(double x) {
  if (x < -1e-8) return -1;
  if (x > 1e-8) return 1;
  return 0;
}
struct node {
  double x, y;
} p[1001];
struct fy {
  double x, y, theta;
} c[1000001];
int cmp(fy x, fy y) {
  if (dcmp(x.x - y.x) == 0)
    if (dcmp(y.y - x.y) == 0)
      return dcmp(y.theta - x.theta) > 0;
    else
      return dcmp(y.y - x.y) > 0;
  return dcmp(y.x - x.x) > 0;
}
int n, tot;
int main() {
  cin >> n;
  int i, j;
  double x, y;
  for (i = 1; i <= n; i++) {
    scanf("%lf%lf", &x, &y);
    p[i].x = x / y;
    scanf("%lf%lf", &x, &y);
    p[i].y = x / y;
    double L = p[i].x * p[i].x + p[i].y * p[i].y;
    p[i].x /= L;
    p[i].y /= L;
  }
  for (i = 1; i <= n; i++)
    for (j = i + 1; j <= n; j++) {
      fy tmp;
      tmp.x = (p[i].x + p[j].x) * 0.5;
      tmp.y = (p[i].y + p[j].y) * 0.5;
      tmp.theta = atan2(p[j].y - p[i].y, p[j].x - p[i].x);
      if (dcmp(tmp.theta) < 0) tmp.theta += acos(-1.0);
      if (dcmp(tmp.theta - acos(-1.0)) >= 0) tmp.theta -= acos(-1.0);
      c[++tot] = tmp;
    }
  sort(c + 1, c + tot + 1, cmp);
  long long mod = 1000000007, t1, t2, ans = 0;
  for (i = 1; i <= tot; i++) {
    j = i;
    t1 = t2 = 0;
    while (j <= tot && dcmp(c[i].x - c[j].x) == 0 &&
           dcmp(c[i].y - c[j].y) == 0) {
      int w = j;
      while (j <= tot && dcmp(c[w].theta - c[j].theta) == 0 &&
             dcmp(c[w].x - c[j].x) == 0 && dcmp(c[w].y - c[j].y) == 0)
        j++;
      t2 += (t1 + t2) * (j - w);
      t2 %= mod;
      t1 += j - w;
      t1 %= mod;
    }
    ans = (ans + t2) % mod;
    i = j - 1;
  }
  cout << ans << endl;
  return 0;
}
