diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index f5ac14dff34d..6e889968642f 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1392,15 +1392,18 @@ def _find_nearest_contour(self, xy, indices=None): for idx_level in indices: path = self._paths[idx_level] - if not len(path.vertices): - continue - lc = self.get_transform().transform(path.vertices) - d2, proj, leg = _find_closest_point_on_path(lc, xy) - if d2 < d2min: - d2min = d2 - idx_level_min = idx_level - idx_vtx_min = leg[1] - proj_min = proj + idx_vtx_start = 0 + for subpath in path._iter_connected_components(): + if not len(subpath.vertices): + continue + lc = self.get_transform().transform(subpath.vertices) + d2, proj, leg = _find_closest_point_on_path(lc, xy) + if d2 < d2min: + d2min = d2 + idx_level_min = idx_level + idx_vtx_min = leg[1] + idx_vtx_start + proj_min = proj + idx_vtx_start += len(subpath) return idx_level_min, idx_vtx_min, proj_min diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index db8ef03925cd..f79584be4086 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -125,6 +125,25 @@ def test_contour_manual_labels(split_collections): plt.clabel(cs, manual=pts, fontsize='small', colors=('r', 'g')) +def test_contour_manual_moveto(): + x = np.linspace(-10, 10) + y = np.linspace(-10, 10) + + X, Y = np.meshgrid(x, y) + + Z = X**2 * 1 / Y**2 - 1 + + contours = plt.contour(X, Y, Z, levels=[0, 100]) + + # This point lies on the `MOVETO` line for the 100 contour + # but is actually closest to the 0 contour + point = (1.3, 1) + clabels = plt.clabel(contours, manual=[point]) + + # Ensure that the 0 contour was chosen, not the 100 contour + assert clabels[0].get_text() == "0" + + @pytest.mark.parametrize("split_collections", [False, True]) @image_comparison(['contour_disconnected_segments'], remove_text=True, style='mpl20', extensions=['png'])