计算几何
计算几何基础
0.公式
三角形:
1. 半周长
2. 面积
3. 中线
4. 角平分线
5. 高线
6. 内切圆半径
7. 外接圆半径
四边形:
D1,D2为对角线,M对角线中点连线,A为对角线夹角
,P为半周长
(以下对圆的内接四边形)
1.
2.
3.
4.
正n边形:
R为外接圆半径,r为内切圆半径
1. 中心角
2. 内角
3. 边长
4. 面积
圆:
1. 弧长
2. 弦长
3. 弓形高
4. 扇形面积
5. 弓形面积
棱柱:
1. 体积
2. 侧面积
3. 全面积
棱锥:
,A为底面积,h为高
,l为棱长,p为直截面周长
1. 体积
A为底面积,h为高
,l为斜高,p为底面周长
,A1.A2为上下底面积,h为高
为上下底面周长,l为斜高
(以下对正棱锥)
2. 侧面积
3. 全面积
棱台:
1. 体积
(以下为正棱台)
2. 侧面积
3. 全面积
圆柱:
1. 侧面积
2. 全面积
3. 体积
圆锥:
1. 母线
2. 侧面积
3. 全面积
4. 体积
圆台:
1. 母线
2. 侧面积
3. 全面积
4. 体积
球:
1. 全面积
2. 体积
球台:
1. 侧面积
2. 全面积
3. 体积
球扇形:
1. 全面积
2. 体积
,h为球冠高,r0为球冠底面半径
1.常量、基础函数
#include
#include
#include
using namespace std;
const double pi = 3.1415926535898;
const double eps = 1e-8;
inline int fcmp(double x,double y) //浮点比较
{
if(fabs(x-y) < eps) return 0;
else return x > y ? 1 : -1;
}
inline double sqr(double x) //浮点平方
{
return x * x;
}
inline double Sqrt(double x)
{
return x <= 0 ? 0 : sqrt(x);
}
inline int abs(int x)
{
return x >= 0 ? x : -x;
}
int main()
{
double x;
int fx = floor(x); //向下取整
int cx = ceil(x); //向上取整
int rx = round(x); //四舍五入
}
2.二维点、向量
2.1 二维点类
struct Point
{
double x, y, ang;
Point(){}
Point(double a, double b): x(a), y(b) {}
friend Point operator + (const Point &a, const Point &b){
return Point(a.x + b.x, a.y + b.y);
}
friend Point operator - (const Point &a, const Point &b){
return Point(a.x - b.x, a.y - b.y);
}
friend bool operator == (const Point &a, const Point &b){
return fcmp(a.x,b.x) == 0 && fcmp(a.y,b.y) == 0;
}
friend Point operator * (const Point &a, const double &b){
return Point(a.x * b, a.y * b);
}
friend Point operator * (const double a,const Point &b){
return Point(a * b.x, a * b.y);
}
friend Point operator / (const Point &a, const double &b){
return Point(a.x / b, a.y / b);
}
friend bool operator < (const Point &a,const Point &b){
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
friend double norm(const Point &a){
return sqrt(sqr(a.x) + sqr(a.y));
}
void calcangle() {ang = atan2(y,x);}
};
2.2 向量
既有大小又有方向的量叫向量
通常用坐标表示
鉴于以上两点,向量可以用二维点类表示。
2.2.1向量运算
1. 内积
向量夹角为锐角,内积为正
向量夹角为钝角,内积为负
向量夹角为直角,内积为0
inline double dot(const Point &a,const Point &b) //内积
{
return a.x * b.x + a.y * b.y;
}
2. 叉积
根据右手定则
若
若
若
B在A的顺时针方向
B与A共线
B在A的逆时针方向
inline double det(const Point &a,const Point &b) //外积
{
return a.x * b.y - a.y * b.x;
}
3.两点间距离(向量长度)
inline double dist(const Point &a,const Point &b) //两点间距离
{
return (a - b).norm();
}
4.两向量夹角(弧度)
inline double angle(const Point &a,const Point &b) //向量夹角
{
return acos(dot(a,b) / norm(a) / norm(b));
}
5.向量绕原点逆时针旋转A(弧度)
inline Point rotate_point(const Point &p,double A) //计算点p绕原点逆时针旋转
A(弧度)
{
return Point(p.x * cos(A) - p.y * sin(A),p.x * sin(A) - p.y * cos(A));
}
6.计算两向量构成的平行四边形有向面积
inline double area2(const Point a,const Point &b) //计算两向量构成的有向面积
{
return det(a,b);
}
2.3 点与线
2.3.1 直线线段类
struct Line
{
Point s, t;
double ang; //直线极角
Line(){};
Line(Point a,Point b) : s(a) , t(b) {}
Line(Point p,double ang) //根据一个点和一个角(弧度制,0 <= ang < pi) 确定直线
{
s = p;
if(sgn(ang - pi / 2) == 0) t = (s + Point(0,1));
else t = s + Point(1,tan(ang));
}
Line(double a,double b,double c) // ax + by + c = 0
{
if(sgn(a) == 0){s = Point(0,-c/b); t = Point(1,-c/b);}
else if(sgn(b) == 0){s = Point(-c/a,0); t = Point(-c/a,1);}
else{s = Point(0,-c/b); t = Point(1,(-c-a)/b);}
}
void calcangle() {ang = atan2((t - s).y, (t - s).x);} //计算直线极角
};
2.3.2 点与线关系计算
1.点到直线距离
inline double dis_point_line(const Point &p,const Point s,const Point &t)
//计算点到直线距离
{
return fabs(det(s-p,t-p) / dist(s,t));
}
2. 点到线段距离
若投影不在线段内,则距离为点到端点距离
inline double dis_point_segment(const Point &p,const Point &s,const Point
&t) //计算点到线段距离
{
if(sgn(dot(p-s,t-s)) < 0) return norm(p-s);
if(sgn(dot(p-t,s-t)) < 0) return norm(p-t);
return fabs(det(s-p,t-p) / dist(s,t));
}
3.判断点相对直线的方向
inline int point_on_line(const Point &p,const Point &s,const Point &t)
//判断p位于直线的哪一边
{
//位于s的逆时针方向返回-1
//位于s的顺时针方向返回1
//在直线上返回0
return sgn(det(p-s,t-s));
}
4.判断点p是否位于线段上(包括端点)
inline bool point_on_segment(const Point &p,const Point &s,const Point &
t)
{
return (sgn(det(p-s,t-s)) == 0 && sgn(dot(p-s,p-t)) <= 0);
}
5.计算点p于直线的投影,计算两点中垂线
定比分点
inline Point point_proj_line(const Point &p,const Point &s,const Point &
t)
{
double r = dot((t-s),(p-s)) / dot(t-s,t-s);
return s + r * (t - s);
}
inline Line get_mid_line(const Point &a, const Point &b) //计算线段ab的中垂
线
{
Point mid = (a + b) / 2;
Point tp = b-a;
return Line(mid,mid+Point(-tp.y,tp.x));
}
6.判断两直线是否平行
若平行,两直线向量叉乘结果为0
inline bool parallel(const Line &A,const Line &B) //判断两直线是否平行
{
return !sgn(det(A.s-A.t,B.s-B.t));
}
7.计算两直线交点,若存在,保存在res中
用到了定比分点公式的坐标形式