检查坐标是否在坐标系上的某个特定区域内

3

我有一个坐标系,其中有一定数量的区域,类似于这样:coordinate system

然而,我这里所有的区域都是唯一编号的,大小相同,总共有16个(因此每个象限都会有4个完全相同大小的切片)。

我还有一组元组(二维坐标),它们的值都在(-1, -1)和(1, 1)之间。现在我想确定将它们映射到坐标系上后,它们会落入哪个区域(即1到16)。

作为一个完全的新手,我不知道该如何解决,但下面是我的思路:

将所有分界线定义为函数,并检查每个点是否在它们的上方或下方。忽略决策边界上的点

例如:第一象限有四个区域。从x轴到y轴(逆时针方向)让我们称其为a、b、c和d。

a是x轴和f1(x) = 0.3333x(红色)之间的区域

b在f1和f2之间,f2(x) = x(黄色)

c在f2和f3之间,f3(x) = 3x(蓝色)

d在f3和y轴之间

graphs

代码如下:

def a(p):
   if(y > 0 and y < 0.3333x):
      return "a"
   else:
      b(p)

def b(p):
   if(y > 0.3333x and y < x)
      return "b"
   else:
      c(p)

def c(p):
   if(y > x and y < 3x):
      return "c"
   else: 
      d(p)

def d(p): 
   if(y > 3x and x > 0):
      return "d"

注意:为了易读性,我在元组的各个坐标处只写了“x”和“y”,而不是每次都写p[0]或p[1]。另外,如上所述,我假设函数上没有直接的物品,因此它们被忽略。
现在,这是一个可能的解决方案,但我觉得肯定有更高效的解决方案。

1
你是否正在寻找一个现成的库来进行笛卡尔形状操作? - Charles Landau
也许吧?老实说我不知道。我只觉得为了确定一个点落在平面上的位置而定义16个非常相似的函数似乎有些低效。 - Readler
2个回答

2

由于您的工作区域在坐标 (-1,-1) 和 (1,1) 之间,并且将笛卡尔平面等分,因此自然而然地使用三角函数。考虑到单位圆具有 2π 度,您将其分成 n 个相等的部分(在本例中为 n=16)。因此每个切片都有 (2π)/16 = π/8 度。现在,您可以想象一个任意点 (x,y) 连接到原点 (0,0),它与 x 轴形成一个角度。要找到这个角度,只需计算 y/x 的反正切即可。然后,您只需要验证它位于哪个角度部分。

以下是草图:

sketch

要直接映射到区间,您可以使用 bisect 模块:

import bisect
from math import atan2
from math import pi

def find_section(x, y):

    # create intervals
    sections = [2 * pi * i / 16 for i in range(1, 17)]

    # find the angle
    angle = atan2(y, x)

    # adjusts the angle to the other half circle
    if y < 0:
        angle += 2*pi

    # map into sections
    return bisect.bisect_left(sections, angle)

使用方法:

In [1]: find_section(0.4, 0.2)
Out[1]: 1

In [2]: find_section(0.8, 0.2)
Out[2]: 0

1
我本来想把平面分成 pi/8 并使用角度进行计算,但是不知道如何在 Python 中实现。太好了!这正是我想要的。 - Readler
2
这样好多了。我会保留我的答案供参考。 - Charles Landau
1
在实现过程中,我发现了一个小缺陷,因为您的解决方案只返回第一象限中的部分。我的问题的“正确”解决方案应该是:`angle = atan2(y,x)if(y < 0): angle = angle + 2 * pi` - Readler
@Readler 已经注意到了!已添加到解决方案中。 - Hemerson Tacon

1

Shapely是一个Python库,可以帮助您处理典型的笛卡尔几何问题,但据我所知,它没有一种简单的方法来基于函数无限扩展其Line对象。

如果您可以接受这一点,那么您可以使用Polygon.contains(Point)模式检查任何Point是否在任何Polygon中,如此处所示:https://shapely.readthedocs.io/en/stable/manual.html#object.contains


它没有一种简单的方法根据函数无限扩展其线对象。幸运的是,这并不需要,因为我的所有点都在一个区域内(介于(-1,-1)和(1,1)之间)!object.within(p)似乎更适合。因此,我的新方法是创建16个多边形(对应于我的16个区域),然后检查点落在哪些区域中(使用within)。听起来比我的方法好多了! - Readler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接