-
Notifications
You must be signed in to change notification settings - Fork 299
/
Copy pathClosestPointPair.cs
67 lines (53 loc) · 1.91 KB
/
ClosestPointPair.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System;
using System.Collections.Generic;
using System.Linq;
namespace Advanced.Algorithms.Geometry;
/// <summary>
/// Closest-point pair finder.
/// </summary>
public class ClosestPointPair
{
public static double Find(List<int[]> points)
{
var xSorted = points
.Select(z => new Point(z[0], z[1]))
.OrderBy(p => p.X).ToList();
return Find(xSorted, 0, points.Count - 1);
}
public static double Find(List<Point> points, int left, int right)
{
if (right - left <= 3) return BruteForce(points, left, right);
var mid = (left + right) / 2;
var leftMin = Find(points, 0, mid);
var rightMin = Find(points, mid + 1, right);
var min = Math.Min(leftMin, rightMin);
var midX = points[mid].X;
var strips = new List<Point>();
for (var i = left; i <= right; i++)
if (Math.Abs(points[i].X - midX) < min)
strips.Add(points[i]);
//vertical strips within the radius of min
strips = strips.OrderBy(p => p.Y).ToList();
for (var i = 0; i < strips.Count; i++)
for (var j = i + 1; j < strips.Count && Math.Abs(strips[i].Y - strips[j].Y) < min; j++)
//check for radius
min = Math.Min(min, GetDistance(strips[i], strips[j]));
return min;
}
private static double BruteForce(IList<Point> points, int left, int right)
{
var min = double.MaxValue;
for (var i = left; i < right; i++)
for (var j = left + 1; j <= right; j++)
min = Math.Min(min, GetDistance(points[i], points[j]));
return min;
}
/// <summary>
/// Eucledian distance.
/// </summary>
private static double GetDistance(Point point1, Point point2)
{
return Math.Sqrt(Math.Pow(Math.Abs(point1.X - point2.X), 2)
+ Math.Pow(Math.Abs(point1.Y - point2.Y), 2));
}
}