Update README with project details and setup instructions; add data directories to .gitignore
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
using System.Numerics;
|
||||
using TheLivingWorld.Core.Geo;
|
||||
using TheLivingWorld.Core.Worlds;
|
||||
|
||||
namespace TheLivingWorld.Tests;
|
||||
|
||||
public class LocalProjectionTests
|
||||
{
|
||||
// Robert Lee, Texas - the town the first worlds were generated around.
|
||||
private static readonly GeoPoint Origin = new(31.8966010, -100.4858591);
|
||||
|
||||
[Fact]
|
||||
public void Origin_projects_to_world_zero()
|
||||
{
|
||||
var projection = new LocalProjection(Origin);
|
||||
|
||||
var projected = projection.Project(Origin);
|
||||
|
||||
Assert.Equal(0f, projected.X, 3);
|
||||
Assert.Equal(0f, projected.Y, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void One_kilometre_north_lands_one_kilometre_up()
|
||||
{
|
||||
var projection = new LocalProjection(Origin);
|
||||
var north = new GeoPoint(Origin.Latitude + 1000.0 / LocalProjection.MetersPerDegreeLatitude, Origin.Longitude);
|
||||
|
||||
var projected = projection.Project(north);
|
||||
|
||||
Assert.Equal(0f, projected.X, 2);
|
||||
Assert.Equal(1000f, projected.Y, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Unproject_reverses_project()
|
||||
{
|
||||
var projection = new LocalProjection(Origin);
|
||||
var point = new Vector2(-4321.5f, 6789.25f);
|
||||
|
||||
var roundTripped = projection.Project(projection.Unproject(point));
|
||||
|
||||
Assert.Equal(point.X, roundTripped.X, 1);
|
||||
Assert.Equal(point.Y, roundTripped.Y, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rejects_coordinates_outside_the_globe()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new LocalProjection(new GeoPoint(91, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
public class GeoBoundsTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(31.8966010, -100.4858591, 10_000)]
|
||||
[InlineData(60.0, 30.3, 20_000)]
|
||||
[InlineData(-33.87, 151.21, 5_000)]
|
||||
public void FromCenter_produces_a_square_of_the_requested_size(double lat, double lon, double sizeMeters)
|
||||
{
|
||||
var center = new GeoPoint(lat, lon);
|
||||
var bounds = GeoBounds.FromCenter(center, sizeMeters);
|
||||
var projection = new LocalProjection(center);
|
||||
|
||||
var southWest = projection.Project(bounds.South, bounds.West);
|
||||
var northEast = projection.Project(bounds.North, bounds.East);
|
||||
|
||||
// Half a metre of slack over a 20 km span is the float rounding in the projection.
|
||||
Assert.Equal(sizeMeters, northEast.X - southWest.X, 0.5);
|
||||
Assert.Equal(sizeMeters, northEast.Y - southWest.Y, 0.5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Overpass_bbox_is_south_west_north_east()
|
||||
{
|
||||
var bounds = new GeoBounds(South: 1, West: 2, North: 3, East: 4);
|
||||
|
||||
Assert.Equal("1.0000000,2.0000000,3.0000000,4.0000000", bounds.ToOverpassBbox());
|
||||
}
|
||||
}
|
||||
|
||||
public class ChunkGridTests
|
||||
{
|
||||
[Fact]
|
||||
public void Covers_the_whole_world_square()
|
||||
{
|
||||
var grid = new ChunkGrid(worldSizeMeters: 2048, chunkSizeMeters: 512);
|
||||
|
||||
Assert.Equal(4, grid.CountX);
|
||||
Assert.Equal(4, grid.CountY);
|
||||
Assert.Equal(-1024f, grid.MinX);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rounds_the_count_up_when_the_size_does_not_divide_evenly()
|
||||
{
|
||||
var grid = new ChunkGrid(worldSizeMeters: 10_000, chunkSizeMeters: 512);
|
||||
|
||||
Assert.Equal(20, grid.CountX);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Maps_points_to_the_chunk_containing_them()
|
||||
{
|
||||
var grid = new ChunkGrid(worldSizeMeters: 2048, chunkSizeMeters: 512);
|
||||
|
||||
Assert.Equal(new ChunkCoord(0, 0), grid.CoordOf(new Vector2(-1024, -1024)));
|
||||
Assert.Equal(new ChunkCoord(2, 2), grid.CoordOf(new Vector2(1, 1)));
|
||||
Assert.Equal(new ChunkCoord(3, 3), grid.CoordOf(new Vector2(1023, 1023)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clamps_points_that_fall_outside_the_world()
|
||||
{
|
||||
var grid = new ChunkGrid(worldSizeMeters: 2048, chunkSizeMeters: 512);
|
||||
|
||||
Assert.Equal(new ChunkCoord(0, 0), grid.CoordOf(new Vector2(-99_999, -99_999)));
|
||||
Assert.Equal(new ChunkCoord(3, 3), grid.CoordOf(new Vector2(99_999, 99_999)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Chunk_bounds_line_up_with_the_grid()
|
||||
{
|
||||
var grid = new ChunkGrid(worldSizeMeters: 2048, chunkSizeMeters: 512);
|
||||
|
||||
var bounds = grid.BoundsOf(new ChunkCoord(1, 2));
|
||||
|
||||
Assert.Equal(-512f, bounds.MinX);
|
||||
Assert.Equal(0f, bounds.MinY);
|
||||
Assert.Equal(0f, bounds.MaxX);
|
||||
Assert.Equal(512f, bounds.MaxY);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user