最近有个朋友问起的一个问题,给定一个荷质比和保留时间构成的平面,想看下哪些化合物落在这个平面里面。

假如有下面一个平面,哪些点在平面里?哪些点在平面外?怎么判断呢?

最简单的方法是目测!

如果采用程序,其中一个方法是光线投射算法,如下图所示:从任意位置画一条到目标点的水平线,计算该水平线进出平面边界的次数,如果是偶数,则点在平面外;如果是奇数,则点在平面内。点正好落在定点或边界时会出现特殊的判断。

我们自己构造一个多边形,绘制几个点:

# (1.5,2)bounding_points = [(1,2),(2,1),(3,1.5),(3.5,2.5),(2.1,6.3),(1,3)]
bounding_box_positions = [(1.5,2), (1.5,4.5), (3,5)]

如下图

plotPolygenAndPoints(bounding_points, bounding_box_positions)

加上从左侧发过来的光线

plotPolygenAndPoints(bounding_points, bounding_box_positions, ray=True)

原始函数不能区分部分边界上的点

Stack Overflow上提供了一个函数polygon_ray_casting (代码见文末)实现ray casting算法,被转换成了各个程序语言的版本。

测试下这个函数,一个边界点(1.5,4.5)计算为在平面内,另一个边界点(2.5,1.25)却未落在边界内。

bounding_box_positions = [(1.5,2), (1,1.25),(1.5,4.5), (3,3),(4,3.1),(2.5,1.25),(3,5),(1.0,2),(3.5,2.5)]
bounding_box_positions = sorted(bounding_box_positions, key=lambda x:x[0])
polygon_ray_casting(bounding_points, bounding_box_positions)
[(3, 3), (3.5, 2.5)]

关于这个结果在评论区也有讨论,函数设计的目的不同,行为也会不同。在公共平台找到的代码和方法是给我们提供思路的,有些代码可以直接用,有些代码需要修改后用。使用前,要注意其使用条件,测试后再用于自己的数据。

修改后的函数可处理边界点

增加边界点的判断、定点的判断增加边界点的判断、定点的判断

测试凸多边形

# 默认落在边界也算polygon_ray_casting_modi(bounding_points, bounding_box_positions)
[(1.0, 2), (3, 3), (3.5, 2.5)]
plotPolygenAndPoints(bounding_points, bounding_box_positions)

# 落在边上不算在内polygon_ray_casting_modi(bounding_points, bounding_box_positions, edgeAsInside=False)
[(1.5, 2), (3, 3)]

测试凹多边形

# (1.5,2)bounding_points = [(1,2),(2,2.5),(3,1.5),(4,2),(2.1,4),(1,3)]
bounding_box_positions = [(1.5,2), (1,1.25), (1.5,2.5), (3,1.5), (3,3),(4,3.1), (1,2.1), (3.5,1.75)]
bounding_box_positions = sorted(bounding_box_positions, key=lambda x:x[0])
polygon_ray_casting_modi(bounding_points, bounding_box_positions)
[(1, 2.1), (1.5, 2.5), (3, 1.5), (3, 3), (3.5, 1.75)]
plotPolygenAndPoints(bounding_points, bounding_box_positions)

测试多种六边形

bounding_points = [(1,3),(2,3),(3,2),(2,1),(1,1),(0,2)]
bounding_box_positions = [(-1,3), (1.5,2.9), (1.5,3),(0,2),(1,3),(0.5,1.5),(2.5,1.5), (2.5,3),(0,1.5),(1,1.1)]
bounding_box_positions = sorted(bounding_box_positions, key=lambda x:x[0])
polygon_ray_casting_modi(bounding_points, bounding_box_positions)
[(0, 2), (0.5, 1.5), (1, 3), (1, 1.1), (1.5, 2.9), (1.5, 3), (2.5, 1.5)]
plotPolygenAndPoints(bounding_points, bounding_box_positions)

# (1.5,2)bounding_points = [(1,3),(2,3),(2,2),(3,2),(3,1),(1,1)]
bounding_box_positions = [(1.5,2), (1.5,3), (1,3), (3,1.25), (3,3)]
polygon_ray_casting_modi(bounding_points, bounding_box_positions)
[(1.5, 2), (1.5, 3), (1, 3), (3, 1.25)]
plotPolygenAndPoints(bounding_points, bounding_box_positions)

