/// <summary> /// Creates a group of rooms by dividing the supplied Polygon perimeter by the quantity of supplied divisions along the orthogonal x and y axes. Room perimeters conform to fit within the supplied Polygon. /// </summary> /// <param name="perimeter">The Polygon to divide with a number of Room perimeters.</param> /// <param name="xRooms">The quantity of Rooms along the x axis.</param> /// <param name="yRooms">The quantity of Rooms along the y axis.</param> /// <param name="name">An arbitrary string identifier for this RoomGroup.</param> /// <returns> /// A new RoomGroup. /// </returns> public RoomGroup(Polygon perimeter, int xRooms = 1, int yRooms = 1, string name = "") { Perimeter = new Polygon(perimeter.Vertices); Name = name; Box = new TopoBox(perimeter); Rooms = new List <Room>(); var sizeX = Box.SizeX / xRooms; var sizeY = Box.SizeY / yRooms; var count = xRooms * yRooms; for (int xIdx = 0; xIdx < xRooms; xIdx++) { var xCoord = Box.SW.X + (xIdx * sizeX); for (int yIdx = 0; yIdx < yRooms; yIdx++) { var yCoord = Box.SW.Y + (yIdx * sizeY); var polygon = Shaper.PolygonBox(sizeX, sizeY); polygon = polygon.MoveFromTo(new Vector3(), new Vector3(xCoord, yCoord)).Intersection(perimeter).First(); var room = new Room() { Color = Palette.Aqua, Perimeter = polygon }; Rooms.Add(room); } } }
/// <summary> /// Attempts to place a Room perimeter on the next open segment of the Row. /// </summary> /// <param name="room">The Room from which to derive the Polygon to place.</param> /// <returns> /// True if the room was successfully placed. /// </returns> private bool AddToRow(Room room, IList <Polygon> among) { var polygon = RoomPerimeter(room); var box = new TopoBox(polygon); var t = new Transform(); var delta = 0.0; if (box.SizeX <= AvailableLength) { t.Rotate(Vector3.ZAxis, angle); delta = box.SizeX; } else if (box.SizeY <= AvailableLength) { t.Rotate(Vector3.ZAxis, angle + 90); delta = box.SizeY; } else { return(false); } polygon = polygon.Transform(t); polygon = polygon.MoveFromTo(new Vector3(), mark); if (among != null && polygon.Intersects(among)) { return(false); } mark = Row.PointAt((mark.DistanceTo(Row.Start) + delta) / Row.Length); room.Perimeter = polygon; Rooms.Add(room); return(true); }
/// <summary> /// Creates an orthogonal 2D grid of Vector3 points from the supplied Polygon and axis intervals. /// </summary> /// <param name="perimeter">The Polygon boundary of the point grid.</param> /// <param name="xInterval">The spacing of the grid along the x-axis.</param> /// <param name="yInterval">The spacing of the grid along the y-axis.</param> /// <returns> /// A new CoordGrid. /// </returns> public CoordGrid(Polygon polygon, double xInterval = 1, double yInterval = 1, int randomSeed = 1) { random = new Random(randomSeed); Allocated = new List <Vector3>(); Available = new List <Vector3>(); Perimeter = new Polygon(polygon.Vertices); var box = new TopoBox(polygon); var x = box.SW.X; var y = box.SW.Y; while (y <= box.NW.Y) { while (x <= box.SE.X) { var point = new Vector3(x, y); if (polygon.Contains(point) || polygon.Touches(point)) { Available.Add(point); } x += xInterval; } x = box.SW.X; y += yInterval; } }
public RoomGroup(Polygon perimeter, string name = "") { Perimeter = new Polygon(perimeter.Vertices); Name = name; Box = new TopoBox(perimeter); Rooms = new List <Room>(); Row = null; }
/// <summary> /// Returns a list of Vector3 points representig the corners of the Polygon's orthogonal bounding box. /// </summary> public static List <Vector3> BoxCorners(this Polygon polygon) { var box = new TopoBox(polygon); return(new List <Vector3> { box.SW, box.SE, box.NE, box.NW }); }
/// <summary> /// Creates a rectilinear Polygon in the specified adjacent quadrant to the supplied Polygon. /// </summary> /// <param name="area">The area of the new Polygon.</param> /// <param name="orient">The relative direction in which the new Polygon will be placed.</param> /// <returns> /// A new Polygon. /// </returns> public static Polygon AdjacentArea(this Polygon polygon, double area, Orient orient) { var box = new TopoBox(polygon); double sizeX = 0.0; double sizeY = 0.0; if (orient == Orient.N || orient == Orient.S) { sizeX = box.SizeX; sizeY = area / box.SizeX; } else { sizeX = area / box.SizeY; sizeY = box.SizeY; } Vector3 origin = null; switch (orient) { case Orient.N: origin = box.NW; break; case Orient.E: origin = box.SE; break; case Orient.S: origin = new Vector3(box.SW.X, box.SW.Y - sizeY); break; case Orient.W: origin = new Vector3(box.SW.X - sizeX, box.SW.Y); break; } return (new Polygon ( new List <Vector3> { origin, new Vector3(origin.X + sizeX, origin.Y), new Vector3(origin.X + sizeX, origin.Y + sizeY), new Vector3(origin.X, origin.Y + sizeY) } )); }
public RoomGroup() { Name = ""; Perimeter = new Polygon ( new List <Vector3> { new Vector3(0.0, 0.0), new Vector3(0.0, 10.0), new Vector3(10.0, 10.0), new Vector3(0.0, 10.0) } ); Box = new TopoBox(Perimeter); Rooms = new List <Room>(); Row = null; }
/// <summary> /// Tests if the supplied Polygon resides in a corner of a Polygon perimeter. /// </summary> /// <param name="polygon">The Polygon to test.</param> /// <param name="perimeter">The Polygon to test against.</param> /// <returns> /// Returns true if exactly three of the polygon bounding box points fall on the Polygon perimeter bounding box. /// </returns> public static bool AtCorner(this Polygon polygon, Polygon perimeter) { var count = 0; var box = new TopoBox(perimeter); var boundary = Shaper.PolygonBox(box.SizeX, box.SizeY).MoveFromTo(Vector3.Origin, box.SW); foreach (Vector3 vertex in BoxCorners(polygon)) { if (boundary.Touches(vertex)) { count++; } } if (count != 3) { return(false); } return(true); }
/// <summary> /// Clears the current Rooms list and creates new Rooms defined by orthogonal x- and y-axis divisions of the RoomGroup Perimeter. /// </summary> /// <param name="xRooms">The quantity of Rooms along orthogonal x-axis. Must be positive.</param> /// <param name="yRooms">The quantity of Rooms along orthogonal y-axis. Must be positive.</param> /// <returns> /// True if the Rooms are created. /// </returns> public bool RoomsByDivision(int xRooms = 1, int yRooms = 1, double height = 3.0, string name = "") { if (Perimeter == null || xRooms < 1 || yRooms < 1 || height <= 0.0) { return(false); } var sizeX = SizeX / xRooms; var sizeY = SizeY / yRooms; var count = xRooms * yRooms; var box = new TopoBox(Perimeter); var newRooms = new List <Room>(); for (int xIdx = 0; xIdx < xRooms; xIdx++) { var xCoord = box.SW.X + (xIdx * sizeX); for (int yIdx = 0; yIdx < yRooms; yIdx++) { var yCoord = box.SW.Y + (yIdx * sizeY); var polygon = Shaper.Rectangle(sizeX, sizeY); polygon = polygon.MoveFromTo(Vector3.Origin, new Vector3(xCoord, yCoord)).Intersection(Perimeter).First(); var room = new Room() { Height = height, Name = name, Perimeter = polygon }; newRooms.Add(room); } } if (newRooms.Count == 0) { return(false); } Rooms.Clear(); Rooms.AddRange(newRooms); return(true); }
/// <summary> /// Attempts to place a Room perimeter on the next open segment of the Row, with optional restrictions of a perimeter within which the Room's perimeter must fit and a list of Polygons which it cannot intersect. /// </summary> /// <param name="room">The Room from which to derive the Polygon to place.</param> /// <param name="within">The optional Polygon perimeter within which a new Room must fit.</param> /// <param name="among">The optional list of Polygon perimeters the new Room cannot intersect.</param> /// <param name="circ">The optional additional allowance opposite the Row to allow for circulation to the Rooms.</param> /// <returns> /// True if the room was successfully placed. /// </returns> public bool AddRoom(Room room, Polygon within = null, IList <Polygon> among = null, double circ = 2.0) { if (room == null) { return(false); } circ = Math.Abs(circ); var polygon = room.MakePerimeter(); var box = new TopoBox(polygon); var delta = 0.0; var newDepth = 0.0; var circDepth = 0.0; var rotation = angle; if (box.SizeX <= AvailableLength) { delta = box.SizeX; newDepth = box.SizeY; circDepth = box.SizeY + circ; } else if (box.SizeY <= AvailableLength) { polygon = polygon.MoveFromTo(box.NW, box.SW); delta = box.SizeY; newDepth = box.SizeX; circDepth = box.SizeX + circ; rotation += 90; } else { return(false); } var t = new Transform(); t.Rotate(Vector3.ZAxis, rotation); var chkCirc = new Polygon( new [] { new Vector3(), new Vector3(delta, 0.0), new Vector3(delta, circDepth), new Vector3(0.0, circDepth) }); chkCirc = t.OfPolygon(chkCirc).MoveFromTo(new Vector3(), mark); if (!chkCirc.Fits(within, among)) { if (Rooms.Count == 0) { mark = Row.PointAt(Math.Abs(mark.DistanceTo(Row.Start) + delta) / Row.Length()); } return(false); } polygon = t.OfPolygon(polygon).MoveFromTo(new Vector3(), mark); if (!polygon.Fits(within, among)) { if (Rooms.Count == 0) { mark = Row.PointAt(Math.Abs(mark.DistanceTo(Row.Start) + delta) / Row.Length()); } return(false); } mark = Row.PointAt(Math.Abs(mark.DistanceTo(Row.Start) + delta) / Row.Length()); if (newDepth > Depth) { Depth = newDepth; } var dpt = Depth + circ; var line1 = new Line(box.SW, new Vector3(0.0, dpt)); line1 = line1.Rotate(box.SW, rotation).MoveFromTo(new Vector3(), Row.Start); var line2 = new Line(box.SW, new Vector3(0.0, dpt)); line2 = line2.Rotate(box.SW, rotation).MoveFromTo(new Vector3(), mark); circulation = new Polygon(new [] { Row.Start, mark, line2.End, line1.End }); room.Perimeter = polygon; Rooms.Add(room); return(true); }