119 lines
4.2 KiB
C#
119 lines
4.2 KiB
C#
|
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();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|