#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <unordered_set>
#include <unordered_map>
using namespace std;
#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS) return -1;
  if (x > +EPS) return +1;
  return 0;
}
struct point {
  double x, y; 
  bool operator<(point p) const { 
    int s = sign(x - p.x);
    return s ? s < 0 : sign(y - p.y) < 0;
  }
};
point operator+(point p, point q) { return {p.x+q.x,p.y+q.y}; }
point operator-(point p, point q) { return {p.x-q.x,p.y-q.y}; }
point operator*(double a, point p) { return {a*p.x,a*p.y}; }
double dot(point p, point q) { return p.x*q.x+p.y*q.y; }
double cross(point p, point q) { return p.x*q.y-p.y*q.x; }
double norm(point p) { return sqrt(dot(p,p)); }
double arg(point p) { return atan2(p.y, p.x); }

struct segment { point p, q; };
vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p); 
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) { a = -a; b = -b; c = -c; }
  if (sign(b) < 0 || sign(a-b) < 0 ||
      sign(c) < 0 || sign(a-c) < 0) return {};
  if (sign(a) != 0) return {s.p + b/a*(s.q - s.p)};
  vector<point> ps;
  auto insert_if_possible = [&](point p) {
    for (auto q: ps) if (sign(dot(p-q, p-q)) == 0) return;
    ps.push_back(p);
  };
  if (sign(dot(s.p-t.p, s.q-t.p)) <= 0) insert_if_possible(t.p);
  if (sign(dot(s.p-t.q, s.q-t.q)) <= 0) insert_if_possible(t.q);
  if (sign(dot(t.p-s.p, t.q-s.p)) <= 0) insert_if_possible(s.p);
  if (sign(dot(t.p-s.q, t.q-s.q)) <= 0) insert_if_possible(s.q);
  return ps;
}
struct arrangement {
  struct edge {
    int src, dst;
    double weight;
    size_t id, rev;
  };
  int n;
  vector<point> ps; // ps[id[p]] = p, id[ps[k]] = k
  map<point,int> id; 
  vector<vector<edge>> adj;
  arrangement(vector<segment> ss) : n(0) {
    vector<vector<pair<double, int>>> group(ss.size());
    auto append = [&](int i, point p) {
      if (!id.count(p)) { id[p] = n++; ps.push_back(p); }
      group[i].push_back({norm(ss[i].p - p), id[p]});
    };
    for (int i = 0; i < ss.size(); ++i) {
      append(i, ss[i].p);
      append(i, ss[i].q);
      for (int j = 0; j < i; ++j) {
        auto qs = intersect(ss[i], ss[j]);
        if (qs.size() == 1) {
          append(i, qs[0]);
          append(j, qs[0]);
        }
      }
    }
    adj.resize(n);
    for (auto &vs: group) {
      sort(all(vs));
      for (int i = 0; i+1 < vs.size(); ++i) {
        auto u = vs[i].snd, v = vs[i+1].snd;
        if (u == v) continue;
        auto len = vs[i+1].fst - vs[i].fst;
        adj[u].push_back({u, v, len});
        adj[v].push_back({v, u, len});
      }
    }
    // remove duplicates and orient edges
    vector<unordered_map<int, int>> idx(n);
    for (int u = 0; u < n; ++u) {
      auto eq = [&](edge e, edge f) { return e.dst == f.dst; };
      auto lt = [&](edge e, edge f) { return e.dst <  f.dst; };
      sort(all(adj[u]), lt);
      adj[u].erase(unique(all(adj[u]), eq), adj[u].end());
      sort(all(adj[u]), [&](edge e, edge f) {
        return arg(ps[e.dst] - ps[e.src]) > arg(ps[f.dst] - ps[f.src]);
      });
      for (int i = 0; i < adj[u].size(); ++i) {
        adj[u][i].id = i;
        int v = adj[u][i].dst;
        idx[u][v] = i;
        if (idx[v].count(u)) {
          int j = idx[v][u];
          adj[u][i].rev = j;
          adj[v][j].rev = i;
        }
      }
    }
  }
  bool traverse_all_faces3() {
    vector<unordered_set<int>> visited(n);
    auto contains = [&](edge e, point p) {
      edge s = e;
      bool in = false;
      do {
        point a = ps[e.src] - p, b = ps[e.dst] - p;
        if (a.y > b.y) swap(a, b);
        if (a.y <= 0 && 0 < b.y && cross(a, b) < 0) in = !in;
        if (!sign(cross(a, b)) && sign(dot(a, b)) <= 0) 
          return 1; // point on the edge

        visited[e.src].count(e.dst);
        int j = adj[e.dst][e.rev].id + 1;
        if (j >= adj[e.dst].size()) j = 0;
        e = adj[e.dst][j];
      } while (e.src != s.src || e.dst != s.dst);
      return in ? 2 : 0; // point in:out the polygon
    };
    for (int u = 0; u < n; ++u) 
      for (edge e: adj[u]) 
        if (!visited[e.src].count(e.dst)) 
          if (contains(e, (point){0,0})) return true;
    return false;
  }
};
int main() {
  for (int n; ~scanf("%d", &n) && n; ) {
    vector<segment> ss;
    for (int i = 0; i < n; ++i) {
      double x1, y1, x2, y2;
      scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
      ss.push_back({{x1,y1},{x2,y2}});
    }
    arrangement arr(ss);
    if (arr.traverse_all_faces3()) printf("yes\n");
    else                           printf("no\n");
  }
}

Measured memory_bytes: 5872