算法模板の计算几何
1、凸包
1 inline bool cmp(const POINT &a, const POINT &b) { 2 if(a.y == b.y) return a.x < b.x; 3 return a.y < b.y; 4 } 5 //turn left 6 inline bool Cross(POINT &sp, POINT &ep, POINT &op) { 7 return (sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y) >= 0; 8 } 9 10 inline double dist(POINT &a, POINT &b) { 11 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 12 } 13 14 void Graham_scan() { 15 std::sort(p, p + n, cmp); 16 top = 1; 17 stk[0] = 0; stk[1] = 1; 18 for(int i = 2; i < n; ++i) { 19 while(top && Cross(p[i], p[stk[top]], p[stk[top - 1]])) --top; 20 stk[++top] = i; 21 } 22 int len = top; 23 stk[++top] = n - 2; 24 for(int i = n - 3; i >= 0; --i) { 25 while(top != len && Cross(p[i], p[stk[top]], p[stk[top - 1]])) --top; 26 stk[++top] = i; 27 } 28 }
2、旋转卡壳(POJ 3384)
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 #define EPS 1e-8 8 #define MAXN 1000 9 10 inline int sgn(double x) { 11 if(fabs(x) < EPS) return 0; 12 return x > 0 ? 1 : -1; 13 } 14 15 struct Point { 16 double x, y; 17 Point(double xx = 0, double yy = 0): x(xx), y(yy) {} 18 bool operator == (const Point &b) const { 19 return sgn(x - b.x) == 0 && sgn(y - b.y) == 0; 20 } 21 }; 22 //cross 23 inline double operator ^ (const Point &a, const Point &b) { 24 return a.x * b.y - a.y * b.x; 25 } 26 27 inline Point operator - (const Point &a, const Point &b) { 28 return Point(a.x - b.x, a.y - b.y); 29 } 30 31 struct Line { 32 Point s, e; 33 double ag; 34 }; 35 36 struct polygon { 37 Point v[MAXN]; 38 int n; 39 } pg, res; 40 41 inline double dist(Point &a, Point &b) { 42 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 43 } 44 45 inline double Cross(Point o, Point s, Point e) { 46 return (s - o) ^ (e - o); 47 } 48 //cross_point 49 Point operator * (const Line &a, const Line &b) { 50 Point res; 51 double u = Cross(a.s, a.e, b.s), v = Cross(a.e, a.s, b.e); 52 res.x = (b.s.x * v + b.e.x * u)/(u + v); 53 res.y = (b.s.y * v + b.e.y * u)/(u + v); 54 return res; 55 } 56 57 int parallel(Line a, Line b) { 58 double u = (a.e.x - a.s.x) * (b.e.y - b.s.y) - (a.e.y - a.s.y) * (b.e.x - b.s.x); 59 return sgn(u) == 0; 60 } 61 62 inline void set_vector(double x1, double y1, double x2, double y2, Line &v) { 63 v.s.x = x1; v.s.y = y1; 64 v.e.x = x2; v.e.y = y2; 65 v.ag = atan2(y2 - y1, x2 - x1); 66 } 67 68 Line vct[MAXN], deq[MAXN]; 69 70 bool cmp(const Line &a, const Line &b) { 71 if(sgn(a.ag - b.ag) == 0) 72 return sgn(Cross(b.s, b.e, a.s)) < 0; 73 return a.ag < b.ag; 74 } 75 76 int half_planes_cross(Line *v, int vn) { 77 int i, n; 78 //sort(v, v + vn, cmp); 79 for(i = n = 1; i < vn; ++i) { 80 if(sgn(v[i].ag - v[i-1].ag) == 0) continue; 81 v[n++] = v[i]; 82 } 83 int head = 0, tail = 1; 84 deq[0] = v[0], deq[1] = v[1]; 85 for(i = 2; i < n; ++i) { 86 if(parallel(deq[tail - 1], deq[tail]) || parallel(deq[head], deq[head + 1])) 87 return false; 88 while(head < tail && sgn(Cross(v[i].s, v[i].e, deq[tail - 1] * deq[tail])) > 0) 89 --tail; 90 while(head < tail && sgn(Cross(v[i].s, v[i].e, deq[head] * deq[head + 1])) > 0) 91 ++head; 92 deq[++tail] = v[i]; 93 } 94 while(head < tail && sgn(Cross(deq[head].s, deq[head].e, deq[tail - 1] * deq[tail])) > 0) 95 --tail; 96 while(head < tail && sgn(Cross(deq[tail].s, deq[tail].e, deq[head] * deq[head + 1])) > 0) 97 ++head; 98 if(tail <= head + 1) return false; 99 res.n = 0; 100 for(i = head; i < tail; ++i) 101 res.v[res.n++] = deq[i] * deq[i + 1]; 102 res.v[res.n++] = deq[head] * deq[tail]; 103 res.n = unique(res.v, res.v + res.n) - res.v; 104 res.v[res.n] = res.v[0]; 105 return true; 106 } 107 108 void moving(Line v[], int vn, double r) { 109 for(int i = 0; i < vn; ++i) { 110 double dx = v[i].e.x - v[i].s.x, dy = v[i].e.y - v[i].s.y; 111 dx = dx / dist(v[i].s, v[i].e) * r; 112 dy = dy / dist(v[i].s, v[i].e) * r; 113 v[i].s.x += dy; v[i].e.x += dy; 114 v[i].s.y -= dx; v[i].e.y -= dx; 115 } 116 } 117 118 int ix, jx; 119 120 double dia_roataing_calipers() { 121 double dia = 0; 122 ix = jx = 0; 123 int q = 1; 124 for(int i = 0; i < res.n; ++i) { 125 while(sgn(Cross(res.v[i+1], res.v[i], res.v[q+1]) - Cross(res.v[i+1], res.v[i], res.v[q])) > 0) 126 q = (q + 1) % res.n; 127 if(sgn(dist(res.v[i], res.v[q]) - dia) > 0) { 128 dia = dist(res.v[i], res.v[q]); 129 ix = i; jx = q; 130 } 131 if(sgn(dist(res.v[i+1], res.v[q]) - dia) > 0) { 132 dia = dist(res.v[i+1], res.v[q]); 133 ix = i+1; jx = q; 134 } 135 } 136 return dia; 137 } 138 139 int main() { 140 int n; 141 double r; 142 while(scanf("%d%lf", &n, &r) != EOF) { 143 for(int i = 0; i < n; ++i) scanf("%lf%lf", &pg.v[i].x, &pg.v[i].y); 144 pg.v[n] = pg.v[0]; 145 for(int i = 0; i < n; ++i) 146 set_vector(pg.v[i].x, pg.v[i].y, pg.v[i+1].x, pg.v[i+1].y, vct[i]); 147 moving(vct, n, r); 148 half_planes_cross(vct, n); 149 dia_roataing_calipers(); 150 printf("%.4f %.4f %.4f %.4f\n", res.v[ix].x, res.v[ix].y, res.v[jx].x, res.v[jx].y); 151 } 152 }
3、最小圆覆盖
1 #include <cstdio> 2 #include <cmath> 3 4 const int MAXN = 1010; 5 6 struct Point { 7 double x, y; 8 Point(double xx = 0, double yy = 0): x(xx), y(yy) {} 9 }; 10 11 double operator ^ (const Point &a, const Point &b) { 12 return a.x * b.y - a.y * b.x; 13 } 14 15 Point operator - (const Point &a, const Point &b) { 16 return Point(a.x - b.x, a.y - b.y); 17 } 18 19 double dist(const Point &a, const Point &b) { 20 double x = a.x - b.x, y = a.y - b.y; 21 return sqrt(x * x + y * y); 22 } 23 24 struct Circle { 25 double r; 26 Point centre; 27 }; 28 29 struct Triangle { 30 Point t[3]; 31 double Area() { 32 return fabs((t[1] - t[0]) ^ (t[2] - t[0]))/2; 33 } 34 }; 35 36 Circle circumcircleOfTriangle(Triangle t) { 37 Circle tmp; 38 double a, b, c, c1, c2; 39 Point A(t.t[0].x, t.t[0].y); 40 Point B(t.t[1].x, t.t[1].y); 41 Point C(t.t[2].x, t.t[2].y); 42 a = dist(B, C); 43 b = dist(A, C); 44 c = dist(A, B); 45 tmp.r = a * b * c / t.Area() / 4; 46 c1 = (A.x * A.x + A.y * A.y - B.x * B.x - B.y * B.y) / 2; 47 c2 = (A.x * A.x + A.y * A.y - C.x * C.x - C.y * C.y) / 2; 48 tmp.centre.x = (c1 * (A.y - C.y) - c2 * (A.y - B.y)) / ((A.x - B.x) * (A.y - C.y) - (A.x - C.x) * (A.y - B.y)); 49 tmp.centre.y = (c1 * (A.x - C.x) - c2 * (A.x - B.x)) / ((A.y - B.y) * (A.x - C.x) - (A.y - C.y) * (A.x - B.x)); 50 return tmp; 51 } 52 53 Circle c; 54 Point a[MAXN]; 55 56 Circle MinCircle2(int tce, Triangle ce) { 57 Circle tmp; 58 if(tce == 0) tmp.r = -2; 59 else if(tce == 1) { 60 tmp.centre = ce.t[0]; 61 tmp.r = 0; 62 } 63 else if(tce == 2) { 64 tmp.r = dist(ce.t[0], ce.t[1]) / 2; 65 tmp.centre.x = (ce.t[0].x + ce.t[1].x) / 2; 66 tmp.centre.y = (ce.t[0].y + ce.t[1].y) / 2; 67 } 68 else if(tce == 3) tmp = circumcircleOfTriangle(ce); 69 return tmp; 70 } 71 72 void MinCircle(int t, int tce, Triangle ce) { 73 Point tmp; 74 c = MinCircle2(tce, ce); 75 if(tce == 3) return; 76 for(int i = 1; i <= t; ++i) { 77 if(dist(a[i], c.centre) > c.r) { 78 ce.t[tce] = a[i]; 79 MinCircle(i - 1, tce + 1, ce); 80 tmp = a[i]; 81 for(int j = i; j >= 2; --j) a[j] = a[j - 1]; 82 a[1] = tmp; 83 } 84 } 85 } 86 87 void run(int n) { 88 Triangle ce; 89 MinCircle(n, 0, ce); 90 printf("%.2f %.2f %.2f\n", c.centre.x, c.centre.y, c.r); 91 } 92 93 int main() { 94 int n; 95 while(scanf("%d", &n) != EOF) { 96 if(n == 0) break; 97 for(int i = 1; i <= n; ++i) 98 scanf("%lf%lf", &a[i].x, &a[i].y); 99 run(n); 100 } 101 }
4、半平面交+最远点对
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 #define EPS 1e-8 8 #define MAXN 1000 9 10 inline int sgn(double x) { 11 if(fabs(x) < EPS) return 0; 12 return x > 0 ? 1 : -1; 13 } 14 15 struct Point { 16 double x, y; 17 Point(double xx = 0, double yy = 0): x(xx), y(yy) {} 18 bool operator == (const Point &b) const { 19 return sgn(x - b.x) == 0 && sgn(y - b.y) == 0; 20 } 21 }; 22 //cross 23 inline double operator ^ (const Point &a, const Point &b) { 24 return a.x * b.y - a.y * b.x; 25 } 26 27 inline Point operator - (const Point &a, const Point &b) { 28 return Point(a.x - b.x, a.y - b.y); 29 } 30 31 struct Line { 32 Point s, e; 33 double ag; 34 }; 35 36 struct polygon { 37 Point v[MAXN]; 38 int n; 39 } pg, res; 40 41 inline double dist(Point &a, Point &b) { 42 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 43 } 44 45 inline double Cross(Point o, Point s, Point e) { 46 return (s - o) ^ (e - o); 47 } 48 //cross_point 49 Point operator * (const Line &a, const Line &b) { 50 Point res; 51 double u = Cross(a.s, a.e, b.s), v = Cross(a.e, a.s, b.e); 52 res.x = (b.s.x * v + b.e.x * u)/(u + v); 53 res.y = (b.s.y * v + b.e.y * u)/(u + v); 54 return res; 55 } 56 57 int parallel(Line a, Line b) { 58 double u = (a.e.x - a.s.x) * (b.e.y - b.s.y) - (a.e.y - a.s.y) * (b.e.x - b.s.x); 59 return sgn(u) == 0; 60 } 61 62 inline void set_vector(double x1, double y1, double x2, double y2, Line &v) { 63 v.s.x = x1; v.s.y = y1; 64 v.e.x = x2; v.e.y = y2; 65 v.ag = atan2(y2 - y1, x2 - x1); 66 } 67 68 Line vct[MAXN], deq[MAXN]; 69 70 bool cmp(const Line &a, const Line &b) { 71 if(sgn(a.ag - b.ag) == 0) 72 return sgn(Cross(b.s, b.e, a.s)) < 0; 73 return a.ag < b.ag; 74 } 75 76 int half_planes_cross(Line *v, int vn) { 77 int i, n; 78 //sort(v, v + vn, cmp); 79 for(i = n = 1; i < vn; ++i) { 80 if(sgn(v[i].ag - v[i-1].ag) == 0) continue; 81 v[n++] = v[i]; 82 } 83 int head = 0, tail = 1; 84 deq[0] = v[0], deq[1] = v[1]; 85 for(i = 2; i < n; ++i) { 86 if(parallel(deq[tail - 1], deq[tail]) || parallel(deq[head], deq[head + 1])) 87 return false; 88 while(head < tail && sgn(Cross(v[i].s, v[i].e, deq[tail - 1] * deq[tail])) > 0) 89 --tail; 90 while(head < tail && sgn(Cross(v[i].s, v[i].e, deq[head] * deq[head + 1])) > 0) 91 ++head; 92 deq[++tail] = v[i]; 93 } 94 while(head < tail && sgn(Cross(deq[head].s, deq[head].e, deq[tail - 1] * deq[tail])) > 0) 95 --tail; 96 while(head < tail && sgn(Cross(deq[tail].s, deq[tail].e, deq[head] * deq[head + 1])) > 0) 97 ++head; 98 if(tail <= head + 1) return false; 99 res.n = 0; 100 for(i = head; i < tail; ++i) 101 res.v[res.n++] = deq[i] * deq[i + 1]; 102 res.v[res.n++] = deq[head] * deq[tail]; 103 res.n = unique(res.v, res.v + res.n) - res.v; 104 res.v[res.n] = res.v[0]; 105 return true; 106 } 107 108 void moving(Line v[], int vn, double r) { 109 for(int i = 0; i < vn; ++i) { 110 double dx = v[i].e.x - v[i].s.x, dy = v[i].e.y - v[i].s.y; 111 dx = dx / dist(v[i].s, v[i].e) * r; 112 dy = dy / dist(v[i].s, v[i].e) * r; 113 v[i].s.x += dy; v[i].e.x += dy; 114 v[i].s.y -= dx; v[i].e.y -= dx; 115 } 116 } 117 118 int ix, jx; 119 120 double dia_roataing_calipers() { 121 double dia = 0; 122 ix = jx = 0; 123 int q = 1; 124 for(int i = 0; i < res.n; ++i) { 125 while(sgn(Cross(res.v[i+1], res.v[i], res.v[q+1]) - Cross(res.v[i+1], res.v[i], res.v[q])) > 0) 126 q = (q + 1) % res.n; 127 if(sgn(dist(res.v[i], res.v[q]) - dia) > 0) { 128 dia = dist(res.v[i], res.v[q]); 129 ix = i; jx = q; 130 } 131 if(sgn(dist(res.v[i+1], res.v[q]) - dia) > 0) { 132 dia = dist(res.v[i+1], res.v[q]); 133 ix = i+1; jx = q; 134 } 135 } 136 return dia; 137 } 138 139 int main() { 140 int n; 141 double r; 142 while(scanf("%d%lf", &n, &r) != EOF) { 143 for(int i = 0; i < n; ++i) scanf("%lf%lf", &pg.v[i].x, &pg.v[i].y); 144 pg.v[n] = pg.v[0]; 145 for(int i = 0; i < n; ++i) 146 set_vector(pg.v[i].x, pg.v[i].y, pg.v[i+1].x, pg.v[i+1].y, vct[i]); 147 moving(vct, n, r); 148 half_planes_cross(vct, n); 149 dia_roataing_calipers(); 150 printf("%.4f %.4f %.4f %.4f\n", res.v[ix].x, res.v[ix].y, res.v[jx].x, res.v[jx].y); 151 } 152 }
其他1:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef double TYPE;
#define Abs(x) (((x)>0)?(x):(-(x)))
#define Sgn(x) (((x)<0)?(-1):(1))
#define Max(a,b) (((a)>(b))?(a):(b))
#define Min(a,b) (((a)<(b))?(a):(b))
#define EPS 1e-8
#define Infinity 1e+10
#define PI acos(-1.0)//3.14159265358979323846
TYPE Deg2Rad(TYPE deg){return (deg * PI / 180.0);}
TYPE Rad2Deg(TYPE rad){return (rad * 180.0 / PI);}
TYPE Sin(TYPE deg){return sin(Deg2Rad(deg));}
TYPE Cos(TYPE deg){return cos(Deg2Rad(deg));}
TYPE ArcSin(TYPE val){return Rad2Deg(asin(val));}
TYPE ArcCos(TYPE val){return Rad2Deg(acos(val));}
TYPE Sqrt(TYPE val){return sqrt(val);}
//点
struct POINT {
TYPE x, y;
POINT(TYPE xx = 0, TYPE yy = 0): x(xx), y(yy) {}
};
// 两个点的距离
TYPE Distance(const POINT &a, const POINT &b) {
return Sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
//线段
struct SEG {
POINT a ,b;
SEG() {};
SEG(POINT aa, POINT bb): a(aa), b(bb) {}
};
//直线(两点式)
struct LINE {
POINT a, b;
LINE() {};
LINE(POINT aa, POINT bb): a(aa), b(bb) {}
};
//直线(一般式)
struct LINE2 {
TYPE A,B,C;
LINE2() {};
LINE2(TYPE AA, TYPE BB, TYPE CC): A(AA), B(BB), C(CC) {}
};
//两点式化一般式
LINE2 Line2line(const LINE &L) {
LINE2 L2;
L2.A = L.b.y - L.a.y;
L2.B = L.a.x - L.b.x;
L2.C = L.b.x * L.a.y - L.a.x * L.b.y;
return L2;
}
// 引用返回直线 Ax + By + C =0 的系数
void Coefficient(const LINE &L, TYPE &A, TYPE &B, TYPE &C) {
A = L.b.y - L.a.y;
B = L.a.x - L.b.x;
C = L.b.x * L.a.y - L.a.x * L.b.y;
}
void Coefficient(const POINT &p,const TYPE &a,TYPE &A,TYPE &B,TYPE &C) {
A = Cos(a);
B = Sin(a);
C = - (p.y * B + p.x * A);
}
//直线相交的交点
POINT Intersection(const LINE &A, const LINE &B) {
TYPE A1, B1, C1;
TYPE A2, B2, C2;
Coefficient(A, A1, B1, C1);
Coefficient(B, A2, B2, C2);
POINT I;
I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
return I;
}
//点到直线的距离
TYPE Ptol(const POINT &p,const LINE2 &L) {
return fabs(L.A * p.x + L.B * p.y + L.C)/Sqrt(L.A * L.A + L.B * L.B);
}
//两线段叉乘
TYPE Cross2(const SEG &p, const SEG &q) {
return (p.b.x - p.a.x) * (q.b.y - q.a.y) - (q.b.x - q.a.x) * (p.b.y - p.a.y);
}
//有公共端点O叉乘,并判拐,若正p0->p1->p2拐向左
TYPE Cross(const POINT &a, const POINT &b, const POINT &o) {
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}
//判等(值,点,直线)
bool IsEqual(const TYPE &a, const TYPE &b) {
return (Abs(a - b) < EPS);
}
bool IsEqual(const POINT & a, const POINT & b) {
return IsEqual(a.x, b.x) && IsEqual(a.y, b.y);
}
bool IsEqual(const LINE & A, const LINE & B) {
TYPE A1, B1, C1;
TYPE A2, B2, C2;
Coefficient(A, A1, B1, C1);
Coefficient(B, A2, B2, C2);
return IsEqual(A1 * B2, A2 * B1) && IsEqual(A1 * C2, A2 * C1) && IsEqual(B1 * C2, B2 * C1);
}
// 判断点是否在线段上
bool IsOnSeg(const SEG &seg, const POINT &p) {
return (IsEqual(p, seg.a) || IsEqual(p, seg.b)) ||
(((p.x - seg.a.x) * (p.x - seg.b.x) < 0 ||
(p.y - seg.a.y) * (p.y - seg.b.y) < 0) &&
(IsEqual(Cross(seg.b, p, seg.a), 0)));
}
//判断两条线断是否相交,端点重合算相交
bool IsIntersect(const SEG &u, const SEG &v) {
return (Cross(v.a, u.b, u.a) * Cross(u.b, v.b, u.a) >= 0) &&
(Cross(u.a, v.b, v.a) * Cross(v.b, u.b, v.a) >= 0) &&
(Max(u.a.x, u.b.x) >= Min(v.a.x, v.b.x)) &&
(Max(v.a.x, v.b.x) >= Min(u.a.x, u.b.x)) &&
(Max(u.a.y, u.b.y) >= Min(v.a.y, v.b.y)) &&
(Max(v.a.y, v.b.y) >= Min(u.a.y, u.b.y));
}
//判断线段P和直线Q是否相交,端点重合算相交
bool Isonline(const SEG &p, const LINE &q) {
SEG p1,p2,q0;
p1.a = q.a; p1.b = p.a;
p2.a = q.a; p2.b = p.b;
q0.a = q.a; q0.b = q.b;
return (Cross2(p1,q0) * Cross2(q0,p2) >= 0);
}
//判断两条线断是否平行
bool IsParallel(const LINE &A, const LINE &B) {
TYPE A1, B1, C1;
TYPE A2, B2, C2;
Coefficient(A, A1, B1, C1);
Coefficient(B, A2, B2, C2);
return (A1 * B2 == A2 * B1);
}
//判断两条直线是否相交
bool IsIntersect(const LINE & A, const LINE & B) {
return !IsParallel(A, B);
}
// 矩形
struct RECT {
POINT a; // 左下点
POINT b; // 右上点
RECT() {}
RECT(const POINT &aa, const POINT &bb): a(aa), b(bb) {}
};
//矩形化标准
RECT Stdrect(const RECT &q) {
RECT p = q;
if(p.a.x > p.b.x) swap(p.a.x , p.b.x);
if(p.a.y > p.b.y) swap(p.a.y , p.b.y);
return p;
}
//根据下标返回矩形的边
SEG Edge(const RECT &rect, int idx) {
SEG edge;
while (idx < 0) idx += 4;
switch (idx % 4) {
case 0: //下边
edge.a = rect.a;
edge.b = POINT(rect.b.x, rect.a.y);
break;
case 1: //右边
edge.a = POINT(rect.b.x, rect.a.y);
edge.b = rect.b;
break;
case 2: //上边
edge.a = rect.b;
edge.b = POINT(rect.a.x, rect.b.y);
break;
case 3: //左边
edge.a = POINT(rect.a.x, rect.b.y);
edge.b = rect.a;
break;
default:
break;
}
return edge;
}
//矩形的面积
TYPE Area(const RECT &rect) {
return (rect.b.x - rect.a.x) * (rect.b.y - rect.a.y);
}
//两个矩形的公共面积
TYPE CommonArea(const RECT &A, const RECT &B) {
TYPE area = 0.0;
POINT LL(Max(A.a.x, B.a.x), Max(A.a.y, B.a.y));
POINT UR(Min(A.b.x, B.b.x), Min(A.b.y, B.b.y));
if((LL.x <= UR.x) && (LL.y <= UR.y)) {
area = Area(RECT(LL, UR));
}
return area;
}
// 圆
struct CIRCLE {
TYPE x, y, r;
CIRCLE() {}
CIRCLE(TYPE xx, TYPE yy, TYPE zz): x(xx), y(yy), r(zz) {}
};
//圆心
POINT Center(const CIRCLE &circle) {
return POINT(circle.x, circle.y);
}
//圆的面积
TYPE Area(const CIRCLE &circle) {
return PI * circle.r * circle.r;
}
//两个圆的公共面积
TYPE CommonArea(const CIRCLE &A, const CIRCLE &B)
{
TYPE area = 0.0;
const CIRCLE & M = (A.r > B.r) ? A : B;
const CIRCLE & N = (A.r > B.r) ? B : A;
TYPE D = Distance(Center(M), Center(N));
if((D < M.r + N.r) && (D > M.r - N.r)) {
TYPE cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D);
TYPE cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D);
TYPE alpha = 2.0 * ArcCos(cosM);
TYPE beta = 2.0 * ArcCos(cosN);
TYPE TM = 0.5 * M.r * M.r * Sin(alpha);
TYPE TN = 0.5 * N.r * N.r * Sin(beta);
TYPE FM = (alpha / 360.0) * Area(M);
TYPE FN = (beta / 360.0) * Area(N);
area = FM + FN - TM - TN;
}
else if(D <= M.r - N.r) {
area = Area(N);
}
return area;
}
//判断圆是否在矩形内(不允许相切)
bool IsInCircle(const CIRCLE &circle, const RECT &rect) {
return (circle.x - circle.r > rect.a.x) &&
(circle.x + circle.r < rect.b.x) &&
(circle.y - circle.r > rect.a.y) &&
(circle.y + circle.r < rect.b.y);
}
//判断矩形是否在圆内(不允许相切)
bool IsInRect(const CIRCLE & circle, const RECT & rect) {
POINT c,d;
c.x = rect.a.x; c.y = rect.b.y;
d.x = rect.b.x; d.y = rect.a.y;
return (Distance( Center(circle) , rect.a ) < circle.r) &&
(Distance( Center(circle) , rect.b ) < circle.r) &&
(Distance( Center(circle) , c ) < circle.r) &&
(Distance( Center(circle) , d ) < circle.r);
}
//判断矩形是否与圆相离(不允许相切)
bool Isoutside(const CIRCLE & circle, const RECT & rect) {
POINT c,d;
c.x = rect.a.x; c.y=rect.b.y;
d.x = rect.b.x; d.y=rect.a.y;
return ((Distance( Center(circle) , rect.a ) > circle.r) &&
(Distance( Center(circle) , rect.b ) > circle.r) &&
(Distance( Center(circle) , c ) > circle.r) &&
(Distance( Center(circle) , d ) > circle.r) &&
(rect.a.x > circle.x || circle.x > rect.b.x || rect.a.y > circle.y || circle.y > rect.b.y)) ||
((circle.x - circle.r > rect.b.x) ||
(circle.x + circle.r < rect.a.x) ||
(circle.y - circle.r > rect.b.y) ||
(circle.y + circle.r < rect.a.y));
}
//三角形
struct TRIANGLE {
POINT a, b, c;
TRIANGLE() {};
TRIANGLE(const POINT & aa, const POINT & bb, const POINT & cc):
a(aa), b(bb), c(cc) {}
};
//三角形标准化
TRIANGLE StdTRIANGLE(TYPE len1, TYPE len2, TYPE len3) //把3边长转化成三角形
{
POINT a, b, c; //已知边长后将其转化成坐标三角形
a.x = a.y = 0.0;
b.x = len1;
b.y = 0.0;
c.x = (len2 * len2 - len3 * len3 + len1 * len1)/len1/2.0;
c.y = Sqrt(len2 * len2 - c.x * c.x);
TRIANGLE temp(a,b,c);
return temp;
};
//三角形费马点(即三角形到三顶点之和最小的点)
POINT fermentPONT(TRIANGLE &t) {
POINT u, v;
double step = fabs(t.a.x) + fabs(t.a.y) + fabs(t.b.x) + fabs(t.b.y) + fabs(t.c.x) + fabs(t.c.y);
int i, j, k;
u.x = (t.a.x + t.b.x + t.c.x)/3;
u.y = (t.a.y + t.b.y + t.c.y)/3;
while (step > EPS)
for(k = 0; k < 10; step /= 2, ++k)
for(i = -1; i <= 1; ++i)
for(j = -1; j <= 1; ++j) {
v.x = u.x + step * i;
v.y = u.y + step * j;
if(Distance(u,t.a) + Distance(u,t.b) + Distance(u,t.c) > Distance(v,t.a) + Distance(v,t.b) + Distance(v,t.c))
u = v;
}
return u;
};
//三角形重心(中线交点)
POINT InCenter(const TRIANGLE &t) {
return POINT((t.a.x + t.b.x + t.c.x)/3, (t.a.y + t.b.y + t.c.y)/3);
}
//三角形外心(中垂线交点)
POINT CcCenter(const TRIANGLE &t) {
POINT u, v;
LINE A, B;
A.a = t.a; A.b = t.b; B.a = t.b; B.b = t.c;
TYPE A1, B1, C1;
TYPE A2, B2, C2;
Coefficient(A, B1, A1, C1);
Coefficient(B, B2, A2, C2);
B1 = -B1; B2 = -B2;
C1 = -((A.a.x + A.b.x) * A1 + (A.a.y + B.a.y) * B1)/2;
C2 = -((B.a.x + B.b.x) * A2 + (B.a.y + B.b.y) * B2)/2;
POINT I(0, 0);
I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
return I;
}
//三角形内心(角平分线交点)
POINT incenter(const TRIANGLE &t) {
LINE u, v;
TYPE m, n;
u.a = t.a;
m = atan2(t.b.y - t.a.y, t.b.x - t.a.x);
n = atan2(t.c.y - t.a.y, t.c.x - t.a.x);
u.b.x = u.a.x + cos((m + n)/2);
u.b.y = u.a.y + sin((m + n)/2);
v.a = t.b;
m = atan2(t.a.y - t.b.y, t.a.x - t.b.x);
n = atan2(t.c.y - t.b.y, t.c.x - t.b.x);
v.b.x = v.a.x + cos((m + n)/2);
v.b.y = v.a.y + sin((m + n)/2);
return Intersection(u, v);
};
//三角形内切圆面积
TYPE InArea(const TRIANGLE &t) {
TYPE p, a, b, c, s;
a = Distance(t.a, t.b);
c = Distance(t.a, t.c);
b = Distance(t.c, t.b);
s = (a + b + c)/2;
p = s * (s - a) * (s - b) * (s - c);
s = p * PI/s/s;
return s;
}
//三角形外接圆面积
TYPE OutArea(const TRIANGLE & t) {
TYPE a,b,c;
a = (t.a.x - t.b.x) * (t.a.x - t.b.x) + (t.a.y - t.b.y) * (t.a.y - t.b.y);
b = (t.a.x - t.c.x) * (t.a.x - t.c.x) + (t.a.y - t.c.y) * (t.a.y - t.c.y);
c = (t.c.x - t.b.x) * (t.c.x - t.b.x) + (t.c.y - t.b.y) * (t.c.y - t.b.y);
a = PI * sqrt(c/(1-(a+b-c)*(a+b-c)/a/b/4));
return a;
}
// 多边形 ,逆时针或顺时针给出x,y
struct POLY {
int n; //n个点
TYPE *x, *y; //x,y为点的指针,首尾必须重合
POLY(): n(0), x(NULL), y(NULL) {};
POLY(int nn, const TYPE *xx, const TYPE *yy) {
n = nn;
x = new TYPE[n + 1];
memcpy(x, xx, n*sizeof(TYPE));
x[n] = xx[0];
y = new TYPE[n + 1];
memcpy(y, yy, n*sizeof(TYPE));
y[n] = yy[0];
}
};
//多边形顶点
POINT Vertex(const POLY &poly, int idx) {
// idx %= poly.n;
return POINT(poly.x[idx], poly.y[idx]);
}
//多边形的边
SEG Edge(const POLY &poly, int idx) {
// idx %= poly.n;
return SEG(POINT(poly.x[idx], poly.y[idx]), POINT(poly.x[idx + 1], poly.y[idx + 1]));
}
//多边形的周长
TYPE Perimeter(const POLY & poly) {
TYPE p = 0.0;
for (int i = 0; i < poly.n; ++i)
p += Distance(Vertex(poly, i), Vertex(poly, i + 1));
return p;
}
//求多边形面积
TYPE Area(const POLY & poly) {
if (poly.n < 3) return TYPE(0);
double s = poly.y[0] * (poly.x[poly.n - 1] - poly.x[1]);
for (int i = 1; i < poly.n; ++i) {
s += poly.y[i] * (poly.x[i - 1] - poly.x[(i + 1) % poly.n]);
}
return s/2;
}
//多边形的重心
POINT InCenter(const POLY & poly) {
TYPE S,Si,Ax,Ay;
POINT p;
Si = (poly.x[poly.n - 1] * poly.y[0] - poly.x[0] * poly.y[poly.n - 1]);
S = Si;
Ax = Si * (poly.x[0] + poly.x[poly.n - 1]);
Ay = Si * (poly.y[0] + poly.y[poly.n - 1]);
for(int i = 1; i < poly.n; ++i){
Si = (poly.x[i-1] * poly.y[i] - poly.x[i] * poly.y[i-1]);
Ax += Si * (poly.x[i-1] + poly.x[i]);
Ay += Si * (poly.y[i-1] + poly.y[i]);
S += Si;
}
S = S * 3;
return POINT(Ax/S,Ay/S);
}
//判断点是否在多边形上
bool IsOnPoly(const POLY &poly, const POINT &p) {
for(int i = 0; i < poly.n; ++i){
if( IsOnSeg(Edge(poly, i), p) ) return true;
}
return false;
}
//判断点是否在多边形内部
bool IsInPoly(const POLY &poly, const POINT &p) {
SEG L(p, POINT(Infinity, p.y));
int count = 0;
for (int i = 0; i < poly.n; i++) {
SEG S = Edge(poly, i);
if (IsOnSeg(S, p)) {
return true; //如果想让 在poly上则返回 true,
}
if(!IsEqual(S.a.y, S.b.y)) {
POINT & q = (S.a.y > S.b.y)?(S.a):(S.b);
if(IsOnSeg(L, q)) ++count;
else if(!IsOnSeg(L, S.a) && !IsOnSeg(L, S.b) && IsIntersect(S, L)) {
++count;
}
}
}
return (count % 2 != 0);
}
//判断是否简单多边形
bool IsSimple(const POLY & poly) {
if(poly.n < 3) return false;
SEG L1, L2;
for(int i = 0; i < poly.n - 1; ++i) {
L1 = Edge(poly, i);
for(int j = i + 1; j < poly.n; ++j) {
L2 = Edge(poly, j);
if(j == i + 1) {
if(IsOnSeg(L1, L2.b) || IsOnSeg(L2, L1.a)) return false;
}
else if(j == poly.n - i - 1) {
if (IsOnSeg(L1, L2.a) || IsOnSeg(L2, L1.b)) return false;
}
else if(IsIntersect(L1, L2)) return false;
} // for j
} // for i
return true;
}
// 点阵的凸包,返回一个多边形(求法一,已测试),不适用于点少于三个的情况
POLY ConvexHull(const POINT * set, int n) {
POINT * points = new POINT[n];
memcpy(points, set, n * sizeof(POINT));
TYPE * X = new TYPE[n];
TYPE * Y = new TYPE[n];
int i, j, k = 0, top = 2;
for(i = 1; i < n; ++i) {
if ((points[i].y < points[k].y) || ((points[i].y == points[k].y) && (points[i].x < points[k].x)))
k = i;
}
swap(points[0], points[k]);
for(i = 1; i < n - 1; ++i) {
k = i;
for(j = i + 1; j < n; ++j) {
if((Cross(points[j], points[k], points[0]) > 0) ||
((Cross(points[j], points[k], points[0]) == 0) &&
(Distance(points[0], points[j]) < Distance(points[0], points[k]))))
k = j;
}
swap(points[i], points[k]);
}
X[0] = points[0].x; Y[0] = points[0].y;
X[1] = points[1].x; Y[1] = points[1].y;
X[2] = points[2].x; Y[2] = points[2].y;
for(i = 3; i < n; i++) {
while(Cross(points[i], POINT(X[top], Y[top]),POINT(X[top - 1], Y[top - 1])) >= 0)
--top;
++top;
X[top] = points[i].x;
Y[top] = points[i].y;
}
delete [] points;
POLY poly(++top, X, Y);
delete [] X;
delete [] Y;
return poly;
}
// 点阵的凸包,返回一个多边形 (求法二,未测试)
bool cmp(const POINT& aa, const POINT& bb) {
if(aa.y != bb.y) return aa.y < bb.y;
else return aa.x < bb.x;
}
POLY ConvexHull2(const POINT * set, int n) {// 不适用于点少于三个的情况
POINT *a = new POINT[n];
memcpy(a, set, n * sizeof(POINT));
sort(a, a + n, cmp);
TYPE * X = new TYPE[n];
TYPE * Y = new TYPE[n];
X[0] = a[0].x;
Y[0] = a[0].y;
X[1] = a[1].x;
Y[1] = a[1].y;
int i,j;
for(i = 2, j = 2; i < n; ++i) {
X[j] = a[i].x;
Y[j] = a[i].y;
while(((X[j]-X[j-1]) * (Y[j-1]-Y[j-2]) - (Y[j]-Y[j-1]) * (X[j-1]-X[j-2])) >= 0 && j > 1) {
X[j-1] = X[j];
Y[j-1] = Y[j];
--j;
}
++j;
}
X[j] = a[n-2].x;
Y[j] = a[n-2].y;
++j;
for(i = n - 3; i >= 0; --i) {
X[j] = a[i].x;
Y[j] = a[i].y;
while(((X[j]-X[j-1]) * (Y[j-1]-Y[j-2]) - (Y[j]-Y[j-1]) * (X[j-1]-X[j-2])) >= 0) {
X[j-1] = X[j];
Y[j-1] = Y[j];
--j;
}
++j;
}
delete [] a;
POLY poly(j, X, Y);
delete [] X;
delete [] Y;
return poly;
}
int main() {
double a,b,c,l1,l2,l3,l4;
POINT d;
int n;
scanf("%d",&n);
while(n--)
{
scanf("%lf%lf%lf",&a,&b,&c);
TRIANGLE t=StdTRIANGLE(a,b,c);
d=fermentPONT(t);//费马点
l1=Distance(d,t.a)+Distance(d,t.b)+Distance(d,t.c);
d=incenter(t);//内心
l2=Distance(d,t.a)+Distance(d,t.b)+Distance(d,t.c);
d=InCenter(t);//重心
l3=Distance(d,t.a)+Distance(d,t.b)+Distance(d,t.c);
d=CcCenter(t);//外心
l4=Distance(d,t.a)+Distance(d,t.b)+Distance(d,t.c);
printf("%.3lf %.3lf %.3lf %.3lf\n",l1,l2,l3,l4);
}
return 0;
}
其他2:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Tpoint{
double x, y;
};
inline double length(Tpoint A, Tpoint B){
double x = A.x - B.x, y = A.y - B.y;
return sqrt(x * x + y * y);
}
inline double across(Tpoint A, Tpoint B, Tpoint C){
double x1 = C.x - A.x, x2 = C.x - B.x;
double y1 = C.y - A.y, y2 = C.y - B.y;
return x1 * y2 - x2 * y1;
}
double distance(Tpoint A, Tpoint B, Tpoint C){
return abs(across(A,B,C))/length(B,C);
}
//http://iask.sina.com.cn/b/14697945.html
int main(){
Tpoint A, B, C, cen;
while(true){
cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y;
/*
srand(time(0));
A.x = (double)rand()/rand(); A.y = (double)rand()/rand();
B.x = (double)rand()/rand(); B.y = (double)rand()/rand();
C.x = (double)rand()/rand(); C.y = (double)rand()/rand();
cout<<A.x<<' '<<A.y<<' '<<B.x<<' '<<B.y<<' '<<C.x<<' '<<C.y<<endl;*/
double a = length(B,C), b = length(C, A), c = length(A, B);
if(abs(across(A, B, C)) < 0.01) {cout<<"Wrong Input!"<<endl; continue;}
cen.x = (a * A.x + b * B.x + c * C.x)/(a + b + c);
cen.y = (a * A.y + b * B.y + c * C.y)/(a + b + c);
cout<<cen.x<<' '<<cen.y<<endl;
cout<<distance(cen, A, B)<<' '<<distance(cen, B, C)<<' '<<distance(cen, C, A)<<endl;
//cout<<abs(across(A, B, C))/(a + b + c)<<endl;
system("pause");
}
}
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Tpoint{
double x, y, z;
};
inline double length(Tpoint A, Tpoint B){
double x = A.x - B.x, y = A.y - B.y, z = A.z - B.z;
return sqrt(x * x + y * y + z * z);
}
inline double across(Tpoint A, Tpoint B, Tpoint C){
Tpoint p1, p2;
p1.x = C.x - A.x; p1.y = C.y - A.y; p1.z = C.z - A.z;
p2.x = C.x - B.x; p2.y = C.y - B.y; p2.z = C.z - B.z;
double x = p1.y * p2.z - p1.z * p2.y;
double y = p1.z * p2.x - p1.x * p2.z;
double z = p1.x * p2.y - p1.y * p2.x;
//cout<<x<<' '<<y<<' '<<z<<endl;
return sqrt(x * x + y * y + z * z);
}
double distance(Tpoint A, Tpoint B, Tpoint C){
return abs(across(A,B,C))/length(B,C);
}
void neijieyuan(Tpoint A, Tpoint B, Tpoint C){
Tpoint cen;
srand(time(0));
A.x = (double)rand()/rand(); A.y = -(double)rand()/rand();
B.x = -(double)rand()/rand(); B.y = (double)rand()/rand();
C.x = -(double)rand()/rand(); C.y = (double)rand()/rand();
cout<<A.x<<' '<<A.y<<' '<<B.x<<' '<<B.y<<' '<<C.x<<' '<<C.y<<endl;
double a = length(B,C), b = length(C, A), c = length(A, B);
//cout<<a<<' '<<b<<' '<<c<<endl;
if(abs(across(A, B, C)) < 0.01) {cout<<"Wrong Input!"<<endl;return;}
cen.x = (a * A.x + b * B.x + c * C.x)/(a + b + c);
cen.y = (a * A.y + b * B.y + c * C.y)/(a + b + c);
cen.z = (a * A.z + b * B.z + c * C.z)/(a + b + c);
cout<<cen.x<<' '<<cen.y<<' '<<cen.z<<endl;
cout<<distance(cen, A, B)<<' '<<distance(cen, B, C)<<' '<<distance(cen, C, A)<<endl;
}
int main(){
Tpoint A, B, C;
while(true){
//cin>>A.x>>A.y>>A.z>>B.x>>B.y>>B.z>>C.x>>C.y>>C.z;
//cout<<across(A, B, C)<<endl;
neijieyuan(A, B, C);
//cout<<abs(across(A, B, C))/(a + b + c)<<endl;
system("pause");
}
}
#include <stdio.h>
#include <math.h>
typedef struct TPoint
{
//平面点
double x;
double y;
}TPoint;
typedef struct TTriangle
{
TPoint t[2];
}TTriangle;
typedef struct TCircle
{
//圆
double r;
TPoint centre;
}TCircle;
double distance(const TPoint p1, const TPoint p2)
{
//计算平面上两个点之间的距离
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double triangleArea(const TTriangle t)
{
//已知三角形三个顶点的坐标,求三角形的面积
return fabs(t.t[0].x * t.t[1].y + t.t[1].x * t.t[2].y + t.t[2].x * t.t[0].y
- t.t[1].x * t.t[0].y - t.t[2].x * t.t[1].y - t.t[0].x * t.t[2].y) / 2;
}
TCircle circumcircleOfTriangle(const TTriangle t)
{
//三角形的外接圆
TCircle tmp;
double a, b, c, c1, c2;
double xA, yA, xB, yB, xC, yC;
a = distance(t.t[0], t.t[1]);
b = distance(t.t[1], t.t[2]);
c = distance(t.t[2], t.t[0]);
printf("a = %lf b = %lf, c = %lf\n", a, b, c);
//根据S = a * b * c / R / 4;求半径R
tmp.r = a * b * c / triangleArea(t) / 4;
xA = t.t[0].x; yA = t.t[0].y;
xB = t.t[1].x; yB = t.t[1].y;
xC = t.t[2].x; yC = t.t[2].y;
c1 = (xA * xA + yA * yA - xB * xB - yB * yB) / 2;
c2 = (xA * xA + yA * yA - xC * xC - yC * yC) / 2;
tmp.centre.x = (c1 * (yA - yC) - c2 * (yA - yB)) /
(xA - xB) * (yA - yC) - (xA - xC) * (yA - yB);
tmp.centre.y = (c1 * (xA - xC) - c2 * (xA - xB)) /
(yA - yB) * (xA - xC) - (yA - yC) * (xA - xB);
return tmp;
}
TCircle incircleOfTriangle(const TTriangle t)
{
//三角形的内接圆
TCircle tmp;
double a, b, c, angleA, angleB, angleC, p, p2, p3, f1, f2;
double xA, yA, xB, yB, xC, yC;
a = distance(t.t[0], t.t[1]);
b = distance(t.t[1], t.t[2]);
c = distance(t.t[2], t.t[0]);
printf("a = %lf b = %lf, c = %lf\n", a, b, c);
tmp.r = 2 * triangleArea(t) / (a + b +c);
angleA = acos((b * b + c * c - a * a) / (2 * b * c));
angleB = acos((a * a + c * c - b * b) / (2 * a * c));
angleC = acos((a * a + b * b - c * c) / (2 * a * b));
p = sin(angleA / 2);
p2 = sin(angleB / 2);
p3 = sin(angleC / 2);
xA = t.t[0].x; yA = t.t[0].y;
xB = t.t[1].x; yB = t.t[1].y;
xC = t.t[2].x; yC = t.t[2].y;
f1 = ((tmp.r / p2) * (tmp.r / p2) - (tmp.r / p) * (tmp.r / p) +
xA * xA - xB * xB + yA * yA - yB * yB) / 2;
f2 = ((tmp.r / p3) * (tmp.r / p3) - (tmp.r / p) * (tmp.r / p) +
xA * xA - xC * xC + yA * yA - yC * yC) / 2;
tmp.centre.x = (f1 * (yA - yC) - f2 * (yA - yB)) /
((xA - xB) * (yA - yC) - (xA - xC) * (yA - yB));
tmp.centre.y = (f1 * (xA - xC) - f2 * (xA - xB)) /
((yA - yB) * (xA - xC) - (yA - yC) * (xA - xB));
return tmp;
}
int main()
{
TTriangle t;
TCircle circumcircle, incircle;
while(scanf("%lf%lf%lf%lf%lf%lf",
&t.t[0].x, &t.t[0].y, &t.t[1].x, &t.t[1].y,
&t.t[2].x, &t.t[2].y) != EOF)
{
incircle = incircleOfTriangle(t);
circumcircle = circumcircleOfTriangle(t);
printf("%lf %lf \n", incircle.r, circumcircle.r);
printf("%.3lf\n", incircle.r / circumcircle.r);
}
return 0;
}

浙公网安备 33010602011771号