using System; using System.Collections.Generic; using System.Linq; using System.Text; using TransportGame.Business; using TransportGame.Model; using TransportGame.Model.Road; using TransportGame.Utils; namespace TransportGame.Generator { public class BuildingGenerator { private const float LotSquareSize = 1f; private const float LotSpacing = 0.1f; private Map map; QuadTree nodeTree; QuadTree lotTree; private void AllocateLots() { float advance = LotSquareSize + LotSpacing; // Generate lots for every segment foreach (var pair in map.RoadNetwork.ArticulationSegments) { var seg = pair.Value; var dir = seg.Direction; var perp = dir.RotateDeg(90); float width0 = ConfigManager.Roadgen.SidewalkWidth + ConfigManager.Roadgen.LaneWidth * seg.LanesTo1; float width1 = ConfigManager.Roadgen.SidewalkWidth + ConfigManager.Roadgen.LaneWidth * seg.LanesTo2; for (Vector2 pos = seg.Terminal1.Position; (pos - seg.Terminal2.Position).LengthSq > advance * advance; pos += dir * advance) { // Build lot squares Vector2[] left = new Vector2[4]; left[0] = pos + perp * (width0 + LotSpacing + LotSquareSize); left[1] = pos + perp * (width0 + LotSpacing); left[2] = pos + dir * LotSquareSize + perp * (width0 + LotSpacing); left[3] = pos + dir * LotSquareSize + perp * (width0 + LotSpacing + LotSquareSize); Vector2[] right = new Vector2[4]; right[0] = pos - perp * (width0 + LotSpacing + LotSquareSize); right[1] = pos - perp * (width0 + LotSpacing); right[2] = pos + dir * LotSquareSize - perp * (width0 + LotSpacing); right[3] = pos + dir * LotSquareSize - perp * (width0 + LotSpacing + LotSquareSize); BuildingLot lot0 = new BuildingLot(left); BuildingLot lot1 = new BuildingLot(right); // Test for intersections if (CanAllocate(pos, lot0)) lotTree.Add(lot0); if (CanAllocate(pos, lot1)) lotTree.Add(lot1); } } // Done map.BuildingLots = lotTree.ToList(); } private bool CanAllocate(Vector2 pos, BuildingLot lot0) { // Test other lots Rectangle lotArea = new Rectangle(pos.X - 2 * LotSquareSize, pos.Y - 2 * LotSquareSize, pos.X + 2 * LotSquareSize, pos.Y + 2 * LotSquareSize); foreach (var lot in lotTree.Query(lotArea)) { if (BuildingLot.Intersect(lot0, lot)) return false; } // Test nearby roads Rectangle roadArea = new Rectangle( pos.X - 2 * ConfigManager.Roadgen.HighwaySegmentLength, pos.Y - 2 * ConfigManager.Roadgen.HighwaySegmentLength, pos.X + 2 * ConfigManager.Roadgen.HighwaySegmentLength, pos.Y + 2 * ConfigManager.Roadgen.HighwaySegmentLength); foreach (var node in nodeTree.Query(roadArea)) { foreach (var segment in node.ArticulationSegments) { if (BuildingLot.Intersect(lot0, segment.AsLineSegment())) return false; } } return true; } private void GenerateBuildings() { } public void Generate(Map map) { this.map = map; // Construct node tree nodeTree = new QuadTree(0, 0, map.Width, map.Height); foreach (var pair in map.RoadNetwork.Nodes) nodeTree.Add(pair.Value); lotTree = new QuadTree(0, 0, map.Width, map.Height); // Allocate lots AllocateLots(); GenerateBuildings(); } } }