ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

我在python中对多边形点(约旦曲线定理)的改编是否正确?

2019-06-28 00:45:51  阅读:266  来源: 互联网

标签:python polygon python-3-x intersection points


问题

我最近发现需要确定我的点是否在多边形内.所以我在C中学习了this方法并将其改编为python.但是,我认为我正在研究的C代码是不是很正确?我相信我已经修好了,但是我不太确定所以我希望那些比我更聪明的人可以帮助我解决这个问题吗?

这个定理非常简单,想法是这样的,给定第n个闭合多边形,你绘制一条任意直线,如果你的点在里面,你的直线将与边相交奇数次.否则,你将是偶数,它在多边形之外.太酷了.

我有以下测试用例:

    polygon_x = [5, 5, 11, 10]
    polygon_y = [5, 10, 5, 10]
    test1_x = 6
    test1_y = 6

    result1 = point_in_polygon(test1_x, test1_y, polygon_x, polygon_y)
    print(result1)

    test2_x = 13
    test2_y = 5
    result2 = point_in_polygon(test2_x, test2_y, polygon_x, polygon_y)
    print(result2)

如果我将其定义如下,上面的内容会给我错误:

            if polygon_x[i] < polygon_x[(i+1) % length]:
                temp_x = polygon_x[i]
                temp_y = polygon_x[(i+1) % length]
            else:
                temp_x = polygon_x[(i+1) % length]
                temp_y = polygon_x[i]

这是错的!我应该为result1获得true,然后为result2获取false.很明显,有些东西很时髦.

除了以上内容之外,我在C中阅读的代码是有意义的.另外,它失败了我的测试用例,这让我觉得temp_y应该用polygon_y而不是polygon_x来定义.果然,当我这样做时,我的测试用例(6,6)通过了.当我的点在线上时它仍然失败,但只要我在多边形内,它就会通过.预期的行为.

采用python的多边形代码

    def point_in_polygon(self, target_x, target_y, polygon_x, polygon_y):
        print(polygon_x)
        print(polygon_y)
        #Variable to track how many times ray crosses a line segment
        crossings = 0
        temp_x = 0
        temp_y = 0
        length = len(polygon_x)

        for i in range(0,length):

            if polygon_x[i] < polygon_x[(i+1) % length]:
                temp_x = polygon_x[i]
                temp_y = polygon_y[(i+1) % length]
            else:
                temp_x = polygon_x[(i+1) % length]
                temp_y = polygon_y[i]

            print(str(temp_x) + ", " + str(temp_y))

            #check
            if target_x > temp_x and target_x <= temp_y and (target_y < polygon_y[i] or target_y <= polygon_y[(i+1)%length]):
                eps = 0.000001

                dx = polygon_x[(i+1) % length] - polygon_x[i]
                dy = polygon_y[(i+1) % length] - polygon_y[i]

                k = 0
                if abs(dx) < eps:
                    k = 999999999999999999999999999
                else:
                    k = dy/dx

                m = polygon_y[i] - k * polygon_x[i]
                y2 = k*target_x + m

                if target_y <= y2:
                    crossings += 1
        print(crossings)
        if crossings % 2 == 1:
            return True
        else:
            return False

摘要

有人可以向我解释一下temp_x和temp_y方法在做什么吗?另外,如果我为polygon_y重新定义polygon_x和temp_y的temp_x的修复是正确的方法吗?我对此表示怀疑.这就是原因.

temp_x和temp_y的内容对我来说没有多大意义.对于i = 0,显然polygon_x [0]< polygon_x [1]为false,因此我们得到temp_x [1] = 5和temp_y [0] = 5.即(5,5).这恰好是我的一对.但是,假设我不按顺序提供算法我的点(按轴,成对完整性总是必须的),类似于:

x = [5, 10, 10, 5]
y = [10,10, 5, 5]

在这种情况下,当i = 0时,我们得到temp_x [1] = 10和temp_y [0] = 10.好的,巧合(10,10).我还针对“校正”算法(9,9)测试了点,它仍然在里面.简而言之,我试图找到一个反例,为什么我的修复不起作用,但我不能.如果这是有效的,我需要了解该方法正在做什么,并希望有人可以帮我解释一下?

无论如何,如果我是对或错,如果有人可以帮助更好地了解这个问题,我将不胜感激.我甚至愿意以更有效的方式解决n-polygons问题,但我想确保我正确理解代码.作为一名程序员,我对一种不太有意义的方法感到不舒服.

非常感谢你听我上面的想法.任何建议都非常欢迎.

解决方法:

您误解了链接的C代码中的x1和x2值是什么,并且误解导致您在Python中选择不适当的变量名称.这两个变量都包含x值,因此temp_y是一个非常具有误导性的名称.更好的名称可能是min_x和max_x,因为它们是构成多边形边缘的顶点的x值的最小值和最大值.更清晰的代码版本可能写成:

for i in range(length):
    min_x = min(polygon_x[i], polygon_x[(i+1)%length])
    max_x = max(polygon_x[i], polygon_x[(i+1)%length])

    if x_min < target_x <= x_max:
        # ...

这可能比C风格的代码效率稍低,因为调用min和max会将值比较两次.

您对点的顺序的评论表明存在进一步的误解,这可能解释了在将temp_y设置为polygon_x的值时所看到的意外结果.多边形列表中坐标的顺序很重要,因为边缘从一个坐标对到列表周围的下一个坐标对(最后一对坐标连接到第一对以关闭多边形).如果对它们重新排序,多边形的边缘将会切换.

您在代码中给出的示例坐标(polygon_x = [5,5,11,10]和polygon_y = [5,10,5,10])不描述正常类型的多边形.相反,你会得到一个(略微倾斜的)蝴蝶结形状,两个对角线边缘相互交叉,就像中间的X一样.但这并不是这个算法的问题.

但是,您正在测试的第一个点恰好位于其中一个对角线边缘(围绕列表,从最后一个顶点,(10,10)到第一个,(5,5)).代码是否将决定它在多边形的内部或外部可能归结为浮点舍入以及操作符在<之间的选择.或< =.在这种情况下,任何一个答案都可以被认为是“正确的”. 当您在问题的后期重新排序坐标时(顺便将11更改为10),您将领结变成了正方形.现在(6,6)测试完全在形状内部,因此如果不将y坐标分配给第二个临时变量,代码将起作用.

标签:python,polygon,python-3-x,intersection,points
来源: https://codeday.me/bug/20190627/1310111.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有