/// <summary> /// Compose a random point whose values fall between Minimum (inclusive) and Maximum (exclusive) but /// which is no closer to all previous points than MinimumDistance. /// /// NOTE: If too many unsuccessful attempts are made to find such a point, null will be returned instead. /// </summary> /// <param name="point">Point whose coordinate values will be changed. /// The values will be changed in place. /// This array must have at least as many elements as Dimensions. /// </param> /// <returns>The same point with changes made, or null, if no point could be found.</returns> public override int[] Generate(int[] p) { UnsignedPoint pt; var intPoint = FindSeparatedPoint(out pt); if (intPoint != null) { PreviousPoints.Add(pt); Array.Copy(intPoint, p, Dimensions); return(p); } else { return(null); } }
/// <summary> /// Find a point far enough away from the previous points, /// but do not record it yet as a Previous Point. /// </summary> /// <param name="uPoint">UnsignedPoint made from the returned array, or null.</param> /// <returns>A point well-separated from all previous points, or null if none could be found. /// </returns> public int[] FindSeparatedPoint(out UnsignedPoint uPoint) { var minDistSquared = (long)Math.Ceiling(MinimumDistance * MinimumDistance); var tries = 0; var point = new int[Dimensions]; while (tries < 100) { for (var iDim = 0; iDim < AffectedDimensions.Count; iDim++) { point[iDim] = Rng.Next(Minimum, Maximum); } var pt = new UnsignedPoint(point); // Copies the array. if (!PreviousPoints.Any(p => p.Measure(pt) < minDistSquared)) { uPoint = pt; return(point); } tries++; } uPoint = null; return(null); }
/// <summary> /// Generate a chain of close points, each seperated by the given segmentLength. /// No points from this chain will be close to any points from previous chains. /// </summary> /// <param name="chainLength"></param> /// <param name="segmentLength"></param> /// <returns>A list of chainLength points (or fewer, if we can't find any more).</returns> public List <int[]> GenerateChain(int chainLength, int segmentLength) { var segSquaredLength = (long)segmentLength * segmentLength; var chain = new List <int[]>(); var currentUnsignedChain = new List <UnsignedPoint>(); UnsignedPoint uPoint = null; var currentPoint = FindSeparatedPoint(out uPoint); if (currentPoint == null) { return(chain); } currentUnsignedChain.Add(uPoint); chain.Add(currentPoint); var failures = 0; while (chain.Count() < chainLength && failures < 20) { var nextPoint = RandomStep(currentPoint, segmentLength); uPoint = new UnsignedPoint(nextPoint); if (IsSeparatedPoint(uPoint)) { chain.Add(nextPoint); currentUnsignedChain.Add(uPoint); currentPoint = nextPoint; } else { failures++; } } PreviousPoints.AddRange(currentUnsignedChain); var startToFinishDistance = currentUnsignedChain.First().Distance(currentUnsignedChain.Last()); return(chain); }
public bool IsSeparatedPoint(UnsignedPoint pt) { var minDistSquared = (long)Math.Ceiling(MinimumDistance * MinimumDistance); return(!PreviousPoints.Any(p => p.Measure(pt) < minDistSquared)); }