Fast distance calculation for Starcraft2 bot
You should probably have another look at the scipy.spatial module. It provides (hopefully) faster methods for most of these checks using a k-d-tree.

from scipy.spatial import cKDTree

class Points(np.ndarray):
    def __new__(cls, units_or_points):
        obj = np.asarray(units_or_points).view(cls)
        obj.kd_tree = cKDTree(obj)
        return obj

    def closest_to(self, point: Point2) -&gt; Point2:
        """Returns the point of self that is closest to another point."""
        _, i = self.kd_tree.query([[point.x, point.y]])
        return Point2(self[i][0])

    def closer_than(self, point: Point2, distance: Union[int, float]) -&gt; "Points":
        """Returns a new Points object with all points of self that
        are closer than distance to point."""
        selection = self.kd_tree.query_ball_point([point.x, point.y], distance)
        return self[selection]

    def in_distance_between(
        self, point: Point2, distance1: Union[int, float], distance2: Union[int, float]
    ) -&gt; "Points":
        """Returns a new Points object with all points of self
        that are between distance1 and distance2 away from point."""
        selection_close = self.kd_tree.query_ball_point([point.x, point.y], distance1)
        selection_far = self.kd_tree.query_ball_point([point.x, point.y], distance2)
        selection = list(set(selection_far) - set(selection_close))
        return self[selection]

    def closest_n_points(self, point: Point2, n: int) -&gt; "Points":
        """Returns a new Points object with the n points of self that are closest to point."""
        _, indices = self.kd_tree.query([[point.x, point.y]], k=n)
        return self[indices]

    def in_distance_of_points(self, points: "Points", distance: Union[int, float]) -&gt; "Points":
        """Returns a new Points object with every point of self that
        is in distance of any point in points."""
        pairs = self.kd_tree.query_ball_tree(points.kd_tree, distance)
        return points[[i for closest in pairs for i in closest]]


These are all the ones I could quickly find a way for using the tree. Not included are sort_by_distance_to, n_closest_to_distance and n_closest_to_distance.

In order to test if this is really faster, here are some tests, with the following setup:

np.random.seed(42)
points = np.random.rand(300, 2)
points_graipher = Points(points)
points_op = PointsOP(points)
point = Point2(np.random.rand(2))
points2 = np.random.rand(10, 2)
points2_graipher = Points(points2)


Here PointsOP is you class and Points is the class defined in this answer.

%timeit points_op.closest_to(point)
# 38.3 µs ± 1.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit points_graipher.closest_to(point)
# 43.7 µs ± 249 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit points_op.closer_than(point, 0.1)
# 39.5 µs ± 238 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)    
%timeit points_graipher.closer_than(point, 0.1)
# 11 µs ± 26 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit points_op.in_distance_between(point, 0.1, 0.2)
# 52.9 µs ± 275 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit points_graipher.in_distance_between(point, 0.1, 0.2)
# 21.9 µs ± 180 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit points_op.closest_n_points(point, 10)
# 29.5 µs ± 359 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit points_graipher.closest_n_points(point, 10)
# 41.7 µs ± 287 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit points_op.in_distance_of_points(points2, 0.1)
# 116 µs ± 727 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit points_graipher.in_distance_of_points(points2_graipher, 0.1)
# 89.2 µs ± 500 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)


As you can see for \$N = 300\$ points there are some methods which are faster with the KDTree (up to four times), some that are basically the same and some that are slower (by up to two times).

To get a feeling how the different approaches, scale, here are some plots. The only thing changing is the number of points. The steps are 30, 300, 3000, 30000.











To summarize, you should check this for some actual cases you have. Depending on the size of points your implementation or this implementation is faster.