【Python】点集凸包Numpy实现(补充版)
2018-03-23 19:52
477 查看
1. 矢量减法
设二维矢量 P=(x1,y1),Q=(x2,y2)
则矢量减法定义(对应位相减)为: P−Q=(x1−x2,y1−y2)
显然有性质 P−Q=−(Q−P)
如不加说明,下面所有的点都看作矢量,两点的减法就是矢量相减;
def sub(p, q): return p-q p, q = np.array([1, 2]), np.array([3, 5]) print(sub(p, q)) print(-sub(q, p))1
2
3
4
5
2. 矢量叉积
设矢量P=(x1,y1),Q=(x2,y2)(本文以二维为例,可自然推广到三维)
则矢量叉积定义为: P×Q=x1∗y2−x2∗y1 得到的是一个标量
显然有性质 P×Q=−(Q×P),P×(−Q)=−(P×Q)
如不加说明,下面所有的点都看作矢量,点的乘法看作矢量叉积;
叉乘的重要性质:
若 P × Q > 0 , 则P 在Q的顺时针方向
若 P × Q < 0 , 则P 在Q的逆时针方向(与性质1等价)
若 P × Q = 0 , 则P 与Q共线,但可能同向也可能反向
def cross_prod(p, q): assert len(p)==2 and len(q)==2 return p[0]*q[1]-p[1]*q[0] p, q = np.array([1, 0]), np.array([0, 1]) # p在q的顺时针方向 print(cross_prod(p, q)) # 1>0 p, q = np.array([1, 2], [2, 4]) # p, q 同向 print(cross_prod(p, q)) # 01
2
3
4
5
6
7
8
9
10
11
3. 判断点在线段上
设点为Q,线段为P1P2 ,判断点Q在该线段上的依据是:
(Q−P1)×(P2−P1)=0 且 Q 在以 P1,P2 为对角顶点的矩形内;
这是叉积性质的直接应用,也即(Q−P1)×(P2−P1)=0,则 Q−P1与P2−P1共线;
def is_point_on_line(q, p1, p2): return True if cross_prod(q-p1, p2-p1)==0 else False p1, p2 = np.array([1, 0]), np.array([0, 1]) q = np.array([1/2, 1/2]) print(is_point_on_line(q, p1, p2)) # True q = np.array([1/2, 1/3]) print(is_point_on_line(q, p1, p2)) # False1
2
3
4
5
6
7
8
9
4. 判断两线段是否相交
我们分两步确定两条线段是否相交:快速排斥试验
设以线段 P1P2
为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交;
def rect_overlap(r1, r2): return not (((r1[1][0] < r2[0][0])|(r1[0][1] > r2[1][1])) |((r2[1][0] < r1[0][0])|(r2[0][1] > r1[1][1]))1
2
3
跨立试验
如果两线段相交,则两线段必然相互跨立对方,如图1所示。在图1中,P1P2
跨立Q1Q2 ,则 矢量 (P1−Q1) 和(P2−Q1)位于矢量(Q2−Q1) 的两侧,即(P1−Q1)×(Q2−Q1)∗(P2−Q1)×(Q2−Q1)<0 上式可改写成 ( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0,
当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。 所以判断P1P2跨立Q1Q2的依据是: ( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) ≥ 0 同理判断Q1Q2跨立P1P2的依据是: ( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) ≥ 0至此已经完全解决判断线段是否相交的问题。
def line_intersection(p1, p2, q1, q2): return False if not rect_overlap([p1, p2], [q1, q2]) else \ # 不相交直接返回 (True if cross_prod(p1-q1, q2-q1)*cross_prod(q2-q1, p2-q1) >= 0 else False)1
2
3
5. 判断线段和直线是否相交
从标题即可看出,这里的直线和线段是不相同的;如果线段 P1P2
和直线 Q1Q2相交,则 P1P2跨立 Q1Q2,根据4的结论:
(P1−Q1)×(Q2−Q1)∗(Q2−Q1)×(P2,Q1)\beq0
6. 判断点是否在矩形内
只需判断该点的横纵坐标是否夹在矩形的左右边,上下边之间。判断线段、折线、多边形是否在矩形中,因为矩形是个凸集,所以只要判断所有端点是否都在矩形中即可;
7. 判断矩形是否在矩形中
只要把比较左右边界和上下边界即可;8. 判断圆是否在矩形中:
圆在矩形内的充要条件:圆心在矩形中且圆的半径小于等于圆心到矩形四条边的距离的最小值。
def circle_in_rect(c, r, lb, rt): # c: center # r: radius # lb: left bottom # rt: right top if ( ((center[0]<lb[0]) | (center[0]>rt[0])) | ((center[1]<lb[1])|(center[1]>rt[1])) ): # 圆心是否在矩形内 return False return True r <= min(center[0]-lb[0], rt[0]-center[0], center[1]-lb[1], rt[1]-center[
相关文章推荐
- 用python+numpy+matplotalib实现梯度下降法
- python 借助numpy保存数据为csv格式的实现方法
- Graham扫描法求点集凸包的原理及代码实现
- RNN学习第二讲-通过Python,numpy 和 theano实现一个RNN网络
- 梯度下降法(BGD,SGD,MSGD)python+numpy具体实现
- 循环神经网络在Python 、Numpy和Theano中的实现
- Python:用Numpy来实现向量的各种运算
- python-numpy的一些简单函数--补充中
- Python使用numpy实现BP神经网络
- Python+matplotlib+numpy实现在不同平面的二维条形图
- 数据预处理(2) ——数据变换与数据离散化 使用python(sklearn,pandas,numpy)实现
- python利用numpy实现结构体
- 【机器学习算法实现】主成分分析(PCA)——基于python+numpy
- Python的Numpy实现深度学习常用的函数
- 2017.05.10回顾 numpy学习 其他python woe iv实现参考
- <深度学习系列>基于numpy和python的反向传播算法的实现与分析
- Python numpy实现二维数组和一维数组拼接
- 【矩阵分解】Python下基于Numpy的四种矩阵基本分解的实现
- 循环神经网络教程-第二部分 用python numpy theano实现RNN
- 用python的numpy实现神经网络 实现 手写数字识别