private LandblockGroup DoTrySplit() { var landblockGroupSplitHelper = new LandblockGroupSplitHelper(); var remainingLandblocks = new List <Landblock>(landblocks); landblockGroupSplitHelper.Add(remainingLandblocks[remainingLandblocks.Count - 1]); remainingLandblocks.RemoveAt(remainingLandblocks.Count - 1); doAnotherPass: bool needsAnotherPass = false; for (int i = remainingLandblocks.Count - 1; i >= 0; i--) { if (landblockGroupSplitHelper.BoundaryDistance(remainingLandblocks[i]) < LandblockGroupMinSpacing) { landblockGroupSplitHelper.Add(remainingLandblocks[i]); remainingLandblocks.RemoveAt(i); needsAnotherPass = true; } } if (needsAnotherPass) { goto doAnotherPass; } // If they're the same size, there's no split possible if (Count == landblockGroupSplitHelper.Count) { return(null); } // Split was a success var newLandblockGroup = new LandblockGroup(); foreach (var landblock in landblockGroupSplitHelper) { // Remove the split landblocks. Do this manually, not through the public Remove() function landblocks.Remove(landblock); // Add them through the proper .Add() method to the new LandblockGroup newLandblockGroup.Add(landblock); } RecalculateBoundaries(); // This can result in returning groups that overlap this ones boundary. // However, that isn't a problem for processing them on separate threads. // In the event a new landblock is added that is within range of both this block and any new block, they will be recombined at that point. return(newLandblockGroup); }
/// <summary> /// This will calculate the distance between the landblock group boarders.<para /> /// -X = Inside the bounds, where -1 is an overlapping outer perimeter<para /> /// 0 = Outside of the bounds but adjacent (touching)<para /> /// +X = Has X landblocks between this and the bounds of the group<para /> /// Distances are measured horizontally and vertically (not diagonally) pictured here: https://math.stackexchange.com/questions/2724537/finding-the-clear-spacing-distance-between-two-rectangles /// </summary> public int BoundaryDistance(LandblockGroup landblockGroup) { return((int)Math.Max( Math.Abs(xCenter - landblockGroup.xCenter) - (width + landblockGroup.width) / 2.0, Math.Abs(yCenter - landblockGroup.yCenter) - (height + landblockGroup.height) / 2.0)); }