Problem:
Problem E: Safe Area

Nathan O. Davis is challenging a kind of shooter game. In this game, enemies emit laser beams
from outside of the screen. A laser beam is a straight line with a certain thickness. Nathan
moves a circular-shaped machine within the screen, in such a way it does not overlap a laser
beam. As in many shooters, the machine is destroyed when the overlap happens.

Nathan is facing an uphill stage. Many enemies attack simultaneously in this stage, so eventually
laser beams fill out almost all of the screen. Surprisingly, it is even possible he has no "safe area" on the screen. In other words, the machine cannot survive wherever it is located in some
cases.

The world is as kind as it is cruel! There is a special item that helps the machine to survive
any dangerous situation, even if it is exposed in a shower of laser beams, for some seconds. In
addition, another straight line (called "a warning line") is drawn on the screen for a few seconds
before a laser beam is emit along that line.

The only problem is that Nathan has a little slow reflexes. He often messes up the timing to
use the special item. But he knows a good person who can write a program to make up his slow
reflexes - it's you! So he asked you for help.

Your task is to write a program to make judgement whether he should use the item or not, for
given warning lines and the radius of the machine.

Input

The input is a sequence of datasets. Each dataset corresponds to one situation with warning
lines in the following format:

W H N R

x1,1 y1,1 x1,2 y1,2 t1

x2,1 y2,1 x2,2 y2,2 t2

...

xN,1 yN,1 xN,2 yN,2 tN

The first line of a dataset contains four integers W, H, N and R (2 < W ≤ 640, 2 < H ≤ 480,
0 ≤ N ≤ 100 and 0 < R < min{W, H}/2). The first two integers W and H indicate the width
and height of the screen, respectively. The next integer N represents the number of laser beams.

The last integer R indicates the radius of the machine. It is guaranteed that the output would
remain unchanged if the radius of the machine would become larger by 10-5 than R.

The following N lines describe the N warning lines. The (i+1)-th line of the dataset corresponds
to the i-th warning line, which is represented as a straight line which passes through two given
different coordinates (xi,1, yi,1 ) and (xi,2 , yi,2 ). The last integer ti indicates the thickness of the
laser beam corresponding to the i-th warning line.

All given coordinates (x, y) on the screen are a pair of integers (0 ≤ x ≤ W, 0 ≤ y ≤ H). Note
that, however, the machine is allowed to be located at non-integer coordinates during the play.

The input is terminated by a line with four zeros. This line should not be processed.

Output

For each case, print "Yes" in a line if there is a safe area, or print "No" otherwise.

Sample Input

100 100 1 1
50 0 50 100 50
640 480 1 1
0 0 640 480 100
0 0 0 0

Output for the Sample Input

No
Yes

Solution in C++14 (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;

#define rep(i,n) for(int i=0,i##_cond=(n);i<i##_cond;++i)
#define FOR(i,a,b) for(int i=(a),i##_cond=(b);i<i##_cond;++i)

const double EPS = 1e-8;
// 点
typedef complex<double> P;
namespace std {
  bool isnan(const P&p){
    return isnan(p.real()) or isnan(p.imag());
  }
}

// 外積
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
// 内積
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}

// 直線
// 線分は端点を入れる
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
};

// 円
struct C {
  P p; double r;
  C(const P &p_, double r_) : p(p_), r(r_) { }
};

// 交差判定
// 直線同士
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
    abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}

// 直線の交点
P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) return P(nan(""),nan("")); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

// 点の線への射影
P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}

// 直線と点の距離
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

// 直線lを垂線方向にdis移動
L slideL(L l, double dis){
  double deg = arg(l[1]-l[0]);
  P p = P(dis*sin(deg),-dis*cos(deg));
  l[0] += p;
  l[1] += p;
  return l;
}

signed main(){
  int n;
  double w,h,r;
  while(cin >> w >> h >> n >> r, n){
    // input
    vector<L> ls;
    vector<double> ts(n);
    rep(i,n){
      double a,b,c,d;
      cin >> a >> b >> c >> d;
      P x{a,b},y{c,d};
      ls.emplace_back(x,y);
      cin >> ts[i];
    }

    // 候補を列挙
    vector<P> can;
    // 四隅を追加
    can.push_back({r,r});
    can.push_back({r,h-r});
    can.push_back({w-r,r});
    can.push_back({w-r,h-r});
    // 2線に接する点を追加
    rep(i,n) FOR(j,i+1,n){
      // 交差しない
      if(not intersectLL(ls[i],ls[j])) continue;

      // 元の直線からr+t平行移動した直線l,rを用意
      // 交点が候補の候補となる
      L li = slideL(ls[i],-r-ts[i]), ri = slideL(ls[i],r+ts[i]);
      L lj = slideL(ls[j],-r-ts[j]), rj = slideL(ls[j],r+ts[j]);
      vector<P> tmpcan;
      tmpcan.push_back(crosspoint(li,lj));
      tmpcan.push_back(crosspoint(li,rj));
      tmpcan.push_back(crosspoint(ri,lj));
      tmpcan.push_back(crosspoint(ri,rj));

      // 枠の中にあるなら候補
      auto isin = [&](const P &p){
	return r < p.real()+EPS and p.real()-EPS < w-r and r < p.imag()+EPS and p.imag()-EPS < h-r;
      };
      rep(k,4){
	if((not isnan(tmpcan[k])) and isin(tmpcan[k]))
	  can.push_back(tmpcan[k]);
      }
    }

    // 各候補が全ての線からr+t以上離れているか
    bool f = false;
    rep(i,can.size()){
      bool g = true;
      rep(j,n){
	double d = distanceLP(ls[j],can[i]);
	if(r + ts[j] > d + EPS){
	  g = false;
	  break;
	}
      }
      if(g){
	f = true;
	break;
      }
    }
    if(f) cout << "Yes" << endl;
    else cout << "No" << endl;
  }
}