city-generation/Game/Assets/Scripts/Generator/BuildingGenerator.cs

119 lines
4.2 KiB
C#
Raw Normal View History

2015-06-03 20:54:22 +00:00
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<RoadNode> nodeTree;
QuadTree<BuildingLot> 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<RoadNode>(0, 0, map.Width, map.Height);
foreach (var pair in map.RoadNetwork.Nodes)
nodeTree.Add(pair.Value);
lotTree = new QuadTree<BuildingLot>(0, 0, map.Width, map.Height);
// Allocate lots
AllocateLots();
GenerateBuildings();
}
}
}