知识点 - 计算几何向量版
简版 包含基本向量操作
struct V {
double x, y;
V() {}
void sc() { scanf("%lf%lf", &x, &y); }
V(double a, double b) : x(a), y(b) { }
V operator+(V o) { return V(x + o.x, y + o.y); }
V operator-(V o) { return V(x - o.x, y - o.y); }
double L() { return sqrt(x * x + y * y); }
V N() {
double l = L();
return V(x / l, y / l);
}
V rot(double th) { return V(x * cos(th) - y * sin(th), x * sin(th) + y * cos(th)); }
V operator*(double z) { return V(x * z, y * z); }
double operator*(V o) { return x * o.x + y * o.y; }
double operator|(V o) { return x * o.y - o.x * y; }
void pr() { printf("%lf %lf\n", x, y); }
} p[maxn];
简版的凸包
bool cmpr(V const &a, V const &b) {//cmpr必要时加上长度排序
V v1 = a - st[0], v2 = b - st[0];
return (v1 | v2) < -eps;
}
vector<V> ch;
void getCH() {
sort(st + 1, st + n, cmpr);
ch.push_back(st[0]);
rep(i, 1, n-1) {
while (ch.size() > 1 && (st[i] - ch.back() | ch.back() - ch[ch.size() - 2]) < eps)ch.pop_back();
ch.push_back(st[i]);
}
}
int out(int x) { return x ? x - 1 : ch.size() - 1; }
int in(int x) { return x + 1 == (int)ch.size() ? 0 : x + 1; }
三维向量
const double PI = acos(-1.0);
struct V3 {
db x, y, z;
V3() {}
V3(db xx, db yy, db zz) :x(xx), y(yy), z(zz) {}
void sc() {scanf("%lf%lf%lf", &x, &y, &z);}
db L() { return sqrt(x*x + y * y + z * z); }
V3 N() { db l = L(); return V3(x / l, y / l, z / l); }
V3 operator+(V3 o) { return V3(x + o.x, y + o.y,z+o.z); }
V3 operator-(V3 o) { return V3(x - o.x, y - o.y,z-o.z); }
V3 operator*(db zz) { return V3(x * zz, y * zz,z*zz); }
db operator*(V3 o) { return x * o.x + y * o.y+z*o.z; }
V3 operator|(V3 o) { return V3(y*o.z-z*o.y,z*o.x-x*o.z,x * o.y - o.x * y); }
};
const double eps = 1e-8;
int sgn(db x) {
if (fabs(x) < eps)return 0;
else if (x > 0)return 1;
else return -1;
}
struct L3 {
V3 s, e;
L3() {}
L3(V3 ss, V3 ee) :s(ss), e(ee) {}
V3 rot(V3 n, db theta) {
if (sgn(((s - n) | (e - n)).L()) == 0)return n;
V3 f1 = (e - s) | (n - s);
V3 f2 = (e - s) | (f1);
db len = ((s - n) | (e - n)).L() / (s - e).L();
f1 = f1.N()*len; f2 = f2.N() * len;
V3 h = n + f2;
V3 nn = h + f1;
return h + ((n - h)*cos(theta)) + ((nn - h)*sin(theta));
}
};
用复数的全功能版
//若想加速可以用上面的 V代替复数 可以加速2~5倍
/*
typedef V point;
V conj(V p) {return V(p.x, -p.y);}
double arg(V p) { return atan2(p.y, p.x); }
double norm(V p) { return p.L()*p.L(); }
double abs(V p) { return p.L(); }
*/
typedef complex<double> point;
#define Decimal fixed<<setprecision(20)
#define PB push_back
#define EB emplace_back
#define X real();
#define Y imag();
#define curr(PP,i) PP[i]
#define next(PP,i) PP[(i+1)%PP.size()]
#define diff(PP,i) (next(PP,i)-curr(PP,i))
const double eps = 1e-7;
const double PI = acos(-1.0);
const double INF = 1e18;
int n;
vector<point> V;
double sumS,nowS,mx,mn;
double cross(const point& a, const point& b) {
return imag(conj(a)*b);
}
double dot(const point& a, const point& b) {
return real(conj(a)*b);
}
double area(const vector<point>& p) {
double A = 0;
F(i, p.size()) A += cross(curr(p, i), next(p, i));
return A / 2.;
}
double triangleArea(V a, V b, V c) {
return abs((a - b) | (a - c)) / 2.;
}
typedef pair<V, V> segment;
point projection(const segment &l, const point &p) {
double t = (p - l.fi)*( l.fi - l.se) / norm(l.fi - l.se);
return l.fi + (l.fi - l.se)*t;
}
bool intersectSP(const segment &s, const point &p) {return abs(s.fi - p) + abs(s.se - p) - abs(s.se - s.fi) < eps;}
bool intersectLP(const segment &l, const point &p) { return eq((l.first - p) | (l.second - p), 0); }
bool intersectLL(const segment &l, const segment &m) {
return eq((l.first - l.second) | (m.first - m.second),0) || eq((l.first - l.second) | (l.first - m.second),0);
}
bool intersectLS(const segment &l, const segment &s) {
return ((l.first - l.second) | (s.first - l.first))*((l.first - l.second) | (s.second - l.first))<eps;
}
int ccw(point a, point b, point c) {
b =b- a, c =c- a;
if ((b | c) > 0)return 1;//counter-clockwise
if ((b | c) < 0)return -1;
if (b*c < 0)return 2;//b-a-c /c-a-b
if (norm(b) < norm(c))return -2;//a-b-c/b-c-a
return 0;//a-c-b/b-c-a
}
bool intersectSS(const segment &s, const segment &t) {
return ccw(s.first, s.second, t.first)*ccw(s.first, s.second, t.first) <= 0 &&
ccw(t.first, t.second, s.first)*ccw(t.first, t.second, s.second) <= 0;
}
double distancePP(const point &a, const point &b) { return abs(a - b); }
double distanceLP(const segment &l, const point &p) { return abs(p-projection(l,p)); }
double distanceSP(const segment &s, const point &p) {
const point r = projection(s, p);
if (intersectSP(s, r))return abs(r - p);
return min(abs(s.fi-p),abs(s.se-p));
}
point crosspoint(segment const &l, segment const &m) {
double A = (l.second - l.first)|( m.second - m.first);
double B = (l.second - l.first) | (l.second - m.first);
if (abs(A) < eps&&abs(B) < eps)return m.fi;//same line
if (abs(A) < eps)return point(INF, INF);//parallel
return m.fi + (m.se - m.fi)*(B / A);
}
double angle(const point& a, const point& b) {
auto tmp = abs(arg(a) - arg(b));
return min(tmp, 2 * PI - tmp);
}
double angle(const segment &s1, const segment &s2) {
return angle(s1.second - s1.first, s2.second - s2.first);
}
point reflection(const segment &l, const point &p) {return p + (projection(l, p)-p) * 2.;}
圆
暂时只包含圆圆交
typedef V point;
struct circle
{
point c;
ld r, v;
circle() {}
circle(point c, ld r, ld v) :c(c), r(r), v(v) {}
inline point pt(double a)
{
return point(c.x + cos(a)*r, c.y + sin(a)*r);
}
};
int getCircleCircleIntersection(circle C1, circle C2, point &t1, point &t2)
{
ld d = abs(C1.c - C2.c);
if (dcmp(d) == 0)
{
if (dcmp(C1.r - C2.r) == 0) return -1;// same cir
return 0;// include
}
if (dcmp(C1.r + C2.r - d) < 0) return 0;// disjoint
if (dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;// include
ld a = arg(C2.c - C1.c);
ld da = acos((C1.r*C1.r + d * d - C2.r*C2.r) / (2 * C1.r*d));
point p1 = C1.pt(a - da), p2 = C1.pt(a + da);
t1 = p1;
if (p1 == p2) return 1;
t2 = p2;
return 2;
}