Adjacent distance method¶
The distance method finds a knee by searching for the point which is as far as possible from the line going through the point’s neighbours.
For every point except for the two edge points, a line is passed through the two points’ neighbour points. Then, an orthogonal distance is measured from the point to that line. The point which is the furthest from the line is declared the knee.
This method is quite sensitive to the input noise, so consider smoothing the input with cubic spline smoothing.
Implementation [1]¶
Let’s assume we have a triangle with three points: \(P_0(x_0, y_0)\), \(P_1(x_1, y_1)\) and \(P_2(x_2, y_2)\). Let’s also assume we want to calculate the distance from the point \(P_0\) to the line going through \(P_1\) and \(P_2\).
The distance from a point to the line, given a line and the point, as per [2] is:
If you really look at the equation, the denominator looks like the length of some vector, and the numerator looks kinda like a determinant of some matrix. We’ll try to express that matrix and that vector using our points.
Let’s translate this entire triangle so that \(P_1\) becomes the origin \(O(0, 0)\). This means we now have \(P'_1(0, 0)\), \(P'_0(x'_0=x_0-x_1, y'_0=y_0-y_1)\) and \(P'_2(x'_2=x_2-x_1, y'_2=y_2-y_1)\). Rewriting the distance yields:
The implementation makes use of the derived final form.
First, all length 3 consecutive windows are extracted from the input points using fancy NumPy indexing. The middle of the three points acts as the point \(P_0\), and the left and right neigbour act as points \(P_1\) and \(P_2\), respectively.
Then, \(P_1\) is subtracted from both \(P_0\) and \(P_2\).
The determinant and the (now prime) \(P'_2\) vector length are computed
The determinant is divided with the vector length, yielding the resulting distance
The implementation heavily relies on NumPy broadcasting and indexing, so all computations for all points are performed at once.