/// <summary> /// Creates reference points for triangulation. /// /// The first is guaranteed to be the origin, and the second will be the opposite corner and /// have "max" for each of its coordinate values, where max = (2^bits) - 1. /// After that, the patterns will be: /// { max, 0, max, 0, max, 0, ... } /// { max, max, 0, 0, max, max, 0, 0, ... } /// { max, max, max, 0, 0, 0, max, max, max, 0, 0, 0, ... } /// { max, max, max, max, 0, 0, 0, 0, max, max, max, max, 0, 0, 0, 0, ... } /// </summary> /// <returns>The reference points.</returns> /// <param name="dimensions">Number of Dimensions for each point.</param> /// <param name="bits">Bits per coordinate.</param> /// <param name="numTriangulationPoints">Number of triangulation points to create.</param> private static UnsignedPoint[] CreateReferencePoints(int dimensions, int bits, int numTriangulationPoints) { var tPoints = new UnsignedPoint[numTriangulationPoints]; var max = (uint)((1 << bits) - 1); // The origin tPoints[0] = new UnsignedPoint(new uint[dimensions]); // The corner opposite the origin. tPoints[1] = new UnsignedPoint( Enumerable.Range(0, dimensions).Select(i => max).ToArray() ); foreach (var i in Enumerable.Range(2, numTriangulationPoints - 2)) { var coordinates = new uint[dimensions]; for (var iDim = 0; iDim < dimensions; iDim++) { if ((iDim / (i - 1)) % 2 == 0) { coordinates[i] = max; } } tPoints[i] = new UnsignedPoint(coordinates); } return(tPoints); }
public Triangulator(UnsignedPoint point, int bits, int numTriangulationPoints = 10) { Key = LookupKey(point.Dimensions, bits, numTriangulationPoints); var refPoints = GetReferencePoints(point.Dimensions, bits, numTriangulationPoints); ReferenceSquareDistances = new long[numTriangulationPoints]; ReferenceDistances = new double[numTriangulationPoints]; for (var iTri = 0; iTri < numTriangulationPoints; iTri++) { ReferenceSquareDistances[iTri] = point.Measure(refPoints[iTri]); ReferenceDistances[iTri] = Math.Sqrt(ReferenceSquareDistances[iTri]); } }
/// <summary> /// If the point is already a HilbertPoint, return it unchanged, otherwise create a new one /// that contains the same coordinates yet has a Hilbert index. /// </summary> /// <returns>A HilbertPoint.</returns> /// <param name="uPoint">U point.</param> /// <param name="bitsPerDimension">Bits per dimension.</param> /// <param name="useSameKey">If true and a new point is created, it will share the same key as the original.</param> public static HilbertPoint CastOrConvert(UnsignedPoint uPoint, int bitsPerDimension, bool useSameKey = false) { HilbertPoint hPoint = uPoint as HilbertPoint; if (hPoint == null || hPoint.BitsPerDimension != bitsPerDimension) { if (useSameKey) { hPoint = new HilbertPoint(uPoint.Coordinates, bitsPerDimension, uPoint.MaxCoordinate, uPoint.SquareMagnitude, uPoint.UniqueId); } else { hPoint = new HilbertPoint(uPoint.Coordinates, bitsPerDimension, uPoint.MaxCoordinate, uPoint.SquareMagnitude); } } return(hPoint); }
/// <summary> /// Can Triangulation bypass the need to compute the ful distance? /// /// THis method is only used for testing. /// </summary> /// <param name="other">Other.</param> /// <param name="squareDistance">Square distance.</param> public bool Triangulatable(UnsignedPoint other, long squareDistance) { var hPoint = other as HilbertPoint; if (hPoint == null) { return(false); } if (Triangulation.ArePointsFartherForSure(hPoint.Triangulation, squareDistance)) { return(true); } if (Triangulation.ArePointsNearerForSure(hPoint.Triangulation, squareDistance)) { return(true); } return(false); }
public override int SquareDistanceCompare(UnsignedPoint other, long squareDistance) { var hPoint = other as HilbertPoint; if (hPoint == null) { return(base.SquareDistanceCompare(other, squareDistance)); } if (Triangulation.ArePointsFartherForSure(hPoint.Triangulation, squareDistance)) { return(1); } if (Triangulation.ArePointsNearerForSure(hPoint.Triangulation, squareDistance)) { return(-1); } return(Measure(other).CompareTo(squareDistance)); }