/// <summary> /// /// </summary> /// <param name="suite"></param> /// <returns></returns> private void PlaceByAxis() { if (Rooms.Count == 0) { return; } var area = 0.0; foreach (var room in Rooms) { area += room.Area; } var roomRows = new List <RoomRow>(); while (RoomsPlaced.Count < Rooms.Count) { roomRows.Clear(); Perimeter = Shaper.RectangleByArea(area * 0.5, Ratio); var roomRow = new RoomRow(Perimeter); roomRows.Add(roomRow); var i = 0; while (i < Rooms.Count) { if (!roomRow.AddRoomFitted(Rooms[i], false)) { break; } i++; } if (i == Rooms.Count) { return; } var compass = Perimeter.Compass(); var row = new Line(compass.SE, compass.SW); var matchRow = new RoomRow(row, area / row.Length()); roomRows.Add(matchRow); while (i < Rooms.Count) { if (!matchRow.AddRoomFitted(Rooms[i], false)) { break; } i++; } Ratio += 0.1; } Rooms.Clear(); foreach (var roomRow in roomRows) { foreach (var room in roomRow.Rooms) { Rooms.Add(room); } } Perimeter = Footprint; }
/// <summary> /// Creates a Room plan from a Polygon centerline as the double-loaded corridor. Assumes sides of the Story Perimeter are parallel to the centerline. /// </summary> /// <param name="ctrLine">Polyline centerline of the Corridor.</param> /// <param name="roomArea">Desired area of each Room.</param> /// <param name="corridorWidth">Width of the Corridor.</param> /// <param name="corridorOffset">Offset of the Corridor end from the Perimeter.</param> public void PlanByCenterline(Polyline ctrLine, double roomArea, double corridorWidth, double corridorOffset) { var perLines = Perimeter.Segments(); var ctrLines = ctrLine.Segments(); var rows = new List <Polygon>(); foreach (var line in ctrLines) { var sides = new List <Line>(); foreach (var perLine in perLines) { if (perLine.IsParallelTo(line)) { sides.Add(perLine); } } if (sides.Count() < 2) { continue; } sides = sides.OrderBy(s => s.Midpoint().DistanceTo(line.Midpoint())).ToList(); sides = new List <Line>() { sides[0], sides[1] }; foreach (var side in sides) { var points = new List <Vector3>(); foreach (var vertex in new List <Vector3>() { line.Start, line.End, side.Start, side.End }) { points.Add(new Vector3(vertex.X, vertex.Y, 0.0)); } Polygon polygon; try { polygon = new Polygon(points); } catch (Exception) { polygon = new Polygon(new[] { points[0], points[1], points[3], points[2] }); } rows.Add(polygon); } } foreach (var row in rows) { var roomRow = new RoomRow(row); roomRow.Populate(roomArea, Height); foreach (var room in roomRow.Rooms) { AddRoom(room); } } var ctrPnts = new List <Vector3>() { ctrLines.First().PositionAt(corridorOffset) }; foreach (var line in ctrLines) { ctrPnts.Add(line.End); } ctrPnts.Reverse(); ctrPnts = ctrPnts.Skip(1).ToList(); ctrPnts.Reverse(); ctrPnts.Add(ctrLines.Last().PositionAt(ctrLines.Last().Length() - corridorOffset)); var ctrCorridor = new Polyline(ctrPnts); var corridor = new Room(ctrCorridor.Offset(corridorWidth * 0.5, EndType.Square).First(), Height); AddCorridor(corridor); }
/// <summary> /// /// </summary> /// <param name="suite"></param> /// <returns></returns> private void PlaceReciprocal() { if (Rooms.Count == 0) { return; } var area = 0.0; foreach (var room in Rooms) { area += room.Area; } var roomRows = new List <RoomRow>(); while (RoomsPlaced.Count < Rooms.Count) { roomRows.Clear(); Perimeter = Shaper.RectangleByArea(area, Ratio); var roomRow = new RoomRow(Perimeter); roomRows.Add(roomRow); var i = 0; while (i < Rooms.Count) { if (!roomRow.AddRoomFitted(Rooms[i], false)) { break; } i++; } if (i == Rooms.Count) { return; } var perimeter = Shaper.Differences(roomRow.Perimeter.ToList(), roomRow.Footprint.ToList()); if (perimeter.Count == 0) { break; } var matchRow = new RoomRow(perimeter.First()); roomRows.Add(matchRow); while (i < Rooms.Count) { if (!matchRow.AddRoomFitted(Rooms[i], true)) { break; } i++; } Ratio += 0.1; } Rooms.Clear(); foreach (var roomRow in roomRows) { foreach (var room in roomRow.Rooms) { Rooms.Add(room); } } //2020.07.09 Anthony Hauck //Commented code makes suite geometric room diffs into one or more extra rooms. //Overall the results were more confusing that just ignoring them, but leaving //this here in case future developers have a better idea. //var lastRow = roomRows.Last(); //var rooms = lastRow.RoomsAsPolygons; //var diffs = lastRow.Perimeter.Difference(rooms).ToList(); //if (diffs.Count > 0) //{ // var height = lastRow.Rooms.Last().Height; // diffs = Shaper.Merge(diffs); // foreach (var diff in diffs) // { // Rooms.Add( // new Room(diff, height) // { // Color = Palette.White // }); // } //} Perimeter = Footprint; }