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图片







posted on 2026-08-19 22:08  Angry_Panda  阅读(3)  评论(0)    收藏  举报

导航