Problem:
Problem D: Area Separation

Mr. Yamada Springfield Tanaka は、国家区画整理事業局局長補佐代理という大任を任されていた。
現在、彼の国は大規模な区画整理の最中であり、この区画整理をスムーズに終わらせることができたならば彼の昇進は間違いなしであるとされている。

ところが、そんな彼の出世を快く思わない者も多くいるのだ。 そんな人間の 1 人に、Mr.Sato Seabreeze Suzuki がいた。
彼は、ことあるごとに Mr. Yamada の足を引っ張ろうと画策してきた。 今回も Mr. Sato は足を引っ張るために、実際の区画整理を担当している組織に圧力をかけて、区画整理の結果を非常に分かりにくいものにしてしまった。

そのため、Mr. Yamada に渡された結果は、 ある正方形の土地をどの直線で分割したかという情報のみになっていた。
最低限、その正方形の土地がいくつに分割されたかだけでも分からなければ、Mr. Yamada は昇進どころか解雇されること間違いなしである。

あなたの仕事は、(-100,-100)、(100,-100)、(100,100)、(-100,100) を頂点とする正方形領域が、与えられた n 本の直線によっていくつに分割されているかを調べるプログラムを書いて、Mr. Yamada を解雇の危機から救うことである。

Input

入力は複数のテストケースからなる。

それぞれのテストケースの最初の行では、直線数を表す整数 n が与えられる（1 <= n <= 100）。 その後の n 行にはそれぞれ 4 つの整数 x1 、y1 、 x2 、y2 が含まれる。
これらの整数は直線上の相異なる 2 点 (x1 , y1 ) と (x2 , y2 ) を表す。
与えられる 2 点は常に正方形の辺上の点であることが保証されている。 与えられる n 本の直線は互いに異なり、直線同士が重なることはない。 また、直線が正方形の辺と重なることもない。

入力の終了は n = 0 で表される。

Output

それぞれのテストケースについて、n 本の直線によって分割された領域の数を 1 行で出力せよ。

なお、距離が 10-10 未満の 2 点は一致するとみなしてよい。 また、|PQ| < 10-10、|QR| < 10-10 でかつ |PR| >= 10-10となるような交点の組 P、Q、R は存在しない。

Sample Input

2
-100 -20 100 20
-20 -100 20 100
2
-100 -20 -20 -100
20 100 100 20
0

Output for the Sample Input

4
3

Solution in C++ (judge verdict: Accepted)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstring>
#include<stack>
using namespace std;
#define EPS 1e-10

struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x=_x; y=_y;
    }
    Point operator +(const Point p)const{
        return Point(x+p.x,y+p.y);
    }
    Point operator -(const Point p)const{
        return Point(x-p.x,y-p.y);
    }
	Point operator *(const double d)const{
		return Point(x*d,y*d);
	}
};

struct Line{
    Point a,b;
    Line(){}
    Line(Point _a,Point _b){
        a=_a; b=_b;
    }
};

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-q.x*p.y;
}

int ccw(Point a,Point b,Point c){
    if(cross(b-a,c-b)>0) return +1;
    if(cross(b-a,c-b)<0) return -1;
    return 0;
}

bool intersect_ss(Line l,Line m) {
    return ccw(l.a,m.a,l.b)*ccw(l.a,m.b,l.b)<=0 && ccw(m.a,l.a,m.b)*ccw(m.a,l.b,m.b)<=0;
}

bool crosspoint_ll(Line l,Line m,Point &p){
    Point a1,a2,b1,b2;
	a1 = l.b-l.a; a2 = m.b-m.a;
	b1 = m.a-l.a; b2 = m.b-l.a;
	double s1,s2;
	s1 = abs(cross(a1,b1)/2); s2 = abs(cross(a1,b2)/2);
	if(s1<EPS && s2<EPS) return false;
	p = Point(m.a.x+a2.x*s1/(s1+s2),m.a.y+a2.y*s1/(s1+s2));
	return true;
}

bool crosspoint_ss(Line l,Line m,Point &p){
    if(intersect_ss(l,m)==false) return false;
	return crosspoint_ll(l,m,p);
}

int main(){
    int N;
    Line l[100];
    while(cin>>N,N){
        int ans=1;
        for(int i=0;i<N;i++){
            cin>>l[i].a.x>>l[i].a.y>>l[i].b.x>>l[i].b.y;
			vector<Point> cp;
			int cnt=1;
			for(int j=0;j<i;j++){
				Point p;
                if(crosspoint_ss(l[i],l[j],p)==true &&
				   abs(p.x-100)>=EPS && abs(p.x+100)>=EPS &&
				   abs(p.y-100)>=EPS && abs(p.y+100)>=EPS){
					cnt++;
					for(int k=0;k<cp.size();k++){
						if(abs(p.x-cp[k].x)<EPS && abs(p.y-cp[k].y)<EPS){
							cnt--; break;
						}
					}
					cp.push_back(p);
				}
            }
			ans += cnt;
        }
        printf("%d\n",ans);
    }
    return 0;
}