1.前置知识:
(1)π=acos(-1)
(2)余弦定理:c^2=a^2+b^2-2abcosθ
2.浮点数的比较:
eps=1e-8
def sign(x):
if abs(x)<eps:
return 0
return -1 if x<0 else 1
def cmp(x,y):
if abs(x-y)<eps:
return 0
return -1 if x<y else 1
3.向量
class Vector():
def __init__(self,x,y):
self.x=x
self.y=y
def __add__(self,other):
return Vector(self.x+other.x,self.y+other.y)
def __sub__(self,other):
return Vector(self.x-other.x,self.y-other.y)
def __mul__(self,num:int or float):
return Vector(self.x*num,self.y*num)
def __truediv__(self,num:int or float):
return Vector(self.x/num,self.y/num)
Point=Vector
3.1.向量的加减法和数乘运算
3.2 内积(点积) A·B = |A||B|cos(θ)
(1) 几何意义:向量A在向量B上的投影与B的长度的乘积。
(2) 代码实现
def dot(a:Vector,b:Vector):
return a.x*b.x+a.y*b.y
3.3 外积(叉积) AxB = |A||B|sin(θ)
(1) 几何意义:向量A与B张成的平行四边形的有向面积。B在A的逆时针方向为正。
(2) 代码实现
def cross(a:Vector,b:Vector):
return a.x*b.y-b.x*a.y
3.4 常用函数
3.4.1 取模
def get_length(a:Vector):
return sqrt(bot(a,a))
3.4.2 计算向量夹角
def get_angle(a:Vector,b:Vector):
return acos(dot(a,b)/get_length(a)/get_length(b))
3.4.3 计算两个向量构成的平行四边形有向面积
def area(a:Point,b:Point,c:Point):
return cross(b-a,c-a)
3.4.5 向量A顺时针旋转C的角度:
def rotate(a:Vector,angle:int or float):
return Point(a.x*cos(angle)+a.y*sin(angle),-a.x*sin(angle)+a.y*cos(angle))
4.点与线
4.1直线定理
(1) 一般式 ax + by + c = 0
(2) 点向式 p0 + vt
(3) 斜截式 y = kx + b
4.2 常用操作
(1) 判断点在直线上 A x B = 0
(2) 两直线相交
// cross(v,w)==0则两直线平行或者重合
def get_intersection(p:Point,v:Vector,q:Point,w:Vector):
u=q-p
t=cross(w,u)/cross(v,w)
return p+v*t
(3) 点到直线的距离
def distance_to_line(p:Point,a:Point,b:Point):
v1=b-a;v2=p-a
return abs(cross(v1,v2)/get_length(v1))
(4) 点到线段的距离
def distance_to_segment(p:Point,a:Point,b:Point):
if a==b:
return get_length(p-a)
v1=b-a;v2=p-a;v3=p-b
if sign(dot(v1,v2))<0:
return get_length(v2)
if sign(dot(v1,v3))>0:
return get_length(v3)
return distance_to_line(p,a,b)
(5) 点在直线上的投影
def get_line_projection(p:Point,a:Point,b:Point):
v=b-a
return v*(dot(v,p-a)/dot(v,v))
(6) 点是否在线段上
def on_segment(p:Point,a:Point,b:Point):
return sign(cross(p-a,p-b))==0 and sign(dot(p-a,p-b))<=0
(7) 判断两线段是否相交
def segment_intersection(p:Point,a:Point,b:Point):
c1=cross(a2-a1,b1-a1);c2=cross(a2-a1,b2-a1)
c3=cross(b2-b1,a1-b1);c4=cross(b2-b1,a2-b1)
return sign(c1)*sign(c2)<=0 and sign(c3)*sign(c4)<=0