# (1.5,2)bounding_points = [(1,2),(3,2),(3,3),(4,3),(4,1),(1,1)]
bounding_box_positions = [(1.5,2), (1,1.25), (3,3),(4,3.1)]
polygon_ray_casting_modi(bounding_points, bounding_box_positions)
[(1.5, 2), (1, 1.25), (3, 3)]
plotPolygenAndPoints(bounding_points, bounding_box_positions)

for i in bounding_box_positions:print(i)print(wn_PnPoly(i, bounding_points))
(1.5, 2)
0
(1, 1.25)
-1
(3, 3)
0
(4, 3.1)
0

用到的绘图函数

import matplotlib.pyplot as pltdef plotPolygenAndPoints(bounding_points, bounding_box_positions, ray=False):coord = bounding_points[:]coord.append(coord[0]) #repeat the first point to create a 'closed loop'xs, ys = zip(*coord) #create lists of x and y valuesplt.figure()plt.plot(xs,ys) for x,y in bounding_box_positions:plt.plot(x,y,'o')        if ray:plt.plot((0,x),(y,y))plt.arrow(x, y, 0.3, 0, shape='full', lw=1, length_includes_head=True, head_width=.1)plt.show()

用到的判断函数

def polygon_ray_casting(bounding_points, bounding_box_positions):# https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html# https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon# Arrays containing the x- and y-coordinates of the polygon's vertices.vertx = [point[0] for point in bounding_points]verty = [point[1] for point in bounding_points]    # Number of vertices in the polygonnvert = len(bounding_points)    # Points that are insidepoints_inside = []    # For every candidate position within the bounding boxfor idx, pos in enumerate(bounding_box_positions):testx, testy = (pos[0], pos[1])c = 0for i in range(0, nvert):j = i - 1 if i != 0 else nvert - 1if( ((verty[i] > testy ) != (verty[j] > testy))   and(testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]) ):c += 1# If odd, that means that we are inside the polygonif c % 2 == 1: points_inside.append(pos)    return points_inside

最终用的函数

def between(a,x,y,equal=True, epsilon=0.000001):if equal:        return (x<=a<=y) or (x>=a>=y) or (abs(a-x)<epsilon) or (abs(a-y)<epsilon)    else:        return (x<a<y) or (x>a>y)def polygon_ray_casting_modi(bounding_points, bounding_box_positions, edgeAsInside=True, epsilon=0.000001):# https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html# https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon# Arrays containing the x- and y-coordinates of the polygon's vertices.vertx = [point[0] for point in bounding_points]verty = [point[1] for point in bounding_points]    # Number of vertices in the polygonnvert = len(bounding_points)    # Points that are insidepoints_inside = []    # For every candidate position within the bounding boxfor idx, pos in enumerate(bounding_box_positions):testx, testy = (pos[0], pos[1])inside = Falsefor i in range(0, nvert):j = i - 1 if i != 0 else nvert - 1# Point on horizontaol edgeif (verty[i] == testy ) and (verty[j] == testy) and between(testx, vertx[i],vertx[j]):inside = edgeAsInside                break# corner pointif (((verty[i] == testy) and (vertx[i] == testx)) or ((verty[j] == testy) and (vertx[j]==testx))):inside = edgeAsInside                breakif between(testy, verty[i], verty[j]):                if(testy==verty[i]<=verty[j]) or (testy==verty[j]<=verty[i]):                    continuec = (vertx[i]-testx)*(verty[j]-testy) - (vertx[j]-testx)*(verty[i]-testy)                # print(c)if c==0 or abs(c) < epsilon:inside = edgeAsInside                    breakif (verty[i]<verty[j]) == (c>0):inside = not inside        # If odd, that means that we are inside the polygon#print(inside)if inside:points_inside.append(pos)    return points_inside

参考

  1. https://stackoverflow.com/questions/8721406/how-to-determine-if-a-point-is-inside-a-2d-convex-polygon/23223947#23223947

  2. https://github.com/mikolalysenko/robust-point-in-polygon

  3. https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html

  4. https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon?page=1&tab=votes#tab-top

  5. https://en.m.wikipedia.org/wiki/Point_in_polygon

  6. 完整代码 https://gitee.com/ct5869/shengxin-baodian

往期精品(点击图片直达文字对应教程)

机器学习

后台回复“生信宝典福利第一波”或点击阅读原文获取教程合集

