Issue
I have been using matplotlib.path.contains_points()
method without any figures or plots. I am getting inconsistent results depending on the path. In the following example, a simple square path works, but a longer path from an ellipse does not:
import numpy as np
from skimage.draw import ellipse_perimeter
from matplotlib.path import Path
import matplotlib.pyplot as plt
s = 100
squarepath = Path([(0,0), (0, s), (s,s), (s, 0)])
print(squarepath.contains_points([(s/2, s/2)]))
(xv,yv) = ellipse_perimeter(200,360,260,360)
xyverts = np.stack((xv,yv),axis=1)
ellipsepath = Path(xyverts)
pt = (213,300)
print(ellipsepath.contains_points([pt]))
fig,ax = plt.subplots()
plt.scatter(ellipsepath.vertices[:,0],ellipsepath.vertices[:,1])
plt.scatter(pt[0],pt[1])
plt.show()
I am using contains_points()
before anything is plotted, so there should not be any data versus display coordinates issue as is discussed in other similar questions about contains_points()
. What else could be going on here?
Solution
The problem is that ellipse_perimeter
is returning the points of the ellipse perimeter in an order that does not define a path. Vertices are then created between points accross your ellipse. You can check that by ploting your path as patch instead of using scatter
:
from matplotlib.patches import PathPatch
ax.add_patch(PathPatch(ellipsepath, facecolor='yellow', lw=1)) # instead of scatter(ellipsepath...)
Output (without changing anything else to your code):
As you can see instead of seeing a yellow ellipse as specified with facecolor
, we only see the lines (linking points all over the perimeter).
I guess the easiest way to solve this would be to use patches.Ellipse
and call get_path()
.
However, if you're stuck with skimage, you'll have to sort your points before creating a path:
import numpy as np
from skimage.draw import ellipse_perimeter
from matplotlib.path import Path
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
(xv,yv) = ellipse_perimeter(200,360,260,360)
xyverts = list(zip(xv, yv))
pt_top = sorted([(x,y) for x,y in xyverts if y >= 360], key=lambda c: c[0])
pt_bottom = sorted([(x,y) for x,y in xyverts if y < 360], key=lambda c: -c[0])
xyverts = pt_top + pt_bottom
ellipsepath = Path(xyverts)
pt = (213,300)
print(ellipsepath.contains_points([pt]))
fig,ax = plt.subplots()
ax.add_patch(PathPatch(ellipsepath, facecolor='yellow', lw=1))
plt.scatter(pt[0],pt[1])
plt.show()
Output:
Answered By - Tranbi
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.