文章目录
计算几何概念
计算几何研究的对象是几何图形,早期人们对于图像的研究一般都是先建立坐标系,把图形转换成函数,然后用插值和逼近的数学方法,特别是用样条函数作为工具来分析图形。——百度百科
向量的基本运算
向量概念
在数学中,向量指具有大小和方向的量。
向量可以在坐标系内进行运算。
向量加法
设向量 ∣ O P ∣ |OP| ∣OP∣为 ( x 1 , y 1 ) (x_1,y_1) (x1,y1), ∣ O Q ∣ |OQ| ∣OQ∣为 ( x 2 , y 2 ) (x_2,y_2) (x2,y2),则 ∣ O P ∣ + ∣ O Q ∣ = ( x 1 + x 2 , y 1 + y 2 ) |OP|+|OQ|=(x_1+x_2,y_1+y_2) ∣OP∣+∣OQ∣=(x1+x2,y1+y2)
向量减法
设法同上,则 ∣ O P ∣ − ∣ O Q ∣ = ( x 1 − x 2 , y 1 − y 2 ) |OP|-|OQ|=(x_1-x_2,y_1-y_2) ∣OP∣−∣OQ∣=(x1−x2,y1−y2)
向量叉积
设法同上,则它们两叉积的大小
∣
O
P
∣
×
∣
O
Q
∣
=
x
1
y
2
−
x
2
y
1
|OP|×|OQ|=x_1y_2-x_2y_1
∣OP∣×∣OQ∣=x1y2−x2y1
其中叉积的几何意义为两向量通过平行构成平行四边形的面积(可能为负数)
如何判断位置关系
快速排斥实验:判断线段构成的矩形是否交
跨立实验:判断两点是否在线段的两端
快速排斥实验code:
double js(abc p1, abc p2, abc p3)
{
return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
bool online(abc p1, abc p2, abc p3)
{
if(p3.x>=min(p1.x, p2.x)&&p3.x<=max(p1.x, p2.x)&&
p3.y>=min(p1.y, p2.y)&&p3.y<=max(p1.y, p2.y))
return 1;
else return 0;
}
跨立实验code:
bool check(abc p1, abc p2, abc p3, abc p4)
{
if(js(p3, p4, p1)*js(p3, p4, p2)<0&&js(p1, p2, p3)*js(p1, p2, p4)<0)
return 1;
else if(js(p3, p4, p1)==0&&online(p3, p4, p1))
return 1;
else if(js(p3, p4, p2)==0&&online(p3, p4, p2))
return 1;
else if(js(p1, p2, p3)==0&&online(p1, p2, p3))
return 1;
else if(js(p1, p2, p4)==0&&online(p1, p2, p4))
return 1;
return 0;
}
判断点是否在线段上
设线段 ∣ O P ∣ |OP| ∣OP∣,点 Q Q Q,则如果 ∣ O Q ∣ × ∣ O P ∣ = 0 |OQ|×|OP|=0 ∣OQ∣×∣OP∣=0,且满足快速排斥实验,则点 Q Q Q在线段 O P OP OP上
判断线段和线段是否相交
设线段
Q
1
Q
2
,
P
1
P
2
Q1Q2,P1P2
Q1Q2,P1P2,则如果满足
(
P
1
−
Q
1
)
×
(
P
2
−
Q
1
)
∗
(
P
1
−
Q
2
)
×
(
P
2
−
Q
2
)
<
0
(P1-Q1)×(P2-Q1)*(P1-Q2)×(P2-Q2)<0
(P1−Q1)×(P2−Q1)∗(P1−Q2)×(P2−Q2)<0,那么线段
P
1
P
2
P1P2
P1P2跨立
Q
1
Q
2
Q1Q2
Q1Q2
特殊的,如果交点为线段端点,则满足点是否在线段上则相交
判断直线和线段是否相交
则只需要判断线段是否跨立直线即可
code:
double js(abc p1, abc p2, abc p3)
{
return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);
}
bool check(abc p1, abc p2, abc p3, abc p4)
{
if(js(p1, p3, p2)*js(p1, p2, p4)>=0)
return 1;
return 0;
}
多边形面积
将多边形上点一一连起构成三角形,通过叉积算出每个三角形面积,然后相加
凸包
凸包概念
在平面内能把所有点围起来的周长最小的多边形
凸包算法
Andrew算法
先选出凸包上必定存在的一点,按照级角大小排序,模拟一条直线将凸包上的点一一算出。(由于电脑不能模拟直线旋转,则直接按照级角坐标排序后来选择)
code:(暂无)
Graham算法
同样选出凸包上一点,按照级角坐标排序,一一遍历点,通过判断旋转方向是否发生改变,用单调栈存储所有凸包上的点
code:
sort(p+2, p+1+n, cmp);
s[1]=1, top=1;
for(long long i=2; i<=n; i++)
{
while(top>1&&cj(p[s[top-1]].x, p[s[top-1]].y, [s[top]].x, p[s[top]].y, p[i].x, p[i].y)<=0)
top--;
s[++top]=i;
}
旋转卡壳
选取凸包上一边,再在此凸包上选出与之构成三角形面积最大的一点,做此边的平行线穿过此点,则两条边正好将凸包卡住
code:(暂无)
判断点和线段是否在多边形内
设一条线从无限远的地方穿过此点,通过计算与多边形边的交点,得出是否在多边形内
设线段与多边形的边交于许多点,如果两个交点的中点也在多边形内,则线段在多边形内
未完继续~