intmain(){ db x = 0.4999; int fx = floor(x);//向下取整 int cx = ceil(x);//向上取整 int rx = round(x);//四舍五入 printf("%f %d %d %d\n", x, fx, cx, rx); //0.499900 0 1 0 return0; }
2. 点和向量
2.1 点和向量的定义
1 2 3 4 5 6 7 8 9 10 11 12
structPoint { db x, y;
Point() {}
Point(db _x, db _y) { x = _x; y = _y; } };
2.2 相关运算
2.2.1 加法
点和向量相加得到另一个点
向量和向量相加得到另一个向量
1 2 3 4 5
Point operator+(const Point &other) const { return {x + other.x, y + other.y}; }
2.2.2 减法
两点差得到一个向量
A−B得到向量BA
1 2 3 4 5
Point operator-(const Point &other) const { return {x - other.x, y - other.y}; }
2.2.3 乘法
缩放
1 2 3 4 5
Point operator*(const db &other) const { return {x * other, y * other}; }
2.2.4 除法
缩放
1 2 3 4 5
Point operator/(const db &other) const { return {x / other, y / other}; }
2.2.5 点积
α⋅β=∣α∣⋅∣β∣⋅cosθ
几何意义
若α与β的夹角为锐角,则其点积为正
若α与β的夹角为钝角,则其点积为负
若α与β的夹角为支教,则其点积为0
向量α在β上的投影长度和β的长度乘积
1 2 3 4 5
db operator*(const Point &other) const { return x * other.x + y * other.y; }
2.2.6 叉积
α⋅β=∣α∣⋅∣β∣⋅sinθ
几何意义:
若β在α的逆时针方向,叉积为正
若β在α的顺时针方向,叉积为负
若β在α平行,叉积为0
向量α和向量β形成的平行四边形的有向面积
1 2 3 4 5
db operator^(const Point &other) const { return x * other.y - y * other.x; }
2.3 常用函数(成员函数)
2.3.1 两点距离
1 2 3 4 5
db distance(Point p){ return hypot(x - p.x, y - p.y); }
2.3.2 逆时针旋转90度
1 2 3 4 5
Point rotleft(){ return {-y, x}; }
2.3.3 顺时针旋转90度
1 2 3 4 5
Point roright(){ return {y, -x}; }
2.3.4 绕着点P逆时针旋转angle
1 2 3 4 5 6 7
Point rotate(Point p, db angle){ Point v = (*this) - p; db c = cos(angle), s = sin(angle); return {p.x + v.x * c - v.y * s, p.y + v.x * s + v.y * c}; }
2.3.5 ToLeftTest 函数
判断bc是不是想两ab的逆时针方向旋转 凸包
1 2 3 4 5
boolToLeftTest(Point a, Point b, Point c){ return ((b - a) ^ (c - b)) > 0; }
Line(Point p, db angle) { s = p; if (sgn(angle - PI / 2) == 0) { e = (s + Point(0, 1)); } else { e = (s + Point(1, tan(angle))); } }
//ax + by + c = 0 Line(db a, db b, db c) { if (sgn(a) == 0) { s = Point(0, -c / b); e = Point(1, -c / b); } elseif (sgn(b) == 0) { s = Point(-c / a, 0); e = Point(-c / a, 1); } else { s = Point(0, -c / b); e = Point(1, (-c - a) / b); } } };
3.1.2 常用函数
3.1.2.1 点和直线的关系
1 2 3 4 5 6 7 8 9 10 11 12
//点和直线关系 //1 在左侧 //2 在右侧 //3 在直线上 intrelation(Point p){ int c = sgn((p - s) ^ (e - s)); if (c < 0) return1; elseif (c > 0) return2; elsereturn3; }
// 3 点上 // 2 边上 // 1 内部 // 0 外部 intrelationpoint(Point q){ for (int i = 0; i < n; ++i) { if (p[i] == q) return3; } getline(); for (int i = 0; i < n; ++i) { if (l[i].pointonseg(q)) { return2; } } int cnt = 0; for (int i = 0; i < n; ++i) { int j = (i + 1) % n; int k = sgn((q - p[j]) ^ (p[i] - p[j])); int u = sgn(p[i].y - q.y); int v = sgn(p[j].y - q.y); if (k > 0 && u < 0 && v >= 0) cnt++; if (k < 0 && v < 0 && u >= 0) cnt++; } return cnt != 0; }
4.2.1.2 获取周长
1 2 3 4 5 6 7 8 9
db getcircumferenct(){ db sum = 0; for (int i = 0; i < n; ++i) { sum += p[i].distance(p[(i + 1) % n]); } return sum; }
4.2.1.3 获取面积
1 2 3 4 5 6 7 8 9
db getarea(){ db sum = 0; for (int i = 0; i < n; ++i) { sum += (p[i] ^ (p[(i + 1) % n])); } returnfabs(sum / 2); }
4.2.1.4 获取重心
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Point getbarycentre(){ Point ret = {0, 0}; db area = 0; for (int i = 1; i < n - 1; ++i) { db tmp = (p[i] - p[0]) ^(p[i + 1] - p[0]); if (sgn(tmp) == 0) continue; area += tmp; ret.x += (p[0].x + p[i].x + p[i + 1].x) / 3 * tmp; ret.y = (p[0].y + p[i].y + p[i + 1].y) / 3 * tmp; } if (sgn(area)) ret = ret / area; return ret; }