Added lot allocation.

This commit is contained in:
2015-06-03 23:54:22 +03:00
parent f9b20b0226
commit 352f212ae9
28 changed files with 488 additions and 65 deletions

View File

@ -0,0 +1,118 @@
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();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 387d471e5e9dff54b9cb832e01b969ec
timeCreated: 1433340433
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TransportGame.Business;
using TransportGame.Model;
using TransportGame.Model.Road;
using TransportGame.Utils;
@ -50,21 +51,21 @@ namespace TransportGame.Generator
System.Random random = new System.Random();
Map map;
const float HighwaySegmentLength = 60;
const float DefaultBranchPopulationTreshold = 0.12f;
const float DefaultBranchProbability = 0.2f;
const float DefaultSegmentLength = 24;
const float SteepnessLimit = 10;
const float SlopeLimit = (float)Math.PI / 7;
const float RoadSegmentAngleLimit = (float)Math.PI / 4;
const float RoadSnapDistance = 19;
const float MinNodeDistance = 12;
const int MaximumRandomStraightAngle = 45; // in degrees
const int MaximumBranchAngleVariation = 12; // in degrees
const float HighwayBranchPopulationTreshold = .4f; // 0..1
const float HighwayBranchProbability = .01f;
const int HighwayBranchDelay = 3;
const int MaximumIntersectingRoads = 5;
private float HighwaySegmentLength { get { return ConfigManager.Roadgen.HighwaySegmentLength; } }
private float DefaultBranchPopulationTreshold { get { return ConfigManager.Roadgen.DefaultBranchPopulationTreshold; } }
private float DefaultBranchProbability { get { return ConfigManager.Roadgen.DefaultBranchProbability; } }
private float DefaultSegmentLength { get { return ConfigManager.Roadgen.DefaultSegmentLength; } }
private float SteepnessLimit { get { return ConfigManager.Roadgen.SteepnessLimit; } }
private float SlopeLimit { get { return ConfigManager.Roadgen.SlopeLimit; } }
private float RoadSegmentAngleLimit { get { return ConfigManager.Roadgen.RoadSegmentAngleLimit; } }
private float RoadSnapDistance { get { return ConfigManager.Roadgen.RoadSnapDistance; } }
private float MinNodeDistance { get { return ConfigManager.Roadgen.MinNodeDistance; } }
private int MaximumRandomStraightAngle { get { return ConfigManager.Roadgen.MaximumRandomStraightAngle; } }
private int MaximumBranchAngleVariation { get { return ConfigManager.Roadgen.MaximumBranchAngleVariation; } }
private float HighwayBranchPopulationTreshold { get { return ConfigManager.Roadgen.HighwayBranchPopulationTreshold; } }
private float HighwayBranchProbability { get { return ConfigManager.Roadgen.HighwayBranchProbability; } }
private int HighwayBranchDelay { get { return ConfigManager.Roadgen.HighwayBranchDelay; } }
private int MaximumIntersectingRoads { get { return ConfigManager.Roadgen.MaximumIntersectingRoads; } }
public RoadGenerator()
{
@ -258,7 +259,7 @@ namespace TransportGame.Generator
}
// Filter & sort the segments by distance
segmentIds = segmentIds.Distinct().OrderBy(id =>
segmentIds = segmentIds.Distinct().OrderBy(id =>
LineSegment.Distance(map.RoadNetwork.ArticulationSegments[id].AsLineSegment(), segment.Terminal2Pos));
foreach (var segmentId in segmentIds)

View File

@ -26,12 +26,12 @@ namespace TransportGame.Generator
{
Noise = new PerlinNoiseGenerator();
if (ConfigurationManager.TerrGenConfig == null)
if (ConfigManager.Tergen == null)
throw new Exception("Not initialized!");
Noise.Octaves = ConfigurationManager.TerrGenConfig.NoiseOctaves;
Noise.NonLinearPower = ConfigurationManager.TerrGenConfig.NoiseNonLinearPower;
Noise.Scale = ConfigurationManager.TerrGenConfig.ElevationScale;
Noise.Octaves = ConfigManager.Tergen.NoiseOctaves;
Noise.NonLinearPower = ConfigManager.Tergen.NoiseNonLinearPower;
Noise.Scale = ConfigManager.Tergen.ElevationScale;
}
public Map Generate(int width, int height)
@ -48,7 +48,7 @@ namespace TransportGame.Generator
// Generate water level
float waterAmount = random.NextSingle(map.Biome.Moisture.Minimum, map.Biome.Moisture.Maximum);
map.WaterLevel = Mathf.Pow(waterAmount, ConfigurationManager.TerrGenConfig.WaterNonLinearPower) * map.Biome.Height;
map.WaterLevel = Mathf.Pow(waterAmount, ConfigManager.Tergen.WaterNonLinearPower) * map.Biome.Height;
return map;
}