static IEnumerable <(PlaneCoordinate Coordinate, int MapIndex)> ExtendPattern (IList <int> decodePattern, int width, int height, short plane, int planePatternSize, int patternSize) { int imageSize = width * height; int pixelIndex = 0; int repeat = 0; while (pixelIndex < width * height) { int extendSize = Math.Min(planePatternSize, imageSize); for (int i = 0; i < extendSize; i++) { var bitIndex = decodePattern[pixelIndex % planePatternSize]; short x = (short)(pixelIndex % width); short y = (short)(pixelIndex / width); var coord = new PlaneCoordinate(x, y, plane); var index = bitIndex + repeat * patternSize; yield return(coord, index); pixelIndex++; } repeat++; } }
public int GetEncodeIndex(PlaneCoordinate coordinate) { if (_encodePattern.TryGetValue(coordinate, out var bitIndex)) { return(bitIndex); } throw new KeyNotFoundException($"{nameof(GetEncodeIndex)} argument {nameof(coordinate)} ({coordinate.X}, {coordinate.Y}, {coordinate.P}) was found in the encoder remapping"); }
private static Tuple<PlaneCoordinate, PlaneCoordinate> DivideConquerClosestPair(PlaneCoordinate[] coordinates) { // sort by x and y Sorter<double> mergeSort = new MergeSort<double>(); double[] px = mergeSort.Sort(coordinates.Select(p => p.X).ToArray()); double[] py = mergeSort.Sort(coordinates.Select(p => p.Y).ToArray()); return FindClosestPair(px, py); }
public void FindClosestPair_TwoPoints_ReturnsExpected() { // arrange PlaneCoordinate x = new PlaneCoordinate(0, 0); PlaneCoordinate y = new PlaneCoordinate(0, 1); ClosestPair algorithm = new ClosestPair(); // act Tuple<PlaneCoordinate, PlaneCoordinate> closestPair = algorithm.FindClosestPair(new[] { x, y }); // assert Assert.AreEqual(closestPair.Item1, x); Assert.AreEqual(closestPair.Item2, y); }
public void FindClosestPair_AllAxesDifferent_ReturnsExpected() { // arrange PlaneCoordinate x = new PlaneCoordinate(0, 1); PlaneCoordinate y = new PlaneCoordinate(1, 5); PlaneCoordinate z = new PlaneCoordinate(4, -10); ClosestPair algorithm = new ClosestPair(); // act Tuple<PlaneCoordinate, PlaneCoordinate> closestPair = algorithm.FindClosestPair(new[] { x, y, z }); // assert Assert.AreEqual(closestPair.Item1, x); Assert.AreEqual(closestPair.Item2, y); }
/// <summary> /// Brute-force closest pair implementation. /// </summary> /// <param name="coordinates">The coordinates.</param> /// <returns>Closest pair.</returns> private static Tuple<PlaneCoordinate, PlaneCoordinate> BruteForceClosestPair(PlaneCoordinate[] coordinates) { if (coordinates == null) { throw new ArgumentNullException("coordinates"); } if (coordinates.Length < 2) { throw new ArgumentException("At least two points must be passed.", "coordinates"); } double minDistance = double.MaxValue; int minI = -1, minJ = -1; for (int i = 0; i < coordinates.Length; i++) { for (int j = i; j < coordinates.Length; j++) { if (i == j) { continue; } double distance = coordinates[i].Distance(coordinates[j]); if (distance < minDistance) { minI = i; minJ = j; minDistance = distance; } } } return new Tuple<PlaneCoordinate, PlaneCoordinate>( coordinates[minI], coordinates[minJ]); }
private static Tuple<PlaneCoordinate, PlaneCoordinate> FindClosestPair(double[] px, double[] py) { if (px.Length == 2) { return new Tuple<PlaneCoordinate, PlaneCoordinate>(new PlaneCoordinate(px[0], py[0]), new PlaneCoordinate(px[1], py[1])); } double minDistance; if (px.Length == 3) { PlaneCoordinate a = new PlaneCoordinate(px[0], py[0]); PlaneCoordinate b = new PlaneCoordinate(px[1], py[1]); PlaneCoordinate c = new PlaneCoordinate(px[2], py[2]); double ab = a.Distance(b); double ac = a.Distance(c); double bc = b.Distance(c); minDistance = Math.Min(ab, Math.Min(ac, bc)); if (minDistance == ab) { return new Tuple<PlaneCoordinate, PlaneCoordinate>(a, b); } if (minDistance == ac) { return new Tuple<PlaneCoordinate, PlaneCoordinate>(a, c); } return new Tuple<PlaneCoordinate, PlaneCoordinate>(b, c); } // divide int middle = px.Length / 2; // left double[] qpx = new double[middle]; Array.Copy(px, qpx, qpx.Length); double[] qpy = new double[middle]; Array.Copy(py, qpy, qpy.Length); // right double[] rpx = new double[px.Length - middle]; Array.Copy(px, middle, rpx, 0, rpx.Length); double[] rpy = new double[px.Length - middle]; Array.Copy(py, middle, rpy, 0, rpy.Length); // conquer Tuple<PlaneCoordinate, PlaneCoordinate> p1q1 = FindClosestPair(qpx, qpy); double dist1 = p1q1.Item1.Distance(p1q1.Item2); Tuple<PlaneCoordinate, PlaneCoordinate> p2q2 = FindClosestPair(rpx, rpy); double dist2 = p2q2.Item1.Distance(p2q2.Item2); minDistance = Math.Min(dist1, dist2); Tuple<PlaneCoordinate, PlaneCoordinate> p3q3 = ClosestPairSplit(px, py, minDistance); double dist3 = p3q3.Item1.Distance(p3q3.Item2); minDistance = Math.Min(minDistance, dist3); if (minDistance == dist1) { return p1q1; } if (minDistance == dist2) { return p2q2; } return p3q3; }
/// <summary> /// Finds the closest pair in a set of coordinates. /// </summary> /// <param name="coordinates">The coordinates.</param> /// <returns>Closest pair.</returns> public Tuple<PlaneCoordinate, PlaneCoordinate> FindClosestPair( PlaneCoordinate[] coordinates) { return BruteForceClosestPair(coordinates); }