python —— 判断平面某点是否在2D多边形内部 —— Python版本的inpolygon函数


代码:
import numpy as np
def inpolygon(xq: np.ndarray, yq: np.ndarray, xv: np.ndarray, yv: np.ndarray):
"""
Python实现等价 MATLAB inpolygon 射线交叉奇偶规则
:param xq: 待测点x坐标,一维数组
:param yq: 待测点y坐标,一维数组
:param xv: 多边形顶点x,一维数组(首尾自动闭合)
:param yv: 多边形顶点y,一维数组
:return: in, on 两个bool数组
in: True = 在多边形内部
on: True = 在多边形边界线段上
"""
xq = np.asarray(xq).ravel()
yq = np.asarray(yq).ravel()
xv = np.asarray(xv).ravel()
yv = np.asarray(yv).ravel()
n_points = len(xq)
n_vert = len(xv)
in_flag = np.zeros(n_points, dtype=bool)
on_flag = np.zeros(n_points, dtype=bool)
# 逐边遍历多边形
for i in range(n_vert):
x1, y1 = xv[i], yv[i]
x2, y2 = xv[(i + 1) % n_vert], yv[(i + 1) % n_vert]
# 1. 判断点是否在线段 (x1,y1)-(x2,y2) 上
def point_on_seg(px, py):
# 叉积=0 共线 + 包围盒判定
cross = (px - x1) * (y2 - y1) - (py - y1) * (x2 - x1)
if not np.isclose(cross, 0):
return False
minx = min(x1, x2) - 1e-12
maxx = max(x1, x2) + 1e-12
miny = min(y1, y2) - 1e-12
maxy = max(y1, y2) + 1e-12
return (minx <= px <= maxx) and (miny <= py <= maxy)
for pid in range(n_points):
px, py = xq[pid], yq[pid]
if point_on_seg(px, py):
on_flag[pid] = True
# 2. 射线交叉计数(奇偶规则)
yi, yj = y1, y2
xi, xj = x1, x2
# 水平射线 y=py 跨边判定
cond = ((yi > yq) != (yj > yq))
t = (yq[cond] - yi) / (yj - yi)
x_cross = xi + t * (xj - xi)
# 射线向右 x>px
cross_pid = np.nonzero(cond)[0]
for idx, pid in enumerate(cross_pid):
if xq[pid] < x_cross[idx] - 1e-12:
in_flag[pid] = ~in_flag[pid]
# MATLAB规则:边界点 on=True,不计入 in
in_flag[on_flag] = False
return in_flag, on_flag
# ========== 测试示例 ==========
if __name__ == "__main__":
# 正方形多边形
xv = np.array([0, 0, 2, 2])
yv = np.array([0, 2, 2, 0])
# 测试点:内部、外部、边上
xq = np.array([1, 3, 0, 1])
yq = np.array([1, 1, 1, 2])
in_, on_ = inpolygon(xq, yq, xv, yv)
print("in: ", in_)
print("on: ", on_)
运行结果:
file:///home/devil/Pictures/%E6%88%AA%E5%9B%BE/%E6%88%AA%E5%9B%BE%202026-08-19%2022-07-43.png
本博客是博主个人学习时的一些记录,不保证是为原创,个别文章加入了转载的源地址,还有个别文章是汇总网上多份资料所成,在这之中也必有疏漏未加标注处,如有侵权请与博主联系。
如果未特殊标注则为原创,遵循 CC 4.0 BY-SA 版权协议。
posted on 2026-08-19 22:08 Angry_Panda 阅读(3) 评论(0) 收藏 举报
浙公网安备 33010602011771号