1. 程式人生 > >boj 35 Video Surveillance 半平面交求多邊形的核

boj 35 Video Surveillance 半平面交求多邊形的核

//============================================================================
// Name        : 35.cpp
// Author      : wly
// Version     :
// Copyright   : Your copyright notice
// Description : Video Surveillance
// Algorithm   : 求多邊形的核
//				 計算幾何,半平面交求多邊形的核
//				 http://blog.csdn.net/accry/article/details/6070621
//				 半平面交找核思想:
//				 對多邊形的每一條邊,這條邊所在的直線都可以將平面分成兩塊,求一條邊劃分的半平面與之前得出的多邊形的交,
//				 得出的多邊形再與下一條邊的半平面求交,依次類推,最後得到的多邊形就是原多邊形的核
//============================================================================


#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
using namespace std;
const double MAX = 100000000;
const double pi = acos(-1.0);
const double eps = 1e-8;
int cCnt, curCnt, n;
//點結構
struct Point {
	double x, y;
	Point(double ix, double iy) :
		x(ix), y(iy) {
	}
	Point() {
	}
	void input() {
		scanf("%lf%lf", &x, &y);
	}
} points[110], p[110], q[110];
//將兩點確定的直線量化
inline void getline(Point x, Point y, double &a, double &b, double &c) {
	a = y.y - x.y;
	b = x.x - y.x;
	c = y.x * x.y - x.x * y.y;
}

int sig(double k) {
	return (k < -eps) ? -1 : (k > eps);
}
//x點y點的連線與量化後的直線求交點
void interect(Point x, Point y, double a, double b, double c) {
	double u = fabs(a * x.x + b * x.y + c);
	double v = fabs(a * y.x + b * y.y + c);
	q[++curCnt].x = (x.x * v + y.x * u) / (u + v);
	q[curCnt].y = (x.y * v + y.y * u) / (u + v);
}

//利用半平面切割
void cut(double a, double b, double c) {
	curCnt = 0;
	int i;
	for (i = 1; i <= cCnt; i++) //遍歷所有頂點是否能觀察到該邊
	{
		if (sig(a * p[i].x + b * p[i].y + c) >= 0)//因為線段是順時針給出的,如果是逆時針就是<=0
		{
			q[++curCnt] = p[i]; //若是則儲存
		} else {
			if (sig(a * p[i - 1].x + b * p[i - 1].y + c) > 0)//逆時針就是<0
				interect(p[i - 1], p[i], a, b, c);
			if (sig(a * p[i + 1].x + b * p[i + 1].y + c) > 0)//逆時針就是<0
				interect(p[i + 1], p[i], a, b, c);
		}
	}
	//最後的p陣列存放半平面的點集合
	for (i = 1; i <= curCnt; i++)
		p[i] = q[i];
	p[curCnt + 1] = p[1], p[0] = p[curCnt];
	cCnt = curCnt;
}
//半平面交初始化
inline void initial() {
	for (int i = 1; i <= n; ++i)
		p[i] = points[i];
	points[n + 1] = points[1];
	p[n + 1] = p[1];
	p[0] = p[n];
	cCnt = n;
}
//輸入
inline void init() {
	for (int i = 1; i <= n; i++)
		points[i].input();
}
//獲得多邊形的核,結果存在p陣列中,如果沒有結果,p陣列長度為0
inline void solve() {
	initial();
	for (int i = 1; i <= n; ++i) {
		double a, b, c;
		getline(points[i], points[i + 1], a, b, c);
		cut(a, b, c);
	}
	//多邊形核的面積
	/*double area = 0;
	for (int i = 1; i <= curCnt; ++i)
		area += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y;
	area = fabs(area / 2.0);*/
}

int main() {
	int tc = 1;
	while (scanf("%d", &n), n) {
		init();
		solve();
		printf("Floor #%d\n", tc++);
		if (!cCnt)
			puts("Surveillance is impossible.");//這裡如果有一個點,或者一條線段都可以,所以判斷m是不是等於0就行了,不用判斷面積
		else
			puts("Surveillance is possible.");
		printf("\n");
	}
	return 0;
}