# How to properly use path.Path.contains_point?

I’m trying to use path.Path.contains_point for point-in-polygon testing and am running into a few different confusing situations. My specific issues/questions are:

1. I’m seeing different behaviour dependent on path direction (clockwise or counter-clockwise). Is there a “correct” direction to use?

2. What is the expected behaviour for Path.contains_point when the point is on a boundary?

3. What is the radius parameter supposed to do? The docs say it “allows the path to be made slightly larger or smaller”, but I’m clearly not understanding this properly (see the cw_path hit test failure with r=0.1 below).

Here is a short example showing some issues with a unit rectangle…

from matplotlib.path import Path

cw_path = Path([[0,0], [0,1], [1,1], [1,0]])

ccw_path = Path([[0,0], [1,0], [1,1], [0,1]])

#Point on x axis not detected for either path…

… cw_path.contains_point([0.5, 0])

0

ccw_path.contains_point([0.5, 0])

0

… r = 0.1

0

1

The following ipython notebook has more detailed tests, but the main points are in the sample above.

http://nbviewer.ipython.org/7e1b347b8b21b338bee1

I’ve found at least one reference [1] online indicating that “this function is intended for use when mouse-clicking”. Does that mean I should not use it for generic point-in-polygon testing?

Thanks,

Russ

I'm trying to use path.Path.contains_point for point-in-polygon testing
and am running into a few different confusing situations. My specific
issues/questions are:

1. I'm seeing different behaviour dependent on path direction (clockwise
or counter-clockwise). Is there a "correct" direction to use?

No, it shouldn't matter, AFAICT. If there are differences, then it should
be reported as a bug.

2. What is the expected behaviour for Path.contains_point when the point
is on a boundary?

The original algorithm that it was based off of considered it outside

(again, from memory), but warns that floating-point errors renders this
point largely theoretical.

3. What is the radius parameter supposed to do? The docs say it "allows
the path to be made slightly larger or smaller", but I'm clearly not
understanding this properly (see the cw_path hit test failure with r=0.1
below).

That is a terrible description of the functionality, I agree. Essentially,
if you have a positive radius, it effectively dilates the polygon for the
purposes of point-testing, while a negative radius effectively erodes the
polygon (but not for plotting... only for point testing).

Here is a short example showing some issues with a unit rectangle...

>>> from matplotlib.path import Path
>>> cw_path = Path([[0,0], [0,1], [1,1], [1,0]])
>>> ccw_path = Path([[0,0], [1,0], [1,1], [0,1]])
>>> #Point on x axis not detected for either path...
... cw_path.contains_point([0.5, 0])
0
>>> ccw_path.contains_point([0.5, 0])
0
>>> #Add a large radius and ccw_path works, but not cw_path (!!?)...
... r = 0.1
0
1

The following ipython notebook has more detailed tests, but the main
points are in the sample above.
http://nbviewer.ipython.org/7e1b347b8b21b338bee1

I've found at least one reference [1] online indicating that "this
function is intended for use when mouse-clicking". Does that mean I should
not use it for generic point-in-polygon testing?

That entirely depends upon your needs. The algorithm has very low
overhead, but it isn't highly optimized. This makes it ideal for
occasional point tests on arbitrary polygons (such as processing
mouse-clicks). But if you want to systematically do many point tests for
every single polygon, then maybe a more rigorously designed and implemented
algorithm (such as Shapely's) is more suited for your needs. Note that
Shapely's algorithm has higher overhead, but can test many more points
faster than ours.

I hope that clears things up!
Ben Root

···

On Sat, Mar 23, 2013 at 12:09 AM, Russell Warren <russ@...4320...> wrote: