- qinkaiwen 的博客
计算几何基本模板归纳总结
- @ 2026-8-27 21:01:54
蒟蒻刚刚开始系统学习计算几何。所有的东西都学自这篇大佬的文章。(不过可能存在一些错误,代码已纠正)
后面有时间了应该会进行一些精修。
//sto command_block orz
#include<bits/stdc++.h>
using namespace std;
#define int long long
const double pi=acos(-1),eps=1e-8;
int sign(double x){return (x<-eps)?-1:(x>eps)?1:0;}//忽略浮点数精度误差
struct point//其实我们可以把一个点看作原点连向这个点的向量,这样对于计算几何来说相对容易理解一点
{
double x,y;
point operator+(point b){return {x+b.x,y+b.y};}
point operator-(point b){return {x-b.x,y-b.y};}
point operator*(double b){return {x*b,y*b};}
point operator/(double b){return {x/b,y/b};}
double operator|(point b){return x*b.x+y*b.y;}//内积(数量积)
double operator^(point b){return x*b.y-y*b.x;}//叉积
};
point rotate(point a,double rd)//将某个点绕原点逆时针旋转(幅角这里用弧度来表示,便于使用内置 sin 函数)
{
double s1=sin(rd),s2=cos(rd);
return {a.x*s2-a.y*s1,a.x*s1+a.y*s2};
/*
原向量 (x1,y1) -> (cosθ*l,sinθ*l),其中 θ 为原幅角,l 为原向量长度
新幅角 -> ɑ+θ,ɑ 为旋转幅角(rd)
新向量长度不变,等价于 -> (cos(ɑ+θ)*l,sin(ɑ+θ)*l)
用三角恒等变换 -> ((cosθcosɑ-sinθsinɑ)*l,(sinθcosɑ+sinɑcosθ)*l)
*/
}
double dis(point p1,point p2){return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}//距离公式
struct line
{
point a,b;
double len(){return dis(a,b);}
};
bool onl0(point a,line l)//判断一个点是否在一条直线上
{
return sign((a-l.a)^(a-l.b))==0;
//三点共线也同时意味着这三点形成的三角形面积为 0,直接判断叉积即可
}
bool onl2(point a,line l)//判断一个点是否在一个线段上
{
return onl0(a,l)&&//首先你肯定要共线
sign(a.x-min(l.a.x,l.b.x))>=0&&
sign(a.y-min(l.a.y,l.b.y))>=0&&
sign(a.x-max(l.a.x,l.b.x))<=0&&
sign(a.y-max(l.a.y,l.b.y))<=0;//然后判断这个点是否位于这条线所处的矩形内
}
point inter(line l1,line l2)
{
double ls=(l1.b-l1.a)^(l2.a-l1.a);//算出左半三角形的面积的 2 倍
double rs=(l1.b-l1.a)^(l2.b-l1.a);//算出右半三角形的面积的 -2 倍
return l2.a+(l2.b-l2.a)*ls/(ls-rs); //根据面积比算出对应向量的长度,用 l2 左端点加上就是交点(原笔记上的记成了 l1,在这里予以更正)
}
double disl0(point a,line l)//计算一个点到一条直线的最短距离
{
return abs((l.a-a)^(l.b-a)/l.len());
//计算三个点的三角形面积除去直线长度即为垂线段长度(即所求距离)
}
double disl2(point a,line l)//计算一个点到一条线段的最短距离
{
if(sign((a-l.a)|(l.b-l.a))<0||sign((a-l.b)|(l.a-l.b))<0)
return min(dis(a,l.a),dis(a,l.b));
//计算点 A 连向线段的两个与线段的夹角是否有一个为钝角,这里只需要判断两个内积是否有一个为负就行了。
return disl0(a,l);
}
signed main()
{
//完全胜利!!!
return 0;
}
//completed: 2026/8/27 21:00
无注释版:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const double pi=acos(-1),eps=1e-8;
int sign(double x){return (x<-eps)?-1:(x>eps)?1:0;}
struct point
{
double x,y;
point operator+(point b){return {x+b.x,y+b.y};}
point operator-(point b){return {x-b.x,y-b.y};}
point operator*(double b){return {x*b,y*b};}
point operator/(double b){return {x/b,y/b};}
double operator|(point b){return x*b.x+y*b.y;}
double operator^(point b){return x*b.y-y*b.x;}
};
point rotate(point a,double rd)
{
double s1=sin(rd),s2=cos(rd);
return {a.x*s2-a.y*s1,a.x*s1+a.y*s2};
}
double dis(point p1,point p2){return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}
struct line
{
point a,b;
double len(){return dis(a,b);}
};
bool onl0(point a,line l)
{
return sign((a-l.a)^(a-l.b))==0;
}
bool onl2(point a,line l)
{
return onl0(a,l)&&
sign(a.x-min(l.a.x,l.b.x))>=0&&
sign(a.y-min(l.a.y,l.b.y))>=0&&
sign(a.x-max(l.a.x,l.b.x))<=0&&
sign(a.y-max(l.a.y,l.b.y))<=0;
}
point inter(line l1,line l2)
{
double ls=(l1.b-l1.a)^(l2.a-l1.a);
double rs=(l1.b-l1.a)^(l2.b-l1.a);
return l2.a+(l2.b-l2.a)*ls/(ls-rs);
}
double disl0(point a,line l)
{
return abs((l.a-a)^(l.b-a)/l.len());
}
double disl2(point a,line l)
{
if(sign((a-l.a)|(l.b-l.a))<0||sign((a-l.b)|(l.a-l.b))<0)
return min(dis(a,l.a),dis(a,l.b));
return disl0(a,l);
}
signed main()
{
return 0;
}