I would use the method suggested by Justin, with one adjustment. He suggests using a map table with fractional indices, although I would suggest integer indices. This may seem a little mathematical, but not ashamed to read the next two times (I would have to too). Suppose that the point in the index, I in the list of pairs A, searched for the nearest points in another list B, and the nearest point is indicated in the index j. To find the nearest point in B to A [i + 1], you should only consider points in B with an index equal to or greater than j. It will probably be j + 1, but it can be j or j + 2, j + 3, etc., but not lower than j. Even if the point closest to A [i + 1] has an index smaller than j, you still should not use this point for interpolation, as this will lead to an unexpected average and graph. Now I will take a moment to create a sample code for you. I hope you see that this optimization makes sense.
EDIT: when implementing this, I realized that j is not only bounded from below (as described above), but also bounded from above. When you try the distance from A [i + 1] to B [j], B [j + 1], B [j + 2], etc., you can stop comparing when the distance A [i + 1] to B [j + ...] stops decreasing. It makes no sense to look further in B. The same reasoning applies when j is bounded below: even if some point in another place of B is closer, perhaps this is not the point with which you want to interpolate. This will lead to an unexpected schedule, perhaps less smooth than you expected. And the added bonus of this second binding is improved performance. I created the following code:
IEnumerable<Tuple<double, double>> Average(List<Tuple<double, double>> A, List<Tuple<double, double>> B) { if (A == null || B == null || A.Any(p => p == null) || B.Any(p => p == null)) throw new ArgumentException(); Func<double, double> square = d => d * d;
For your information, the Average function returns the same amount of interpolated points that List A contains, which is probably good, but you should think about this for your specific application. I added a few comments to clarify some details, and I described all aspects of this code in the text above. I hope this is clear, and otherwise feel free to ask questions.
SECOND EDIT: I misunderstood and thought that you have only two points lists. I have created a generic function of the above multiple list reception. He still uses only those principles that have been described above.
IEnumerable<Tuple<double, double>> Average(List<List<Tuple<double, double>>> data) { if (data == null || data.Count < 2 || data.Any(list => list == null || list.Any(p => p == null))) throw new ArgumentException(); Func<double, double> square = d => d * d; Func<Tuple<double, double>, Tuple<double, double>, double> euclidianDistance = (a, b) => Math.Sqrt(square(a.Item1 - b.Item1) + square(a.Item2 - b.Item2)); var firstList = data[0]; for (int i = 0; i < firstList.Count; i++) { int[] previousIndices = new int[data.Count];
In fact, that I made a specific case for the two lists separately, perhaps it was good: it is easy to explain and offers a step to understanding the generalized version. In addition, the square root could be taken out, since it does not change the order of the distances when sorting, just the length.
THIRD CHANGE: In the comments, it became clear that there might be a mistake. I think that there is no, except for the mentioned small error, which should not have any meaning, except at the end of the graphs. As evidence that it really works, this is the result of it (the dashed line is the middle): 