@@ -80,7 +80,7 @@ def segment_hits(cx, cy, x, y, radius):
8080 """
8181 # Process single points specially
8282 if len (x ) <= 1 :
83- res , = np .nonzero (np . hypot (cx - x , cy - y ) <= radius )
83+ res , = np .nonzero ((cx - x ) ** 2 + ( cy - y ) ** 2 <= radius ** 2 )
8484 return res
8585
8686 # We need to lop the last element off a lot.
@@ -89,24 +89,24 @@ def segment_hits(cx, cy, x, y, radius):
8989 # Only look at line segments whose nearest point to C on the line
9090 # lies within the segment.
9191 dx , dy = x [1 :] - xr , y [1 :] - yr
92- u = (cx - xr ) * dx + (cy - yr ) * dy
93- candidates = (0 <= u ) & (u <= dx ** 2 + dy ** 2 )
92+ Lnorm_sq = dx ** 2 + dy ** 2 # Possibly want to eliminate Lnorm==0
93+ u = ((cx - xr ) * dx + (cy - yr ) * dy ) / Lnorm_sq
94+ candidates = (u >= 0 ) & (u <= 1 )
9495
9596 # Note that there is a little area near one side of each point
9697 # which will be near neither segment, and another which will
9798 # be near both, depending on the angle of the lines. The
9899 # following radius test eliminates these ambiguities.
99- point_hits = np . hypot (cx - x , cy - y ) <= radius
100+ point_hits = (cx - x ) ** 2 + ( cy - y ) ** 2 <= radius ** 2
100101 candidates = candidates & ~ (point_hits [:- 1 ] | point_hits [1 :])
101102
102103 # For those candidates which remain, determine how far they lie away
103104 # from the line.
104105 px , py = xr + u * dx , yr + u * dy
105- line_hits = np . hypot (cx - px , cy - py ) <= radius
106+ line_hits = (cx - px ) ** 2 + ( cy - py ) ** 2 <= radius ** 2
106107 line_hits = line_hits & candidates
107-
108- points , = point_hits .nonzero ()
109- lines , = line_hits .nonzero ()
108+ points , = point_hits .ravel ().nonzero ()
109+ lines , = line_hits .ravel ().nonzero ()
110110 return np .concatenate ((points , lines ))
111111
112112
@@ -454,16 +454,21 @@ def contains(self, mouseevent):
454454 else :
455455 pixels = self .figure .dpi / 72. * self .pickradius
456456
457- # Check for collision
458- if self ._linestyle in ['None' , None ]:
459- # If no line, return the nearby point(s)
460- ind , = np .nonzero (
461- np .hypot (xt - mouseevent .x , yt - mouseevent .y ) <= pixels )
462- else :
463- # If line, return the nearby segment(s)
464- ind = segment_hits (mouseevent .x , mouseevent .y , xt , yt , pixels )
465- if self ._drawstyle .startswith ("steps" ):
466- ind //= 2
457+ # The math involved in checking for containment (here and inside of
458+ # segment_hits) assumes that it is OK to overflow, so temporarily set
459+ # the error flags accordingly.
460+ with np .errstate (all = 'ignore' ):
461+ # Check for collision
462+ if self ._linestyle in ['None' , None ]:
463+ # If no line, return the nearby point(s)
464+ ind , = np .nonzero (
465+ (xt - mouseevent .x ) ** 2 + (yt - mouseevent .y ) ** 2
466+ <= pixels ** 2 )
467+ else :
468+ # If line, return the nearby segment(s)
469+ ind = segment_hits (mouseevent .x , mouseevent .y , xt , yt , pixels )
470+ if self ._drawstyle .startswith ("steps" ):
471+ ind //= 2
467472
468473 ind += self .ind_offset
469474
0 commit comments