public static Rect GetSupportRect(FloorPlan floorPlan, IRoomGen oldGen, IRoomGen newGen, Dir4 dir, List <RoomHallIndex> adjacentsInDir) { bool vertical = dir.ToAxis() == Axis4.Vert; Rect supportRect = newGen.Draw; supportRect.Start += dir.GetLoc() * supportRect.Size.GetScalar(dir.ToAxis()); supportRect.SetScalar(dir, oldGen.Draw.GetScalar(dir)); IntRange minMax = newGen.Draw.GetSide(dir.ToAxis()); foreach (RoomHallIndex adj in adjacentsInDir) { IRoomGen adjGen = floorPlan.GetRoomHall(adj).RoomGen; IntRange adjMinMax = adjGen.Draw.GetSide(dir.ToAxis()); minMax = new IntRange(Math.Min(adjMinMax.Min, minMax.Min), Math.Max(adjMinMax.Max, minMax.Max)); } IntRange oldMinMax = oldGen.Draw.GetSide(dir.ToAxis()); minMax = new IntRange(Math.Max(oldMinMax.Min, minMax.Min), Math.Min(oldMinMax.Max, minMax.Max)); if (vertical) { supportRect.SetScalar(Dir4.Left, minMax.Min); supportRect.SetScalar(Dir4.Right, minMax.Max); } else { supportRect.SetScalar(Dir4.Up, minMax.Min); supportRect.SetScalar(Dir4.Down, minMax.Max); } return(supportRect); }
protected static ListPathTraversalNode?GetRoomToConnect(FloorPlan floorPlan, RoomHallIndex chosenFrom, Dir4 dir) { // extend a rectangle to the border of the floor in the chosen direction bool vertical = dir.ToAxis() == Axis4.Vert; int dirSign = dir.GetLoc().GetScalar(dir.ToAxis()); IRoomGen genFrom = floorPlan.GetRoomHall(chosenFrom).RoomGen; Rect sampleRect = genFrom.Draw; // expand from the start of that border direction to the borders of the floor sampleRect.Start += dir.GetLoc() * sampleRect.Size.GetScalar(dir.ToAxis()); // it doesn't have to be exactly the borders so just add the total size to be sure sampleRect.Expand(dir, vertical ? floorPlan.Size.Y : floorPlan.Size.X); // find the closest room. var chosenTo = new RoomHallIndex(-1, false); foreach (RoomHallIndex collision in floorPlan.CheckCollision(sampleRect)) { Rect collidedRect = floorPlan.GetRoomHall(collision).RoomGen.Draw; // limit the expansion by direction int sampleScalar = sampleRect.GetScalar(dir); int collidedScalar = collidedRect.GetScalar(dir.Reverse()); bool limit = dirSign == Math.Sign(sampleScalar - collidedScalar); if (limit) { // update the boundaries sampleRect.SetScalar(dir, collidedScalar); chosenTo = collision; } } // if it didn't collide with ANYTHING, then quit if (chosenTo.Index == -1) { return(null); } IRoomGen genTo = floorPlan.GetRoomHall(chosenTo).RoomGen; // narrow the rectangle if touching something on the side // widen the rectangle by width Rect widthRect = sampleRect; widthRect.Inflate(vertical ? 1 : 0, vertical ? 0 : 1); bool retractLeft = false; bool retractRight = false; Dir4 leftDir = DirExt.AddAngles(dir, Dir4.Left); Dir4 rightDir = DirExt.AddAngles(dir, Dir4.Right); foreach (RoomHallIndex collision in floorPlan.CheckCollision(widthRect)) { Rect collidedRect = floorPlan.GetRoomHall(collision).RoomGen.Draw; if (!retractLeft) { if (collidedRect.GetScalar(leftDir.Reverse()) == sampleRect.GetScalar(leftDir)) { retractLeft = true; } } if (!retractRight) { if (collidedRect.GetScalar(rightDir.Reverse()) == sampleRect.GetScalar(rightDir)) { retractRight = true; } } } // retract the rectangle if (retractLeft) { sampleRect.Expand(leftDir, -1); } if (retractRight) { sampleRect.Expand(rightDir, -1); } // if the rectangle has been retracted too much, we can't go on if (sampleRect.Area <= 0) { return(null); } // check for border availability between start and end bool foundFrom = HasBorderOpening(genFrom, sampleRect, dir); bool foundTo = HasBorderOpening(genTo, sampleRect, dir.Reverse()); // return the expansion if one is found if (foundFrom && foundTo) { return(new ListPathTraversalNode(chosenFrom, chosenTo, sampleRect)); } else { return(null); } }