如何判断一个点是否落在一个平面内相关推荐

  1. Qt 判断一个点是否落在三角形内(算法)

    利用重心法判断一个点是否落在三角形面积内,三角形的三个点在同一个平面上,如果选中其中一个点,其他两个点不过是相对该点的位移而已,比如选择点A作为起点,那么点B相当于在AB方向移动一段距离得到,而点C相 ...

  2. python 判断一个点(坐标)是否在一个多边形内利用射线法

    看了一篇博客写的用射线法判断一个经纬度点是否在一个多边形的内部的方法 经验证可行所以拿来用作备份: class Point:lng = ''lat = ''def __init__(self, lng ...

  3. 关于判断一个点是否落在矩形内

    判断一个点是否在矩形内会经常用到,比如判断点是否在障碍物里,判断游戏中的玩家是否在某一区域.网上的解释都是抄来抄去的,有的明显错误也没发现,要么就是扔了一段代码,什么解释也没有,让人云里雾里.因此这里 ...

  4. python经纬度是否在范围内_如何判断一个经纬度是否落在一个指定的区域范围内?...

    /** * 使用Path2D创建一个多边形 * @param polygon 经纬度 集合 * @return 返回Path2D.Double */ private static Path2D.Dou ...

  5. 判断一个点是否在指定三角形内(1)

    问题:判断点P是否在三角形ABC内 判断一个点是否在在三角形内,最常用的两种方法:面积法.向量同向法.算法虽然很简单,但要做到高效却不容易,要考虑到二维.三维的区别,还要考虑到坐标是用浮点数还是用整数 ...

  6. 地图处理方法-判断一个点是否在某个区域内

    判断一个点是否在某个区域内(多边形) 背景: 比如滴滴会根据乘客所在的不同区域,给出不同的价格.市区堵一点,那么价格也高点.获取服务范围只规定在某个范围内 原理: 求解从该点向右发出的水平线射线与多边 ...

  7. 判断一个点是否在某个区域内(多边形)

    判断一个点是否在某个区域内(多边形) 背景: 比如滴滴会根据乘客所在的不同区域,给出不同的价格.市区堵一点,那么价格也高点.获取服务范围只规定在某个范围内 原理: 求解从该点向右发出的水平线射线与多边 ...

  8. Unity判断一个物体是否在相机范围内

    Unity判断一个物体是否在相机范围内 思路 代码 注意点 思路 先说下思路,先把物体从世界坐标转到该相机的视口坐标viewPos, 如果满足这两个条件: 0<viewPos.x < 1 ...

  9. java判断一个字符串对象是否在一个集合里面

    最初遇到的这个小问题是,如何判断一个字符串是否在一个字符串数组里面? private static boolean isBelongList(String str){ String[] strArra ...

最新文章

  1. 电脑python安装库_Python安装第三方库的3种方法 -电脑资料
  2. python3项目-终于找到python3项目实战教程
  3. 详解FTP服务完成Linux和WIN10之间的信息传输(实验详解)
  4. 深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件(转)
  5. maven打包指定main函数
  6. 填补服务机器人市场空白,九号机器人提供智能服务场景解决方案!
  7. Java基础知识强化之网络编程笔记05:UDP之多线程实现聊天室案例
  8. 明晚9点 华为新款折叠屏手机MateXs即将闪亮登场
  9. 洛谷P1258 小车问题(题解)
  10. VS2012下基于Glut 矩阵变换示例程序:
  11. Bailian2693 最远距离【序列处理】
  12. EXCEL数据处理小结(SQL)
  13. 理解图像处理中的 双线性内插法(图文说明)
  14. PHP商城网站绑定中国银联在线支付接口
  15. 科技爱好者周刊:第 75 期
  16. 医学案例统计分析与SAS应用--自学笔记
  17. python中多行语句可以使用反斜杠来实现吗_Python中的多行语句可以使用反斜杠来实现...
  18. 文件服务器要备案么,icp备案一定要云服务器吗
  19. Apache Avro 入门
  20. java中unicode编码和utf8编码相互转换

热门文章

  1. python选择题和填空题_用Python快速阅卷选择、填空题等客观题目
  2. Java实现分页效果
  3. Java判断日期是否是本日,本周,本月
  4. 考研复习计划(8.20-8.31)
  5. 欢 迎 投 稿 | Python中文社区征文启事
  6. 嵌入式STM32入门之定时器控制LED闪烁与产生PWM脉冲宽度调制信号
  7. 刷机显示服务器连接不上怎么办,完美刷机怎么连接不到云服务器
  8. 怎样把手机搜索的计算机放到桌面上,我的手机桌面上的软件图标不见了,但软件还在,该怎么把图标找回来?...
  9. 计算机专升本英语零基础,学位英语零基础能过吗,英语底子差还有希望吗?
  10. 大手牵小手在穗过节,益起来为祖国庆生!