Python 如何知道点是否在QPolygon(PyQt4)的周长上
PyQt4中是否有任何函数可以帮助我确定点是否位于多边形的周长上?例如:Python 如何知道点是否在QPolygon(PyQt4)的周长上,python,pyqt4,qpolygon,Python,Pyqt4,Qpolygon,PyQt4中是否有任何函数可以帮助我确定点是否位于多边形的周长上?例如: from PyQt4 import QtGui from PyQt4.QtCore import Qt, QPoint as QP polygon = QtGui.QPolygon([QP(0, 1), QP(3,7), QP(4, 6), QP(4,3), QP(2,1), QP(0,1]) 如果我将QP(1,3)、QP(4,5)、QP(3,2)或QP(1,1)传递给该函数,则该函数应返回true。这确实是一个困难
from PyQt4 import QtGui
from PyQt4.QtCore import Qt, QPoint as QP
polygon = QtGui.QPolygon([QP(0, 1), QP(3,7), QP(4, 6), QP(4,3), QP(2,1), QP(0,1])
如果我将QP(1,3)、QP(4,5)、QP(3,2)或QP(1,1)传递给该函数,则该函数应返回true。这确实是一个困难的问题。我用了很多种方法,比如交叉法、联合法、减法法,但都没有成功 例如,我认为这可能有效:复制多边形,将点添加到副本中,然后检查结果是否为空。如果点位于多边形的周长上,则原始和副本应具有相同的形状,因此结果应为空
def on_perimeter(poly, point):
poly2 = poly + QtGui.QPolygon() # copy the polygon
poly2.add(point)
return poly.subtracted(poly2).isEmpty()
然而,多边形似乎是按照给定的点的顺序“绘制”的,因此,如果只添加点,这将导致其他形状。例如,考虑点<代码>(0,0)(0,2)(2.2)(2,0)< /代码>,它构成正方形,并且要检查<代码>(0,1)< /C>。然后,如果您只在末尾添加点,这将“连接”(2,0)
与(0,1)
和(0,1)
与(0,0)
因为多边形必须是闭合形式。这会提供一些其他形状。因此,您必须在正确的位置插入点才能获得相同的形状。例如,它将位于(0,0)
之后。因此我想,好吧,让我们尝试上述所有可能的排列,并且只有一种配置(以及由旋转和反转产生的变换)使减法结果为空
import itertools
def on_perimeter(poly, point):
points = [point] # the points of the new polygon
for ii in range(0, poly.size()):
points += [poly.point(ii)]
permuts = list(itertools.permutations(points)) # all possible permutations
checks = 0
for permut in permuts:
checks += int(poly.subtracted(QtGui.QPolygon(list(permut))).isEmpty())
return checks
但不知何故,这也不起作用。试一下你的例子,我得到了QP(4,5)
和QP(3,2)
值checks=10
对于QP(1,1)
检查=20和QP(1,3)
检查=0。我所期望的是所有分数都得到checks=12
(因为它们都位于外围).12
因为poly2
由6个
点组成,所以你可以旋转点6次
并在你颠倒顺序后做同样的事情因此12
排列中包含的不同配置导致相同的形状s以另一种方式执行(即QtGui.QPolygon(list(permut)).subtracted(poly).isEmpty()
)对于每个点,甚至对于不在多边形内但在多边形外的点,我都得到True
在上述函数中,我使用united
和intersected
而不是isEmpty
尝试了类似的方法:
tmp = QtGui.QPolygon(list(permut))
checks += int(poly.intersected(tmp) == poly.united(tmp))
同样,如果该点实际位于周界上,则其应仅计算为True
。但这将返回False
,几乎我在上述示例中检查的每个点
我没有看一看QPolygon
方法的源代码(如果有的话),但似乎发生了一些奇怪的事情
因此,我建议您编写一个自己的方法,如果点位于多边形中的一条线上,该方法将计算多边形中的所有直线
def on_perimeter(poly, point):
lines = []
for ii in range(1, poly.size()):
p1 = poly.point(ii-1)
p2 = poly.point(ii)
lines += [ ( (p1.x(), p1.y()), (p2.x(), p2.y()) ) ]
lines += [ ( (poly.last.x(), poly.last.y()), (poly.first.x(), poly.first.y()) ) ]
for line in lines:
dx = line[1][0] - line[0][0]
dy = line[1][1] - line[0][1]
if abs(dx) > abs(dy) and dx*dy != 0 or dx == 0 and dy == 0: # abs(slope) < 1 and != 0 thus no point with integer coordinates can lie on this line
continue
if dx == 0:
if point.x() == line[0][0] and (point.y()-line[[0][1])*abs(dy)/dy > 0 and (line[1][1]-point.y())*abs(dy)/dy > 0:
return True
if dy == 0:
if point.y() == line[0][1] and (point.x()-line[[0][0])*abs(dx)/dx > 0 and (line[1][0]-point.x())*abs(dx)/dx > 0:
return True
dx2 = point.x() - line[0][0]
dy2 = point.y() - line[0][1]
if dx*dx2 < 0 or dy*dy2 < 0:
continue
if abs(dx) % abs(dx2) == 0 and abs(dy) % abs(dy2) == 0:
return True
return False
def在_周长上(多边形,点):
行=[]
对于范围(1,poly.size())内的ii:
p1=多边形点(ii-1)
p2=多边形点(ii)
行+=[((p1.x(),p1.y()),(p2.x(),p2.y())]
线条+=[((poly.last.x(),poly.last.y()),(poly.first.x(),poly.first.y())]
对于行中的行:
dx=第[1][0]行-第[0][0]行
dy=第[1][1]行-第[0][1]行
如果abs(dx)>abs(dy)和dx*dy!=0或dx==0和dy==0:#abs(slope)<1和!=0,则具有整数坐标的点不能位于这条线上
持续
如果dx==0:
如果点x()==line[0][0]和(point.y()-line[[0][1])*abs(dy)/dy>0和(line[1][1]-point.y())*abs(dy)/dy>0:
返回真值
如果dy==0:
如果点.y()==line[0][1]和(point.x()-line[[0][0])*abs(dx)/dx>0和(line[1][0]-point.x())*abs(dx)/dx>0:
返回真值
dx2=点.x()-线[0][0]
dy2=点.y()-线[0][1]
如果dx*dx2<0或dy*dy2<0:
持续
如果abs(dx)%abs(dx2)==0且abs(dy)%abs(dy2)==0:
返回真值
返回错误
这似乎有点繁重,但必须仅使用整数执行所有计算,因为由于浮点精度的原因,可能会得到错误的结果(
QPolygon
无论如何只接受整数)。虽然还没有测试,但它应该可以工作。谢谢你的长篇大论。我确实根据绘制绘图时使用的一些缩放比例找到了解决方法。我曾经检查过像你在这里显示的每个点,但是我的绘图细节非常复杂,花费了太长时间。