Is there any function in PyQt4 to help me decide if a point is on the perimeter of a QPolygon? For example:
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])
The function should return true if I pass QP(1,3), QP(4,5), QP(3,2) or QP(1,1) to it.
This is a tough one indeed. I played around a lot with several methods of
QPolygon
likeintersected
,united
,subtracted
but none brought any success.For example I thought this might work: Copy the polygon, add the point to the copy and then check if the result is empty. If the point lies on the perimeter of the polygon both the original and the copy should have the same shape and therefore the result should be empty.
However a polygon seems to be 'drawn' in the order the points are given thus if you just add the point this leads to some other shape. For example consider the points
(0,0) (0,2) (2.2) (2,0)
which form a square and you want to check(0,1)
. Then if you just add the point at the end this will 'connect"(2,0)
with(0,1)
and(0,1)
with(0,0)
since a polygon has to be a closed form. This gives some other shape. Thus you would have to insert the point at the right position to get the same shape. For this example it would be right after(0,0)
. So I thought, ok, lets try the above with all possible permutations and there will be only one configuration (and its transformations resulting from rotation and inversion) such that the result of the subtraction is empty.But somehow this doesn't work either. Trying out your example I get for
QP(4,5)
andQP(3,2)
a value ofchecks = 10
forQP(1,1)
checks = 20
and forQP(1,3)
checks = 0
. What I would have expected is to getchecks = 12
for all of the points (since they all lie on the perimeter).12
becausepoly2
is made of6
points so you can rotate the points6
times and do the same after you inverted the order so have12
different configurations contained inpermuts
leading to the same shape. Furthermore if the subtraction is performed the other way round (i.e.QtGui.QPolygon(list(permut)).subtracted(poly).isEmpty()
) I getTrue
for every point also for points not even lying within the polygon but outside.I tried similar things using
united
andintersected
instead ofisEmpty
in the above function:Same here, it should only evaluate as
True
if the point is actually lying on the perimeter. But this gives backFalse
for almost every point I checked of your above example.I didn't take a look at the source code of the methods of
QPolygon
(if any available) but it appears that there is some weird stuff happening.So I would suggest you to write an own method which evaluates for all lines in the polygon if the point lies on one of it.
This appears to be a bit heavy but it is important to perform all calculations with integers only since you could get wrong results due to floating point precision (
QPolygon
takes integer points only anyway). Although not tested yet it should work.