def _compute_projection_pick(artist, path, xy):
transform = artist.get_transform().frozen()<EOL>tpath = (path.cleaned(transform) if transform.is_affine<EOL>else transform.transform_path(path).cleaned())<EOL>vertices = tpath.vertices[:-<NUM_LIT:1>]<EOL>codes = tpath.codes[:-<NUM_LIT:1>]<EOL>vertices[codes == tpath.CLOSEPOLY] = vertices[<NUM_LIT:0>]<EOL>us = vertices[<NUM_LIT:1>:] - vertices[:-<NUM_LIT:1>]<EOL>ls = np.hypot(*us.T)<EOL>with np.errstate(invalid="<STR_LIT:ignore>"):<EOL><INDENT>us /= ls[:, None]<EOL><DEDENT>vs = xy - vertices[:-<NUM_LIT:1>]<EOL>with np.errstate(invalid="<STR_LIT:ignore>"):<EOL><INDENT>dot = np.clip(np.einsum("<STR_LIT>", vs, us), <NUM_LIT:0>, ls, out=vs[:, <NUM_LIT:0>])<EOL><DEDENT>projs = vertices[:-<NUM_LIT:1>] + dot[:, None] * us<EOL>ds = np.hypot(*(xy - projs).T, out=vs[:, <NUM_LIT:1>])<EOL>try:<EOL><INDENT>argmin = np.nanargmin(ds)<EOL>dmin = ds[argmin]<EOL><DEDENT>except (ValueError, IndexError):  <EOL><INDENT>return<EOL><DEDENT>else:<EOL><INDENT>target = AttrArray(<EOL>artist.axes.transData.inverted().transform_point(projs[argmin]))<EOL>target.index = (<EOL>(argmin + dot[argmin] / ls[argmin])<EOL>/ (path._interpolation_steps / tpath._interpolation_steps))<EOL>return Selection(artist, target, dmin, None, None)<EOL><DEDENT>
Project *xy* on *path* to obtain a `Selection` for *artist*.

*path* is first transformed to screen coordinates using the artist
transform, and the target of the returned `Selection` is transformed
back to data coordinates using the artist *axes* inverse transform.  The
`Selection` `index` is returned as a float.  This function returns ``None``
for degenerate inputs.

The caller is responsible for converting the index to the proper class if
needed.