OJ-Problems-Source/.ACM-Templates/TXTs/计算几何.txt

1394 lines
41 KiB
Plaintext
Raw Normal View History

2016-11-22 09:38:35 +08:00
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>СԲ<D0A1><D4B2><EFBFBD><EFBFBD>
//Բ<><D4B2>ΪO, <20>뾶ΪR
double R, EPS = 1e-9;
struct Point { double x, y; } a[N], O;
inline double dis(Point x, Point y) { return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y)); }
Point center(Point x, Point y, Point z) {
double a1 = y.x - x.x, a2 = z.x - x.x, b1 = y.y - x.y, b2 = z.y - x.y,
c1 = (a1 * a1 + b1 * b1) / 2, c2 = (a2 * a2 + b2 * b2) / 2,
d = a1 * b2 - a2 * b1;
return (Point) {x.x + (c1 * b2 - c2 * b1) / d, x.y + (a1 * c2 - a2 * c1) / d};
}
void cal(int n, Point b[]) {
O = a[0]; R = 0;
for (int i = 0; i < n; i++) { a[i] = b[i]; }
for (int i = 0; i < n; i++) { swap(a[rand() % n], a[i]); }
for (int i = 1; i < n; i++) {
if (dis(a[i], O) > R + EPS) {
O = a[i]; R = 0;
for (int j = 0; j < i; j++) {
if (dis(a[j], O) > R + EPS) {
O = (Point) {(a[i].x + a[j].x) / 2, (a[i].y + a[j].y) / 2}, R = dis(O, a[i]);
for (int k = 0; k < j; k++) {
if (dis(a[k], O) > R + EPS) { O = center(a[k], a[j], a[i]), R = dis(O, a[i]); }
}
}
}
}
}
}
//kuangbin
//1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//1.1 Point <20><><EFBFBD><EFBFBD>
const double PI = acos(-1.0);
const double EPS = 1e-8;
inline int sgn(double x) {
return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1));
}
struct Point {
double x, y;
Point() {}
Point(double _x, double _y): x(_x), y(_y) {}
Point operator-(const Point &b)const {
return Point(x - b.x, y - b.y);
}
//<2F><><EFBFBD><EFBFBD>
double operator^(const Point &b)const {
return x * b.y - y * b.x;
}
//<2F><><EFBFBD><EFBFBD>
double operator*(const Point &b)const {
return x * b.x + y * b.y;
}
//<2F><>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>ת<EFBFBD>Ƕ<EFBFBD>B(<28><><EFBFBD><EFBFBD>ֵ), <20><>x, y<>ı
void transXY(double B) {
double tx = x, ty = y;
x = tx * cos(B) - ty * sin(B);
y = tx * sin(B) + ty * cos(B);
}
};
//1.2 Line <20><><EFBFBD><EFBFBD>
struct Line {
Point s, e;
Line() {}
Line(Point _s, Point _e): s(_s), e(_e) {}
//<2F><>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>󽻵<EFBFBD>
//<2F><>һ<EFBFBD><D2BB>ֵΪ0<CEAA><30>ʾֱ<CABE><D6B1><EFBFBD>غ<EFBFBD>, Ϊ1<CEAA><31>ʾƽ<CABE><C6BD>, Ϊ0<CEAA><30>ʾ<EFBFBD>ཻ, Ϊ2<CEAA><32><EFBFBD>
//ֻ<>е<EFBFBD>һ<EFBFBD><D2BB>ֵΪ2ʱ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pair<int, Point> operator&(const Line &b)const {
Point res = s;
if (sgn((s - e) ^ (b.s - b.e)) == 0) {
if (sgn((s - b.e) ^ (b.s - b.e)) == 0) { return make_pair(0, res); } //<2F>غ<EFBFBD>
else { return make_pair(1, res); } //ƽ<><C6BD>
}
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(2, res);
}
};
//1.3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double dist(const Point &a, const Point &b) {
return sqrt((a - b) * (a - b));
}
//1.4 <20>ж<EFBFBD>: <20>߶<EFBFBD><DFB6>
//*<2A>ж<EFBFBD><D0B6>߶<EFBFBD><DFB6>
bool inter(const Line &l1, const Line &l2) {
return max(l1.s.x, l1.e.x) >= min(l2.s.x, l2.e.x)
&& max(l2.s.x, l2.e.x) >= min(l1.s.x, l1.e.x)
&& max(l1.s.y, l1.e.y) >= min(l2.s.y, l2.e.y)
&& max(l2.s.y, l2.e.y) >= min(l1.s.y, l1.e.y)
&& sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) <= 0
&& sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e-l2.e) ^ (l2.s - l2.e)) <= 0;
}
//1.5 <20>жϣ<D0B6>ֱ<EFBFBD>ߺ<EFBFBD><DFBA>߶<EFBFBD><DFB6>
//<2F>ж<EFBFBD>ֱ<EFBFBD>ߺ<EFBFBD><DFBA>߶<EFBFBD><DFB6>
bool Seg_inter_line(const Line &l1, const Line &l2) { //<2F>ж<EFBFBD>ֱ<EFBFBD><D6B1>l1<6C><31><EFBFBD>߶<EFBFBD>l2<6C>Ƿ<EFBFBD><C7B7>
return sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) <= 0;
}
//1.6 <20>㵽ֱ<E3B5BD>߾<EFBFBD><DFBE><EFBFBD>
//<2F>㵽ֱ<E3B5BD>߾<EFBFBD><DFBE><EFBFBD>
//<2F><><EFBFBD><EFBFBD>Ϊresult, <20>ǵ㵽ֱ<E3B5BD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
Point PointToLine(const Point &P, const Line &L) {
double t = ((P - L.s) * (L.e-L.s)) / ((L.e - L.s) * (L.e - L.s));
return Point(L.s.x + (L.e.x - L.s.x) * t, L.s.y + (L.e.y - L.s.y) * t);
}
//1.7 <20><EFBFBD>߶ξ<DFB6><CEBE><EFBFBD>
//<2F><EFBFBD>߶εľ<CEB5><C4BE><EFBFBD>
//<2F><><EFBFBD>ص㵽<D8B5>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
Point NearestPointToLineSeg(const Point &P, const Line &L) {
double t = ((P - L.s) * (L.e-L.s)) / ((L.e-L.s) * (L.e-L.s));
Point result;
if (t >= 0 && t <= 1) {
result.x = L.s.x + (L.e.x - L.s.x) * t;
result.y = L.s.y + (L.e.y - L.s.y) * t;
} else {
if (dist(P, L.s) < dist(P, L.e)) { result = L.s; }
else { result = L.e; }
}
return result;
}
//1.8 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>ı<EFBFBD><C4B1>Ŵ<EFBFBD>0 ~ n - 1
double CalcArea(Point p[], int n) {
double res = 0;
for (int i = 0; i < n; i++) {
res += (p[i] ^ p[(i + 1) % n]) * 0.5;
}
return fabs(res);
}
//1.9 <20>жϵ<D0B6><CFB5><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD>
//*<2A>жϵ<D0B6><CFB5><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD>
bool OnSeg(const Point &P, const Line &L) {
return sgn((L.s - P) ^ (L.e-P)) == 0
&& sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0
&& sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
//1.10 <20>жϵ<D0B6><CFB5><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//*<2A>жϵ<D0B6><CFB5><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>γ<EFBFBD>һ<EFBFBD><D2BB>͹<EFBFBD><CDB9>, <20><><EFBFBD>Ұ<EFBFBD><D2B0><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳ʱ<CBB3><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><0<><30>Ϊ>0)
//<2F><><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>:0 ~ n - 1
//<2F><><EFBFBD><EFBFBD>ֵ:
//-1:<3A><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//0:<3A><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD>α߽<CEB1><DFBD><EFBFBD>
//1:<3A><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int inConvexPoly(const Point &a, Point p[], int n) {
for (int i = 0; i < n; i++) {
if (sgn((p[i] - a) ^ (p[(i + 1) % n] - a)) < 0) { return -1; }
else if (OnSeg(a, Line(p[i], p[(i + 1) % n]))) { return 0; }
}
return 1;
}
//1.11 <20>жϵ<D0B6><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//*<2A>жϵ<D0B6><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>߷<EFBFBD>, poly[]<5D>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>3,<2C><><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>0~n-1
//<2F><><EFBFBD><EFBFBD>ֵ
//-1:<3A><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//0:<3A><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD>α߽<CEB1><DFBD><EFBFBD>
//1:<3A><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int inPoly(const Point &p, Point poly[], int n) {
int cnt = 0;
Line ray(p, Point(-100000000000.0, p.y)), side; //-INF,ע<><D7A2>ȡֵ<C8A1><D6B5>ֹԽ<D6B9><D4BD>
for (int i = 0; i < n; i++) {
side.s = poly[i];
side.e = poly[(i + 1) % n];
if (OnSeg(p, side)) { return 0; }
//<2F><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD>򲻿<EFBFBD><F2B2BBBF><EFBFBD>
if (sgn(side.s.y - side.e.y) == 0) { continue; }
if (OnSeg(side.s, ray)) {
if (sgn(side.s.y - side.e.y) > 0) { cnt++; }
} else if (OnSeg(side.e, ray)) {
if (sgn(side.e.y - side.s.y) > 0) { cnt++; }
} else if (inter(ray, side)) {
cnt++;
}
}
if (cnt & 1) { return 1; }
else { return -1; }
}
//1.12 <20>ж<EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F>ж<EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳ʱ<CBB3><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>1~n-1
bool isconvex(Point poly[], int n) {
bool s[3] = {0};
for (int i = 0; i < n; i++) {
s[sgn((poly[(i + 1) % n] - poly[i]) ^ (poly[(i + 2) % n] - poly[i])) + 1] = true;
if (s[0] && s[2]) { return false; }
}
return true;
}
//2<><32>͹<EFBFBD><CDB9>
/*
* <20><>͹<EFBFBD><CDB9>, Graham<61>
* <20><><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>0 ~ n - 1
* <20><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Stack[0 ~ top - 1]Ϊ͹<CEAA><CDB9><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
*/
const int N = 1010;
Point lst[N];
int Stack[N], top;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>lst[0]<5D>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool _cmp(const Point &p1, const Point &p2) {
double tmp = (p1 - lst[0]) ^ (p2 - lst[0]);
if (sgn(tmp) > 0) { return true; }
else if (sgn(tmp) == 0 && sgn(dist(p1, lst[0]) - dist(p2, lst[0])) <= 0) { return true; }
else { return false; }
}
void Graham(int n) {
Point p0 = lst[0];
int k = 0;
//<2F><><EFBFBD><EFBFBD><EFBFBD>±ߵ<C2B1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
for (int i = 1; i < n; i++) {
if ((p0.y > lst[i].y) || (p0.y == lst[i].y && p0.x > lst[i].x)) {
p0 = lst[i]; k = i;
}
}
swap(lst[k], lst[0]);
sort(lst + 1, lst + n, _cmp);
if (n == 1) {
top = 1;
Stack[0] = 0;
return;
}
if (n == 2) {
top = 2;
Stack[0] = 0;
Stack[1] = 1;
return ;
}
top = 2;
Stack[0] = 0;
Stack[1] = 1;
for (int i = 2; i < n; i++) {
while (top > 1 && sgn((lst[Stack[top - 1]] - lst[Stack[top - 2]]) ^ (lst[i] - lst[Stack[top - 2]])) <= 0) {
top--;
}
Stack[top++] = i;
}
}
//3<><33>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(HDU 1007)
const double EPS = 1e-6;
const double INF = 1e20;
const int N = 100005;
struct Point {
double x, y;
} p[N], tmpt[N];
double dist(const Point &a, const Point &b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
bool cmpxy(const Point &a, const Point &b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
bool cmpy(Point a, Point b) {
return a.y < b.y;
}
double Closest_Pair(int left, int right) {
double d = INF;
if (left == right) { return d; }
if (left + 1 == right) { return dist(p[left], p[right]); }
int mid = (left + right) / 2;
double d1 = Closest_Pair(left, mid);
double d2 = Closest_Pair(mid + 1, right);
d = min(d1, d2);
int k = 0;
for (int i = left; i <= right; i++) {
if (fabs(p[mid].x - p[i].x) <= d) {
tmpt[k++] = p[i];
}
}
sort(tmpt, tmpt + k, cmpy);
for (int i = 0; i < k; i++) {
for (int j = i + 1; j < k && tmpt[j].y - tmpt[i].y < d; j++) {
d = min(d, dist(tmpt[i], tmpt[j]));
}
}
return d;
}
int main() {
int n;
while (scanf("%d", &n) == 1 && n) {
for (int i = 0; i < n; i++) {
scanf("%lf%lf", &p[i].x, &p[i].y);
}
sort(p, p + n, cmpxy);
printf("%.2lf\n", Closest_Pair(0, n - 1) / 2);
}
}
//4<><34><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
//4.1 <20><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>(POJ 2187 Beauty Contest)
struct Point {
int x, y;
Point(int _x = 0, int _y = 0): x(_x), y(_y) {}
Point operator-(const Point &b)const {
return Point(x - b.x, y - b.y);
}
int operator^(const Point &b)const {
return x * b.y - y * b.x;
}
int operator*(const Point &b)const {
return x * b.x + y * b.y;
}
void input() {
scanf("%d%d", &x, &y);
}
};
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD>
int dist2(const Point &a, const Point &b) {
return (a - b) * (a - b);
}
//******<2A><>ά͹<CEAC><CDB9>, int***********
const int N = 50005;
Point lst[N], p[N];
int Stack[N], top;
bool _cmp(const Point &p1, const Point &p2) {
int tmp = (p1 - lst[0]) ^ (p2 - lst[0]);
if (tmp > 0) { return true; }
else if (tmp == 0 && dist2(p1, lst[0]) <= dist2(p2, lst[0])) { return true; }
else { return false; }
}
void Graham(int n) {
Point p0 = lst[0];
int k = 0;
for (int i = 1; i < n; i++) {
if (p0.y > lst[i].y || (p0.y == lst[i].y && p0.x > lst[i].x)) {
p0 = lst[i];
k = i;
}
}
swap(lst[k], lst[0]);
sort(lst + 1, lst + n, _cmp);
if (n == 1) {
top = 1;
Stack[0] = 0;
return;
}
if (n == 2) {
top = 2;
Stack[0] = 0; Stack[1] = 1;
return;
}
top = 2;
Stack[0] = 0;
Stack[1] = 1;
for (int i = 2; i < n; i++) {
while (top > 1 && ((lst[Stack[top - 1]] - lst[Stack[top - 2]]) ^ (lst[i] - lst[Stack[top - 2]])) <= 0) {
top--;
}
Stack[top++] = i;
}
}
//<2F><>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
int rotating_calipers(Point p[], int n) {
int ans = 0, cur = 1;
Point v;
for (int i = 0; i < n; i++) {
v = p[i] - p[(i + 1) % n];
while ((v ^ (p[(cur + 1) % n] - p[cur])) < 0) {
cur = (cur + 1) % n;
}
ans = max(ans, max(dist2(p[i], p[cur]), dist2(p[(i + 1) % n], p[(cur + 1) % n])));
}
return ans;
}
int main() {
int n;
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++) { lst[i].input(); }
Graham(n);
for (int i = 0; i < top; i++) { p[i] = lst[Stack[i]]; }
printf("%d\n", rotating_calipers(p, top));
}
}
//4.2 <20><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><E3BCAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><>ת<EFBFBD><D7AA><EFBFBD>Ǽ<EFBFBD><C7BC><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><E3BCAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Point lst[N], p[N];
int rotating_calipers(Point p[], int n) {
int ans = 0;
Point v;
for (int i = 0; i < n; i++) {
int j = (i + 1) % n, k = (j + 1) % n;
while (j != i && k != i) {
ans = max(ans, abs((p[j] - p[i]) ^ (p[k] - p[i])));
while (((p[i] - p[j]) ^ (p[(k + 1) % n] - p[k])) < 0) {
k = (k + 1) % n;
}
j = (j + 1) % n;
}
}
return ans;
}
int main() {
int n;
while (scanf("%d", &n) == 1) {
if (n == -1) { break; }
for (int i = 0; i < n; i++) { lst[i].input(); }
Graham(n);
for (int i = 0; i < top; i++) { p[i] = lst[Stack[i]]; }
printf("%.2f\n", rotating_calipers(p, top) / 2.0);
}
}
//4.3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>(POJ 3608)
const double EPS = 1e-8;
inline int sgn(double x) {
return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1));
}
struct Point {
double x, y;
Point() {}
Point(double _x = 0, double _y = 0): x(_x), y(_y) {}
Point operator-(const Point &b)const {
return Point(x - b.x, y - b.y);
}
//<2F><><EFBFBD><EFBFBD>
double operator^(const Point &b)const {
return x * b.y - y * b.x;
}
//<2F><><EFBFBD><EFBFBD>
double operator*(const Point &b)const {
return x * b.x + y * b.y;
}
void input() {
scanf("%lf%lf", &x, &y);
}
};
struct Line {
Point s, e;
Line() {}
Line(Point _s, Point _e): s(_s), e(_e) {}
};
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double dist(const Point &a, const Point &b) {
return sqrt((a - b) * (a - b));
}
//<2F><EFBFBD>߶εľ<CEB5><C4BE><EFBFBD>, <20><><EFBFBD>ص㵽<D8B5>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
Point NearestPointToLineSeg(const Point &P, const Line &L) {
double t = ((P - L.s) * (L.e-L.s)) / ((L.e-L.s) * (L.e-L.s));
Point result;
if (t >= 0 && t <= 1) {
result.x = L.s.x + (L.e.x - L.s.x) * t;
result.y = L.s.y + (L.e.y - L.s.y) * t;
} else {
if (dist(P, L.s) < dist(P, L.e)) { result = L.s; }
else { result = L.e; }
}
return result;
}
/*
* <20><>͹<EFBFBD><CDB9>, Graham<61>
* <20><><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>0~n-1
* <20><><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Stack[0~top-1]Ϊ͹<CEAA><CDB9><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
*/
const int N = 10005;
Point lst[N];
int Stack[N], top;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>list[0]<5D>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool _cmp(const Point &p1, const Point &p2) {
double tmp = (p1 - lst[0]) ^ (p2 - lst[0]);
if (sgn(tmp) > 0) { return true; }
else if (sgn(tmp) == 0 && sgn(dist(p1, lst[0]) - dist(p2, lst[0])) <= 0) { return true; }
else { return false; }
}
void Graham(int n) {
Point p0 = lst[0];
int k = 0;
//<2F><><EFBFBD><EFBFBD><EFBFBD>±ߵ<C2B1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
for (int i = 1; i < n; i++) {
if ((p0.y > lst[i].y) || (p0.y == lst[i].y && p0.x > lst[i].x)) {
p0 = lst[i];
k = i;
}
}
swap(lst[k], lst[0]);
sort(lst + 1, lst + n, _cmp);
if (n == 1) {
top = 1;
Stack[0] = 0;
return;
}
if (n == 2) {
top = 2;
Stack[0] = 0;
Stack[1] = 1;
return ;
}
top = 2;
Stack[0] = 0;
Stack[1] = 1;
for (int i = 2; i < n; i++) {
while (top > 1 && sgn((lst[Stack[top - 1]] - lst[Stack[top - 2]]) ^ (lst[i] - lst[Stack[top - 2]])) <= 0) {
top--;
}
Stack[top++] = i;
}
}
//<2F><>p0<70><30><EFBFBD>߶<EFBFBD>p1p2<70>ľ<EFBFBD><C4BE><EFBFBD>
double pointtoseg(const Point &p0, const Point &p1, const Point &p2) {
return dist(p0, NearestPointToLineSeg(p0, Line(p1, p2)));
}
//ƽ<><C6BD><EFBFBD>߶<EFBFBD>p0p1<70><31>p2p3<70>ľ<EFBFBD><C4BE><EFBFBD>
double dispallseg(const Point &p0, const Point &p1, const Point &p2, const Point &p3) {
double ans1 = min(pointtoseg(p0, p2, p3), pointtoseg(p1, p2, p3));
double ans2 = min(pointtoseg(p2, p0, p1), pointtoseg(p3, p0, p1));
return min(ans1, ans2);
}
//<2F>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>a1a2<61><32>b1b2<62><32>λ<EFBFBD>ù<EFBFBD>ϵ
double Get_angle(const Point &a1, const Point &a2, const Point &b1, const Point &b2) {
return (a2 - a1) ^ (b1 - b2);
}
double rotating_calipers(Point p[], int np, Point q[], int nq) {
int sp = 0, sq = 0;
for (int i = 0; i < np; i++) {
if (sgn(p[i].y - p[sp].y) < 0) { sp = i; }
}
for (int i = 0; i < nq; i++) {
if (sgn(q[i].y - q[sq].y) > 0) { sq = i; }
}
double ans = dist(p[sp], q[sq]), tmp;
for (int i = 0; i < np; i++) {
while (sgn(tmp = Get_angle(p[sp], p[(sp + 1) % np], q[sq], q[(sq + 1) % nq])) < 0) {
sq = (sq + 1) % nq;
}
if (sgn(tmp) == 0) {
ans = min(ans, dispallseg(p[sp], p[(sp + 1) % np], q[sq], q[(sq + 1) % nq]));
} else { ans = min(ans, pointtoseg(q[sq], p[sp], p[(sp + 1) % np])); }
sp = (sp + 1) % np;
}
return ans;
}
double solve(Point p[], int n, Point q[], int m) {
return min(rotating_calipers(p, n, q, m), rotating_calipers(q, m, p, n));
}
Point p[N], q[N];
int main() {
int n, m;
while (scanf("%d%d", &n, &m) == 2) {
if (n == 0 && m == 0) { break; }
for (int i = 0; i < n; i++) { lst[i].input(); }
Graham(n);
for (int i = 0; i < top; i++) { p[i] = lst[i]; }
n = top;
for (int i = 0; i < m; i++) { lst[i].input(); }
Graham(m);
for (int i = 0; i < top; i++) { q[i] = lst[i]; }
m = top;
printf("%.4f\n", solve(p, n, q, m));
}
}
//5<><35><EFBFBD><EFBFBD>ƽ<EFBFBD>
//5.1 <20><>ƽ<EFBFBD>潻ģ<E6BDBB><C4A3>(from UESTC)
const double PI = acos(-1.0);
const double EPS = 1e-8;
const int N = 105;
inline int sgn(double x) {
return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1));
}
struct Point {
double x, y;
Point() {}
Point(double _x, double _y): x(_x), y(_y) {}
Point operator-(const Point &b)const {
return Point(x - b.x, y - b.y);
}
double operator^(const Point &b)const {
return x * b.y - y * b.x;
}
double operator*(const Point &b)const {
return x * b.x + y * b.y;
}
};
struct Line {
Point s, e;
double k;
Line() {}
Line(Point _s, Point _e): s(_s), e(_e), k(atan2(e.y - s.y, e.x - s.x)) {}
Point operator&(const Line &b)const {
Point res = s;
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return res;
}
};
//<2F><>ƽ<EFBFBD>潻, ֱ<>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD>ߴ<EFBFBD><DFB4><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
bool HPIcmp(const Line &a, const Line &b) {
if (fabs(a.k - b.k) > EPS) { return a.k < b.k; }
return ((a.s - b.s) ^ (b.e - b.s)) < 0;
}
Line Q[N];
void HPI(Line line[], int n, Point res[], int &resn) {
int tot = 1;
sort(line, line + n, HPIcmp);
for (int i = 1; i < n; i++) {
if (fabs(line[i].k - line[i - 1].k) > EPS) { line[tot++] = line[i]; }
}
int head = 0, tail = 1;
Q[0] = line[0]; Q[1] = line[1];
resn = 0;
for (int i = 2; i < tot; i++) {
if (fabs((Q[tail].e-Q[tail].s) ^ (Q[tail - 1].e-Q[tail - 1].s)) < EPS
|| fabs((Q[head].e-Q[head].s) ^ (Q[head + 1].e-Q[head + 1].s)) < EPS) {
return;
}
while (head < tail
&& (((Q[tail]&Q[tail - 1]) - line[i].s) ^ (line[i].e-line[i].s)) > EPS) {
tail--;
}
while (head < tail
&& (((Q[head]&Q[head + 1]) - line[i].s) ^ (line[i].e-line[i].s)) > EPS) {
head++;
}
Q[++tail] = line[i];
}
while (head < tail
&& (((Q[tail]&Q[tail - 1]) - Q[head].s) ^ (Q[head].e-Q[head].s)) > EPS) {
tail--;
}
while (head < tail
&& (((Q[head]&Q[head - 1]) - Q[tail].s) ^ (Q[tail].e-Q[tail].e)) > EPS) {
head++;
}
if (tail <= head + 1) { return; }
for (int i = head; i < tail; i++) {
res[resn++] = Q[i] & Q[i + 1];
}
if (head < tail - 1) {
res[resn++] = Q[head] & Q[tail];
}
}
//5.2 <20><>ͨ<EFBFBD><CDA8>ƽ<EFBFBD>潻д<E6BDBB><D0B4>
//POJ 1750
const double EPS = 1e-18;
const double INF = 100000000000.0;
const int N = 105;
inline int sgn(double x) {
return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1));
}
struct Point {
double x, y;
Point() {}
Point(double _x, double _y): x(_x), y(_y) {}
Point operator-(const Point &b)const {
return Point(x - b.x, y - b.y);
}
double operator^(const Point &b)const {
return x * b.y - y * b.x;
}
double operator*(const Point &b)const {
return x * b.x + y * b.y;
}
};
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double CalcArea(Point p[], int n) {
double res = 0;
for (int i = 0; i < n; i++) {
res += (p[i] ^ p[(i + 1) % n]);
}
return fabs(res / 2);
}
//ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ȷ<><C8B7>ֱ<EFBFBD>߷<EFBFBD><DFB7><EFBFBD>
void Get_equation(const Point &p1, const Point &p2, double &a, double &b, double &c) {
a = p2.y - p1.y;
b = p1.x - p2.x;
c = p2.x * p1.y - p1.x * p2.y;
}
//<2F>󽻵<EFBFBD>
Point Intersection(const Point &p1, const Point &p2, double a, double b, double c) {
double u = fabs(a * p1.x + b * p1.y + c);
double v = fabs(a * p2.x + b * p2.y + c);
return Point((p1.x * v + p2.x * u) / (u + v), (p1.y * v + p2.y * u) / (u + v));
}
Point tp[N];
void Cut(double a, double b, double c, Point p[], int &cnt) {
int tmp = 0;
for (int i = 1; i <= cnt; i++) {
//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>ʱ<EFBFBD><CAB1><EFBFBD>ĵ<EFBFBD>
if (a * p[i].x + b * p[i].y + c < EPS) { tp[++tmp] = p[i]; }
else {
if (a * p[i - 1].x + b * p[i - 1].y + c < -EPS) {
tp[++tmp] = Intersection(p[i - 1], p[i], a, b, c);
}
if (a * p[i + 1].x + b * p[i + 1].y + c < -EPS) {
tp[++tmp] = Intersection(p[i], p[i + 1], a, b, c);
}
}
}
for (int i = 1; i <= tmp; i++) { p[i] = tp[i]; }
p[0] = p[tmp];
p[tmp + 1] = p[1];
cnt = tmp;
}
double V[N], U[N], W[N];
int n;
Point p[N];
bool solve(int id) {
p[1] = Point(0, 0);
p[2] = Point(INF, 0);
p[3] = Point(INF, INF);
p[4] = Point(0, INF);
p[0] = p[4];
p[5] = p[1];
int cnt = 4;
for (int i = 0; i < n; i++) {
if (i != id) {
double a = (V[i] - V[id]) / (V[i] * V[id]);
double b = (U[i] - U[id]) / (U[i] * U[id]);
double c = (W[i] - W[id]) / (W[i] * W[id]);
if (sgn(a) == 0 && sgn(b) == 0) {
if (sgn(c) >= 0) { return false; }
else { continue; }
}
Cut(a, b, c, p, cnt);
}
}
if (sgn(CalcArea(p, cnt)) == 0) { return false; }
else { return true; }
}
int main() {
while (scanf("%d", &n) == 1) {
for (int i = 0; i < n; i++) {
scanf("%lf%lf%lf", &V[i], &U[i], &W[i]);
}
for (int i = 0; i < n; i++) {
if (solve(i)) { printf("Yes\n"); }
else { printf("No\n"); }
}
}
}
//6<><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Point waixin(const Point &a, const Point &b, const Point &c) {
double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1 * a1 + b1 * b1) / 2;
double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2 * a2 + b2 * b2) / 2;
double d = a1 * b2 - a2 * b1;
return Point(a.x + (c1 * b2 - c2 * b1) / d, a.y + (a1 * c2 - a2 * c1) / d);
}
//7<><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><E0BDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>Բ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double Area_of_overlap(const Point &c1, double r1, const Point &c2, double r2) {
double d = dist(c1, c2);
if (r1 + r2 < d + EPS) { return 0; }
if (d < fabs(r1 - r2) + EPS) {
double r = min(r1, r2);
return PI * r * r;
}
double x = (d * d + r1 * r1 - r2 * r2) / (2 * d);
double t1 = acos(x / r1);
double t2 = acos((d - x) / r2);
return r1 * r1 * t1 + r2 * r2 * t2 - d * r1 * sin(t1);
}
//8<><38>Pick <20><>ʽ
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ򵥶<C4BC><F2B5A5B6><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD> = <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ + <20><><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD><EFBFBD>Ŀ / 2 - 1
//http://www.cppblog.com/abilitytao/archive/2009/08/04/92171.html
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const double M_PI = acos(-1.0); //PI
const double INF = 1e10; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const double EPS = 1e-8; //<2F><><EFBFBD><EFBFBD><E3BEAB>
const int LEFT = 0; //<2F><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const int RIGHT = 1; //<2F><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>ұ<EFBFBD>
const int ONLINE = 2; //<2F><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>
const int CROSS = 0; //<2F><>ֱ<EFBFBD><D6B1><EFBFBD>
const int COLINE = 1; //<2F><>ֱ<EFBFBD>߹<EFBFBD><DFB9><EFBFBD>
const int PARALLEL = 2; //<2F><>ֱ<EFBFBD><D6B1>ƽ<EFBFBD><C6BD>
const int NOTCOPLANAR = 3; //<2F><>ֱ<EFBFBD>߲<EFBFBD><DFB2><EFBFBD><EFBFBD><EFBFBD>
const int INSIDE = 1; //<2F><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ڲ<EFBFBD>
const int OUTSIDE = 2; //<2F><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ⲿ
const int BORDER = 3; //<2F><><EFBFBD><EFBFBD>ͼ<EFBFBD>α߽<CEB1>
const int BAOHAN = 1; //<2F><>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD>СԲ
const int NEIQIE = 2; //<2F><><EFBFBD><EFBFBD>
const int XIANJIAO = 3; //<2F>
const int WAIQIE = 4; //<2F><><EFBFBD><EFBFBD>
const int XIANLI = 5; //<2F><><EFBFBD><EFBFBD>
///////////////////////////////////////////////////////////////////
//<2F><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>
struct Point { //<2F><>ά<EFBFBD><CEAC><EFBFBD><EFBFBD>ʸ<EFBFBD><CAB8>
double x, y;
double angle, dis;
Point(): x(0), y(0), angle(0), dis(0) {}
Point(double x0, double y0): x(x0), y(y0), angle(0), dis(0) {}
};
struct Point3D { //<2F><>ά<EFBFBD><CEAC><EFBFBD><EFBFBD>ʸ<EFBFBD><CAB8>
double x, y, z;
Point3D(): x(0), y(0), z(0) {}
Point3D(double x0, double y0, double z0): x(x0), y(y0), z(z0) {}
};
struct Line { //<2F><>ά<EFBFBD><CEAC>ֱ<EFBFBD>߻<EFBFBD><DFBB>߶<EFBFBD>
Point p1, p2;
Line(): p1(), p2() {}
Line(Point p10, Point p20): p1(p10), p2(p20) {}
};
struct Line3D { //<2F><>ά<EFBFBD><CEAC>ֱ<EFBFBD>߻<EFBFBD><DFBB>߶<EFBFBD>
Point3D p1, p2;
Line3D(): p1(), p2() {}
Line3D(Point3D p10, Point3D p20): p1(p10), p2(p20) {}
};
struct Rect { //<2F>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>εķ<CEB5><C4B7><EFBFBD> w, h<>ֱ<EFBFBD><D6B1><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>Ⱥ͸߶<CDB8>
double w, h;
Rect(): w(0), h(0) {}
Rect(double _w, double _h) : w(_w), h(_h) {}
};
struct Rect_2 { //<2F><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>, <20><><EFBFBD>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(xl, yl), <20><><EFBFBD>Ͻ<EFBFBD><CFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(xh, yh)
double xl, yl, xh, yh;
Rect_2(): xl(0), yl(0), xh(0), yh(0) {}
Rect_2(double _xl, double _yl, double _xh, double _yh) : xl(_xl), yl(_yl), xh(_xh), yh(_yh) {}
};
struct Circle { //Բ
Point c;
double r;
Circle(): c(), r(0) {}
Circle(Point _c, double _r) : c(_c), r(_r) {}
};
typedef vector<Point> Polygon; //<2F><>ά<EFBFBD><CEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
typedef vector<Point> Points; //<2F><>ά<EFBFBD>
typedef vector<Point3D> Points3D; //<2F><>ά<EFBFBD>
///////////////////////////////////////////////////////////////////
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
inline bool ZERO(double x) { //x == 0
return (fabs(x) < EPS);
}
inline bool ZERO(Point p) { //p == 0
return (ZERO(p.x) && ZERO(p.y));
}
inline bool ZERO(Point3D p) { //p == 0
return (ZERO(p.x) && ZERO(p.y) && ZERO(p.z));
}
inline bool EQ(double x, double y) { //eqaul, x == y
return (fabs(x - y) < EPS);
}
inline bool NEQ(double x, double y) { //not equal, x != y
return (fabs(x - y) >= EPS);
}
inline bool LT(double x, double y) { //less than, x < y
return (NEQ(x, y) && (x < y));
}
inline bool GT(double x, double y) { //greater than, x > y
return (NEQ(x, y) && (x > y));
}
inline bool LEQ(double x, double y) { //less equal, x <= y
return (EQ(x, y) || (x < y));
}
inline bool GEQ(double x, double y) { //greater equal, x >= y
return (EQ(x, y) || (x > y));
}
//ע<><EFBFBD><E2A3A1><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>С<EFBFBD>ĸ<EFBFBD><C4B8>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Чλ<D0A7><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-0.000<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ,
//ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>ͻᵼ<CDBB>´<EFBFBD><C2B4>󣡣<EFBFBD><F3A3A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ, һ<><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>ôκ<C3B4><CEBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
inline double FIX(double x) {
return (fabs(x) < EPS) ? 0 : x;
}
/////////////////////////////////////////////////////////////////////////////////////
//<2F><>άʸ<CEAC><CAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool operator==(Point p1, Point p2) {
return (EQ(p1.x, p2.x) && EQ(p1.y, p2.y));
}
bool operator!=(Point p1, Point p2) {
return (NEQ(p1.x, p2.x) || NEQ(p1.y, p2.y));
}
bool operator<(Point p1, Point p2) {
if (NEQ(p1.x, p2.x)) { return (p1.x < p2.x); }
else { return (p1.y < p2.y); }
}
Point operator+(Point p1, Point p2) {
return Point(p1.x + p2.x, p1.y + p2.y);
}
Point operator-(Point p1, Point p2) {
return Point(p1.x - p2.x, p1.y - p2.y);
}
double operator*(Point p1, Point p2) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> p1 <20><> p2
return (p1.x * p2.y - p2.x * p1.y);
}
double operator&(Point p1, Point p2) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> p1<70><31>p2
return (p1.x * p2.x + p1.y * p2.y);
}
double Norm(Point p) { //<2F><><EFBFBD><EFBFBD>ʸ<EFBFBD><CAB8>p<EFBFBD><70>ģ
return sqrt(p.x * p.x + p.y * p.y);
}
//<2F><>ʸ<EFBFBD><CAB8>p<EFBFBD><70>ת<EFBFBD>Ƕ<EFBFBD>angle (<28><><EFBFBD>ȱ<EFBFBD>ʾ)
//angle > 0<><30>ʾ<EFBFBD><CABE>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ת
//angle < 0<><30>ʾ˳ʱ<CBB3><CAB1><EFBFBD><EFBFBD>ת
Point Rotate(Point p, double angle) {
Point result;
result.x = p.x * cos(angle) - p.y * sin(angle);
result.y = p.x * sin(angle) + p.y * cos(angle);
return result;
}
//////////////////////////////////////////////////////////////////////////////////////
//<2F><>άʸ<CEAC><CAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool operator==(Point3D p1, Point3D p2) {
return (EQ(p1.x, p2.x) && EQ(p1.y, p2.y) && EQ(p1.z, p2.z));
}
bool operator<(Point3D p1, Point3D p2) {
if (NEQ(p1.x, p2.x)) { return (p1.x < p2.x); }
else if (NEQ(p1.y, p2.y)) { return (p1.y < p2.y); }
else { return (p1.z < p2.z); }
}
Point3D operator+(Point3D p1, Point3D p2) {
return Point3D(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z);
}
Point3D operator-(Point3D p1, Point3D p2) {
return Point3D(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z);
}
Point3D operator*(Point3D p1, Point3D p2) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> p1 x p2
return Point3D(p1.y * p2.z - p1.z * p2.y, p1.z * p2.x - p1.x * p2.z, p1.x * p2.y - p1.y * p2.x);
}
double operator&(Point3D p1, Point3D p2) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> p1<70><31>p2
return (p1.x * p2.x + p1.y * p2.y + p1.z * p2.z);
}
double Norm(Point3D p) { //<2F><><EFBFBD><EFBFBD>ʸ<EFBFBD><CAB8>p<EFBFBD><70>ģ
return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
}
/////////////////////////////////////////////////////////////////////////////////////
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>
double Area(Point A, Point B, Point C) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return ((B - A) * (C - A) / 2.0);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double Area(double a, double b, double c) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double s = (a + b + c) / 2.0;
return sqrt(s * (s - a) * (s - b) * (s - c));
}
double Area(const Circle &C) {
return M_PI * C.r * C.r;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>
double Area(const Polygon &poly) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double res = 0;
int n = poly.size();
if (n < 3) { return 0; }
for (int i = 0; i < n; i++) {
res += poly[i].x * poly[(i + 1) % n].y;
res -= poly[i].y * poly[(i + 1) % n].x;
}
return (res / 2.0);
}
/////////////////////////////////////////////////////////////////////////////////////
//<2F><>.<2E>߶<EFBFBD><><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//
double Distance(Point p1, Point p2) { //2<><32><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double Distance(Point3D p1, Point3D p2) { //2<><32><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>,<2C><>ά
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z));
}
double Distance(Point p, Line L) { //<2F><><EFBFBD><EFBFBD>άƽ<CEAC><C6BD><EFBFBD>ϵ㵽ֱ<E3B5BD>ߵľ<DFB5><C4BE><EFBFBD>
return (fabs((p - L.p1) * (L.p2 - L.p1)) / Norm(L.p2 - L.p1));
}
double Distance(Point3D p, Line3D L) { //<2F><><EFBFBD><EFBFBD>ά<EFBFBD>ռ<EFBFBD><D5BC>е㵽ֱ<E3B5BD>ߵľ<DFB5><C4BE><EFBFBD>
return (Norm((p - L.p1) * (L.p2 - L.p1)) / Norm(L.p2 - L.p1));
}
bool OnLine(Point p, Line L) { //<2F>ж϶<D0B6>άƽ<CEAC><C6BD><EFBFBD>ϵ<EFBFBD>p<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ֱ<EFBFBD><D6B1>L<EFBFBD><4C>
return ZERO((p - L.p1) * (L.p2 - L.p1));
}
bool OnLine(Point3D p, Line3D L) { //<2F>ж<EFBFBD><D0B6><EFBFBD>ά<EFBFBD>ռ<EFBFBD><D5BC>е<EFBFBD>p<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ֱ<EFBFBD><D6B1>L<EFBFBD><4C>
return ZERO((p - L.p1) * (L.p2 - L.p1));
}
int Relation(Point p, Line L) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><70>ֱ<EFBFBD><D6B1>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD>ϵ ,<2C><><EFBFBD><EFBFBD>ONLINE,LEFT,RIGHT
double res = (L.p2 - L.p1) * (p - L.p1);
if (EQ(res, 0)) { return ONLINE; }
else if (res > 0) { return LEFT; }
else { return RIGHT; }
}
bool SameSide(Point p1, Point p2, Line L) { //<2F>жϵ<D0B6>p1, p2<70>Ƿ<EFBFBD><C7B7><EFBFBD>ֱ<EFBFBD><D6B1>L<EFBFBD><4C>ͬ<EFBFBD><CDAC>
double m1 = (p1 - L.p1) * (L.p2 - L.p1);
double m2 = (p2 - L.p1) * (L.p2 - L.p1);
return GT(m1 * m2, 0);
}
bool OnLineSeg(Point p, Line L) { //<2F>ж϶<D0B6>άƽ<CEAC><C6BD><EFBFBD>ϵ<EFBFBD>p<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>߶<EFBFBD>l<EFBFBD><6C>
return (ZERO((L.p1 - p) * (L.p2 - p)) && LEQ((p.x - L.p1.x) * (p.x - L.p2.x), 0)
&& LEQ((p.y - L.p1.y) * (p.y - L.p2.y), 0));
}
bool OnLineSeg(Point3D p, Line3D L) { //<2F>ж<EFBFBD><D0B6><EFBFBD>ά<EFBFBD>ռ<EFBFBD><D5BC>е<EFBFBD>p<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>߶<EFBFBD>l<EFBFBD><6C>
return (ZERO((L.p1 - p) * (L.p2 - p)) && EQ(Norm(p - L.p1) + Norm(p - L.p2), Norm(L.p2 - L.p1)));
}
Point SymPoint(Point p, Line L) { //<2F><><EFBFBD><EFBFBD>άƽ<CEAC><C6BD><EFBFBD>ϵ<EFBFBD>p<EFBFBD><70><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>L<EFBFBD>ĶԳƵ<D4B3>
Point result;
double a = L.p2.x - L.p1.x;
double b = L.p2.y - L.p1.y;
double t = ((p.x - L.p1.x) * a + (p.y - L.p1.y) * b) / (a * a + b * b);
result.x = 2 * L.p1.x + 2 * a * t - p.x;
result.y = 2 * L.p1.y + 2 * b * t - p.y;
return result;
}
bool Coplanar(Points3D points) { //<2F>ж<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>еĵ<D0B5><C4B5>Ƿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Point3D p;
if (points.size() < 4) { return true; }
p = (points[2] - points[0]) * (points[1] - points[0]);
for (size_t i = 3; i < points.size(); i++) {
if (!ZERO(p & (points[i] - points[0]))) { return false; }
}
return true;
}
bool LineIntersect(Line L1, Line L2) { //<2F>ж϶<D0B6>ά<EFBFBD><CEAC><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>Ƿ<EFBFBD><C7B7>
return (!ZERO((L1.p1 - L1.p2) * (L2.p1 - L2.p2))); //<2F>Ƿ<EFBFBD>ƽ<EFBFBD><C6BD>
}
bool LineIntersect(Line3D L1, Line3D L2) { //<2F>ж<EFBFBD><D0B6><EFBFBD>ά<EFBFBD><CEAC><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>Ƿ<EFBFBD><C7B7>
Point3D p1 = L1.p1 - L1.p2;
Point3D p2 = L2.p1 - L2.p2;
Point3D p = p1 * p2;
if (ZERO(p)) { return false; } //<2F>Ƿ<EFBFBD>ƽ<EFBFBD><C6BD>
p = (L2.p1 - L1.p2) * (L1.p1 - L1.p2);
return ZERO(p & L2.p2); //<2F>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
}
bool LineSegIntersect(Line L1, Line L2) { //<2F>ж϶<D0B6>ά<EFBFBD><CEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>Ƿ<EFBFBD><C7B7>
return (GEQ(max(L1.p1.x, L1.p2.x), min(L2.p1.x, L2.p2.x)) &&
GEQ(max(L2.p1.x, L2.p2.x), min(L1.p1.x, L1.p2.x)) &&
GEQ(max(L1.p1.y, L1.p2.y), min(L2.p1.y, L2.p2.y)) &&
GEQ(max(L2.p1.y, L2.p2.y), min(L1.p1.y, L1.p2.y)) &&
LEQ(((L2.p1 - L1.p1) * (L1.p2 - L1.p1)) * ((L2.p2 - L1.p1) * (L1.p2 - L1.p1)), 0) &&
LEQ(((L1.p1 - L2.p1) * (L2.p2 - L2.p1)) * ((L1.p2 - L2.p1) * (L2.p2 - L2.p1)), 0));
}
bool LineSegIntersect(Line3D L1, Line3D L2) { //<2F>ж<EFBFBD><D0B6><EFBFBD>ά<EFBFBD><CEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>Ƿ<EFBFBD><C7B7>
//todo
return true;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>άֱ<CEAC>ߵĽ<DFB5><C4BD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>P<EFBFBD>з<EFBFBD><D0B7><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ˵<D6B5><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ߵ<EFBFBD>λ<EFBFBD>ù<EFBFBD>ϵ: COLINE -- <20><><EFBFBD><EFBFBD> PARALLEL -- ƽ<><C6BD> CROSS -- <20>
int CalCrossPoint(Line L1, Line L2, Point &P) {
double A1, B1, C1, A2, B2, C2;
A1 = L1.p2.y - L1.p1.y;
B1 = L1.p1.x - L1.p2.x;
C1 = L1.p2.x * L1.p1.y - L1.p1.x * L1.p2.y;
A2 = L2.p2.y - L2.p1.y;
B2 = L2.p1.x - L2.p2.x;
C2 = L2.p2.x * L2.p1.y - L2.p1.x * L2.p2.y;
if (EQ(A1 * B2, B1 * A2)) {
if (EQ((A1 + B1) * C2, (A2 + B2) * C1)) { return COLINE; }
else { return PARALLEL; }
} else {
P.x = (B2 * C1 - B1 * C2) / (A2 * B1 - A1 * B2);
P.y = (A1 * C2 - A2 * C1) / (A2 * B1 - A1 * B2);
return CROSS;
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>άֱ<CEAC>ߵĽ<DFB5><C4BD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>P<EFBFBD>з<EFBFBD><D0B7><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ˵<D6B5><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ߵ<EFBFBD>λ<EFBFBD>ù<EFBFBD>ϵ COLINE -- <20><><EFBFBD><EFBFBD> PARALLEL -- ƽ<><C6BD> CROSS -- <20>ཻ NONCOPLANAR -- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int CalCrossPoint(Line3D L1, Line3D L2, Point3D &P) {
//todo
return 0;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><50>ֱ<EFBFBD><D6B1>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Point NearestPointToLine(Point P, Line L) {
Point result;
double a, b, t;
a = L.p2.x - L.p1.x;
b = L.p2.y - L.p1.y;
t = ((P.x - L.p1.x) * a + (P.y - L.p1.y) * b) / (a * a + b * b);
result.x = L.p1.x + a * t;
result.y = L.p1.y + b * t;
return result;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><50><EFBFBD>߶<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Point NearestPointToLineSeg(Point P, Line L) {
Point result;
double a, b, t;
a = L.p2.x - L.p1.x;
b = L.p2.y - L.p1.y;
t = ((P.x - L.p1.x) * a + (P.y - L.p1.y) * b) / (a * a + b * b);
if (GEQ(t, 0) && LEQ(t, 1)) {
result.x = L.p1.x + a * t;
result.y = L.p1.y + b * t;
} else {
if (Norm(P - L.p1) < Norm(P - L.p2)) { result = L.p1; }
else { result = L.p2; }
}
return result;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>ն<EFBFBD>L1<4C><31><EFBFBD>߶<EFBFBD>L2<4C><32><EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD><CCBE><EFBFBD>
double MinDistance(Line L1, Line L2) {
double d1, d2, d3, d4;
if (LineSegIntersect(L1, L2)) {
return 0;
} else {
d1 = Norm(NearestPointToLineSeg(L1.p1, L2) - L1.p1);
d2 = Norm(NearestPointToLineSeg(L1.p2, L2) - L1.p2);
d3 = Norm(NearestPointToLineSeg(L2.p1, L1) - L2.p1);
d4 = Norm(NearestPointToLineSeg(L2.p2, L1) - L2.p2);
return min(min(d1, d2), min(d3, d4));
}
}
//<2F><><EFBFBD><EFBFBD>ά<EFBFBD><CEAC>ֱ<EFBFBD>ߵļн<C4BC>,
//<2F><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>0~Pi֮<69><D6AE><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>
double Inclination(Line L1, Line L2) {
Point u = L1.p2 - L1.p1;
Point v = L2.p2 - L2.p1;
return acos((u & v) / (Norm(u) * Norm(v)));
}
//<2F><><EFBFBD><EFBFBD>ά<EFBFBD><CEAC>ֱ<EFBFBD>ߵļн<C4BC>,
//<2F><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>0~Pi֮<69><D6AE><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>
double Inclination(Line3D L1, Line3D L2) {
Point3D u = L1.p2 - L1.p1;
Point3D v = L2.p2 - L2.p1;
return acos((u & v) / (Norm(u) * Norm(v)));
}
/////////////////////////////////////////////////////////////////////////////
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
//<2F>жϵ<D0B6>p<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>poly<6C><79>
//poly<6C>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>ĿҪ<C4BF><D2AA><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>3
//<2F><><EFBFBD><EFBFBD>ֵΪ<D6B5><CEAA>
//INSIDE -- <20><><EFBFBD><EFBFBD>poly<6C><79>
//BORDER -- <20><><EFBFBD><EFBFBD>poly<6C>߽<EFBFBD><DFBD><EFBFBD>
//OUTSIDE -- <20><><EFBFBD><EFBFBD>poly<6C><79>
int InsideConvex(Point p, const Polygon &poly) { //<2F>жϵ<D0B6>p<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>poly<6C><79>
Point q(0, 0);
Line side;
int i, n = poly.size();
for (i = 0; i < n; i++) {
q.x += poly[i].x; q.y += poly[i].y;
}
q.x /= n; q.y /= n;
for (i = 0; i < n; i++) {
side.p1 = poly[i];
side.p2 = poly[(i + 1) % n];
if (OnLineSeg(p, side)) { return BORDER; }
else if (!SameSide(p, q, side)) { return OUTSIDE; }
}
return INSIDE;
}
//<2F>ж϶<D0B6><CFB6><EFBFBD><EFBFBD><EFBFBD>poly<6C>Ƿ<EFBFBD><C7B7><EFBFBD>͹<EFBFBD><CDB9>
bool IsConvex(const Polygon &poly) {
int i, n, rel;
Line side;
n = poly.size();
if (n < 3) { return false; }
side.p1 = poly[0];
side.p2 = poly[1];
rel = Relation(poly[2], side);
for (i = 1; i < n; i++) {
side.p1 = poly[i];
side.p2 = poly[(i + 1) % n];
if (Relation(poly[(i + 2) % n], side) != rel) { return false; }
}
return true;
}
//<2F>жϵ<D0B6>p<EFBFBD>Ƿ<EFBFBD><C7B7>ڼ򵥶<DABC><F2B5A5B6><EFBFBD><EFBFBD><EFBFBD>poly<6C><79>, <20><><EFBFBD><EFBFBD><EFBFBD>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD>Ļ򰼵<C4BB>
//poly<6C>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>ĿҪ<C4BF><D2AA><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>3
//<2F><><EFBFBD><EFBFBD>ֵΪ<D6B5><CEAA>
//INSIDE -- <20><><EFBFBD><EFBFBD>poly<6C><79>
//BORDER -- <20><><EFBFBD><EFBFBD>poly<6C>߽<EFBFBD><DFBD><EFBFBD>
//OUTSIDE -- <20><><EFBFBD><EFBFBD>poly<6C><79>
int InsidePolygon(const Polygon &poly, Point p) {
int i, n, count;
Line ray, side;
n = poly.size();
count = 0;
ray.p1 = p;
ray.p2.y = p.y;
ray.p2.x = - INF;
for (i = 0; i < n; i++) {
side.p1 = poly[i];
side.p2 = poly[(i + 1) % n];
if (OnLineSeg(p, side)) {
return BORDER;
}
//<2F><><EFBFBD><EFBFBD>sideƽ<65><C6BD>x<EFBFBD><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (EQ(side.p1.y, side.p2.y)) { continue; }
if (OnLineSeg(side.p1, ray)) {
if (GT(side.p1.y, side.p2.y)) { count++; }
} else if (OnLineSeg(side.p2, ray)) {
if (GT(side.p2.y, side.p1.y)) { count++; }
} else if (LineSegIntersect(ray, side)) {
count++;
}
}
return ((count % 2 == 1) ? INSIDE : OUTSIDE);
}
//<2F>ж<EFBFBD><D0B6>߶<EFBFBD><DFB6>Ƿ<EFBFBD><C7B7>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28>߶εĵ<CEB5><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
//<2F><><EFBFBD><EFBFBD><EFBFBD>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򵥶<EFBFBD><F2B5A5B6><EFBFBD><EFBFBD><EFBFBD>
bool InsidePolygon(const Polygon &poly, Line L) {
bool result;
int n;
Points points;
Point p;
Line side;
result = ((InsidePolygon(poly, L.p1) != OUTSIDE) && (InsidePolygon(poly, L.p2) != OUTSIDE));
if (!result) { return false; }
n = poly.size();
for (int i = 0; i < n; i++) {
side.p1 = poly[i];
side.p2 = poly[(i + 1) % n];
if (OnLineSeg(L.p1, side)) {
points.push_back(L.p1);
} else if (OnLineSeg(L.p2, side)) {
points.push_back(L.p2);
} else if (OnLineSeg(side.p1, L)) {
points.push_back(side.p1);
} else if (OnLineSeg(side.p2, L)) {
points.push_back(side.p2);
} else if (LineSegIntersect(side, L)) {
return false;
}
}
//<2F>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
sort(points.begin(), points.end());
for (size_t i = 1; i < points.size(); i++) {
if (points[i - 1] != points[i]) {
p.x = (points[i - 1].x + points[i].x) / 2.0;
p.y = (points[i - 1].y + points[i].y) / 2.0;
if (InsidePolygon(poly, p) == OUTSIDE) {
return false;
}
}
}
return true;
}
//Ѱ<><D1B0>͹<EFBFBD><CDB9> graham ɨ<>
//<2F><><EFBFBD>ɵĶ<C9B5><C4B6><EFBFBD><EFBFBD>ζ<EFBFBD><CEB6><EFBFBD><E3B0B4>ʱ<EFBFBD><EFBFBD><EBB7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool GrahamComp(const Point &left, const Point &right) {
if (EQ(left.angle, right.angle)) {
return (left.dis < right.dis);
} else {
return (left.angle < right.angle);
}
}
void GrahamScan(Points &points, Polygon &result) {
int i, k, n;
Point p;
n = points.size();
result.clear();
if (n < 3) { return; }
//ѡȡpoints<74><73>y<EFBFBD><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ĵ<EFBFBD>points[k],
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ж<EFBFBD><D0B6><EFBFBD>, <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>һ<EFBFBD><D2BB>
k = 0;
for (i = 1; i < n; i++) {
if (EQ(points[i].y, points[k].y)) {
if (points[i].x <= points[k].x) { k = i; }
} else if (points[i].y < points[k].y) {
k = i;
}
}
swap(points[0], points[k]);
//<2F><><EFBFBD><EFBFBD>points<74><73>y<EFBFBD><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>points[0]
//<2F><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>points[0]<5D>ļ<EFBFBD><C4BC>Ǻ;<C7BA><CDBE><EFBFBD>
for (i = 1; i < n; i++) {
points[i].angle = atan2(points[i].y - points[0].y, points[i].x - points[0].x);
points[i].dis = Norm(points[i] - points[0]);
}
//<2F>Զ<EFBFBD><D4B6><EFBFBD><E3B0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>points[0]<5D>ļ<EFBFBD><C4BC>Ǵ<EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>İ<EFBFBD><C4B0>վ<EFBFBD>points[0]<5D>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
sort(points.begin() + 1, points.end(), GrahamComp);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><CDB9>
result.push_back(points[0]);
for (i = 1; i < n; i++) {
//<2F><><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>ĵ<EFBFBD>, ֻȡ<D6BB><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>points[0]<5D><>Զ<EFBFBD><D4B6>һ<EFBFBD><D2BB>
if ((i + 1 < n) && EQ(points[i].angle, points[i + 1].angle)) { continue; }
if (result.size() >= 3) {
p = result[result.size() - 2];
while (GEQ((points[i] - p) * (result.back() - p), 0)) {
result.pop_back();
p = result[result.size() - 2];
}
}
result.push_back(points[i]);
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>line<6E>и<EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
//result[LEFT]<5D><>result[RIGHT]<5D>ֱ𱣴汻<F0B1A3B4>и<EFBFBD><D0B8><EFBFBD>line<6E><65><EFBFBD><EFBFBD><EFBFBD>ߺ<EFBFBD><DFBA>ұ߲<D2B1><DFB2><EFBFBD>
//result[ONLINE]û<><C3BB><EFBFBD>õ<EFBFBD>, ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><CEB5>пڵij<DAB5><C4B3><EFBFBD>,
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>0 <20><>˵<EFBFBD><CBB5>δ<EFBFBD><CEB4><EFBFBD>и
//<2F><>δ<EFBFBD><CEB4><EFBFBD>и<EFBFBD>ʱ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD>ֱ<EFBFBD>ߵ<EFBFBD><DFB5>Ҳ<EFBFBD>, <20><>result[RIGHT]<5D><><EFBFBD>ڸö<DAB8><C3B6><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>result[LEFT]<5D><><EFBFBD>ڸö<DAB8><C3B6><EFBFBD><EFBFBD><EFBFBD>
//ע<><EFBFBD><E2A3BA><EFBFBD>и<EFBFBD><D0B8>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><E3B0B4><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>εĺ<CEB5>, <20><>ʼ<EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD>Ϊһ<CEAA><D2BB><EFBFBD>ܴ<EFBFBD><DCB4>ľ<EFBFBD><C4BE><EFBFBD>, Ȼ<><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD>ε<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5>
double CutConvex(const Polygon &poly, const Line &line, Polygon result[3]) {
vector<Point> points;
Line side;
Point p;
int i, n, cur, pre;
result[LEFT].clear();
result[RIGHT].clear();
result[ONLINE].clear();
n = poly.size();
if (n == 0) { return 0; }
pre = cur = Relation(poly[0], line);
for (i = 0; i < n; i++) {
cur = Relation(poly[(i + 1) % n], line);
if (cur == pre) {
result[cur].push_back(poly[(i + 1) % n]);
} else {
side.p1 = poly[i];
side.p2 = poly[(i + 1) % n];
CalCrossPoint(side, line, p);
points.push_back(p);
result[pre].push_back(p);
result[cur].push_back(p);
result[cur].push_back(poly[(i + 1) % n]);
pre = cur;
}
}
sort(points.begin(), points.end());
if (points.size() < 2) { return 0; }
else { return Norm(points.front() - points.back()); }
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD>Ļ򰼵ļ򵥶<C4BC><F2B5A5B6><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD>һ<EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԵĶ<D4B5><C4B6><EFBFBD>һ<EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Point CenterOfPolygon(const Polygon &poly) {
Point p, p0, p1, p2, p3;
double m, m0;
p1 = poly[0];
p2 = poly[1];
p.x = p.y = m = 0;
for (size_t i = 2; i < poly.size(); i++) {
p3 = poly[i];
p0.x = (p1.x + p2.x + p3.x) / 3.0;
p0.y = (p1.y + p2.y + p3.y) / 3.0;
m0 = p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.y * p2.x - p2.y * p3.x - p3.y * p1.x;
if (ZERO(m + m0)) { m0 += EPS; } //Ϊ<>˷<EFBFBD>ֹ<EFBFBD><D6B9>0<EFBFBD><30><EFBFBD><EFBFBD>, <20><>m0<6D><30>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
p.x = (m * p.x + m0 * p0.x) / (m + m0);
p.y = (m * p.y + m0 * p0.y) / (m + m0);
m = m + m0;
p2 = p3;
}
return p;
}
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>
bool Intersect(Rect_2 r1, Rect_2 r2) {
return (max(r1.xl, r2.xl) < min(r1.xh, r2.xh) && max(r1.yl, r2.yl) < min(r1.yh, r2.yh));
}
//<2F>жϾ<D0B6><CFBE><EFBFBD>r2<72>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD>ھ<EFBFBD><DABE><EFBFBD>r1<72><31>
//r2<72><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת
//<2F><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>OJ<4F>ϵ<EFBFBD><CFB5>޹<EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>Ĵ<EFBFBD><C4B4><EFBFBD>
bool IsContain(Rect r1, Rect r2) { //<2F><><EFBFBD>ε<EFBFBD>w > h
if (r1.w > r2.w && r1.h > r2.h) { return true; }
else {
double r = sqrt(r2.w * r2.w + r2.h * r2.h) / 2.0;
double alpha = atan2(r2.h, r2.w);
double sita = asin((r1.h / 2.0) / r);
double x = r * cos(sita - 2 * alpha);
double y = r * sin(sita - 2 * alpha);
if (x < r1.w / 2.0 && y < r1.h / 2.0 && x > 0 && y > -r1.h / 2.0) { return true; }
else { return false; }
}
}
////////////////////////////////////////////////////////////////////////
//Բ
Point Center(const Circle &C) { //Բ<><D4B2>
return C.c;
}
//<2F><><EFBFBD><EFBFBD>Բ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double CommonArea(const Circle &A, const Circle &B) {
double area = 0.0;
const Circle &M = (A.r > B.r) ? A : B;
const Circle &N = (A.r > B.r) ? B : A;
double D = Distance(Center(M), Center(N));
if ((D < M.r + N.r) && (D > M.r - N.r)) {
double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D);
double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D);
double alpha = 2.0 * acos(cosM);
double beta = 2.0 * acos(cosN);
double TM = 0.5 * M.r * M.r * sin(alpha);
double TN = 0.5 * N.r * N.r * sin(beta);
double FM = (alpha / 360.0) * Area(M);
double FN = (beta / 360.0) * Area(N);
area = FM + FN - TM - TN;
} else if (D <= M.r - N.r) {
area = Area(N);
}
return area;
}
//<2F>ж<EFBFBD>Բ<EFBFBD>Ƿ<EFBFBD><C7B7>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
bool IsInCircle(const Circle &C, const Rect_2 &rect) {
return (GT(C.c.x - C.r, rect.xl) && LT(C.c.x + C.r, rect.xh) && GT(C.c.y - C.r, rect.yl)
&& LT(C.c.y + C.r, rect.yh));
}
//<2F>ж<EFBFBD><32><D4B2>λ<EFBFBD>ù<EFBFBD>ϵ
//<2F><><EFBFBD><EFBFBD>:
//BAOHAN = 1; //<2F><>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD>СԲ
//NEIQIE = 2; //<2F><><EFBFBD><EFBFBD>
//XIANJIAO = 3; //<2F>
//WAIQIE = 4; //<2F><><EFBFBD><EFBFBD>
//XIANLI = 5; //<2F><><EFBFBD><EFBFBD>
int CirCir(const Circle &c1, const Circle &c2) {
double dis = Distance(c1.c, c2.c);
if (LT(dis, fabs(c1.r - c2.r))) { return BAOHAN; }
if (EQ(dis, fabs(c1.r - c2.r))) { return NEIQIE; }
if (LT(dis, c1.r + c2.r) && GT(dis, fabs(c1.r - c2.r))) { return XIANJIAO; }
if (EQ(dis, c1.r + c2.r)) { return WAIQIE; }
return XIANLI;
}