#include <bits/stdc++.h>
using namespace std;
const long double eps = 1E-10, PI = acos(-1);
inline int flag(long double x) {
  if (fabs(x) <= eps) return 0;
  return x > eps ? 1 : -1;
}
struct Point {
  long double x, y;
  inline bool operator<(const Point &a) const {
    if (flag(x - a.x)) return flag(x - a.x) < 0;
    return flag(y - a.y) < 0;
  }
  inline bool operator==(const Point &a) const {
    return !flag(x - a.x) && !flag(y - a.y);
  }
} pi[1100];
struct node {
  Point p;
  long double alpha;
  inline bool operator<(const node &a) const {
    if (p == a.p) return flag(alpha - a.alpha) < 0;
    return p < a.p;
  }
} ci[1100000];
int n, m;
int main(void) {
  scanf("%d", &n);
  double x, y, len;
  node tmp;
  for (int i = 1; i <= n; i++) {
    scanf("%lf%lf", &x, &y), pi[i].x = x / y, scanf("%lf%lf", &x, &y),
                             pi[i].y = x / y;
    len = pi[i].x * pi[i].x + pi[i].y * pi[i].y, pi[i].x /= len, pi[i].y /= len;
  }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= i - 1; j++) {
      tmp.p.x = (pi[i].x + pi[j].x) / 2, tmp.p.y = (pi[i].y + pi[j].y) / 2;
      tmp.alpha = atan2(pi[j].y - pi[i].y, pi[j].x - pi[i].x);
      if (flag(tmp.alpha) < 0) tmp.alpha += PI;
      if (flag(tmp.alpha - PI) >= 0) tmp.alpha -= PI;
      ci[++m] = tmp;
    }
  sort(ci + 1, ci + m + 1);
  int ans = 0;
  for (int i = 1; i <= m; i++) {
    int j = i;
    int t1 = 0, t2 = 0;
    while (j <= m && ci[j].p == ci[i].p) {
      int k = j;
      while (j <= m && !(ci[k] < ci[j])) j++;
      t2 = (t2 + (t1 + t2) * 1LL * (j - k)) % 1000000007;
      t1 = (t1 + j - k) % 1000000007;
    }
    i = j - 1, ans = (ans + t2) % 1000000007;
  }
  printf("%d\n", ans);
  return 0;
}
