@@ -80,7 +80,7 @@ def segment_hits(cx, cy, x, y, radius):
80
80
"""
81
81
# Process single points specially
82
82
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 )
84
84
return res
85
85
86
86
# We need to lop the last element off a lot.
@@ -89,24 +89,24 @@ def segment_hits(cx, cy, x, y, radius):
89
89
# Only look at line segments whose nearest point to C on the line
90
90
# lies within the segment.
91
91
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 )
94
95
95
96
# Note that there is a little area near one side of each point
96
97
# which will be near neither segment, and another which will
97
98
# be near both, depending on the angle of the lines. The
98
99
# 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
100
101
candidates = candidates & ~ (point_hits [:- 1 ] | point_hits [1 :])
101
102
102
103
# For those candidates which remain, determine how far they lie away
103
104
# from the line.
104
105
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
106
107
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 ()
110
110
return np .concatenate ((points , lines ))
111
111
112
112
@@ -454,16 +454,21 @@ def contains(self, mouseevent):
454
454
else :
455
455
pixels = self .figure .dpi / 72. * self .pickradius
456
456
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
467
472
468
473
ind += self .ind_offset
469
474
0 commit comments