XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Rendering;
using XFEExtension.NetCore.XUnit.Attributes;

namespace XFEEDToolBox.Test;

[TestFixture]
public sealed class LocalSystemSceneTests
{
    private static SystemLocation Body(int key,Vector3d? position,SystemLocationCategory category=SystemLocationCategory.Planet)
        =>new(key,(ulong)key,"Body "+key,"",3,category,null,position,null,false,"identity-"+key);
    private static CurrentSystemSnapshot Snapshot(params SystemLocation[] rows)=>new(1,"Actual coordinates",1,1,DateTimeOffset.UtcNow,rows);
    [Test]public void PerspectiveHasIndependentKnownAxisDirectionsAndDepthScaling()
    {
        var camera=new LocalSystemCamera(0,0,10,new(0,0,0));
        var centre=camera.Project(new(0,0,0),1000,600)!.Value;
        var right=camera.Project(new(1,0,0),1000,600)!.Value;
        var above=camera.Project(new(0,1,0),1000,600)!.Value;
        var nearer=camera.Project(new(1,0,5),1000,600)!.Value;
        Check.Equal(500d,centre.X);Check.Equal(300d,centre.Y);Check.That(right.X>centre.X&&above.Y<centre.Y);
        Check.That(Math.Abs((nearer.X-centre.X)-2*(right.X-centre.X))<1e-9);
    }
    [Test]public void UnmeasuredLocationsAreNotInventedAndRemainCounted()
    {
        var scene=new LocalSystemScene(Snapshot(Body(1,new(0,0,0),SystemLocationCategory.Star),Body(2,null),Body(3,new(double.NaN,0,0))));
        Check.Equal(1,scene.Nodes.Count);Check.Equal(2,scene.UnpositionedCount);
    }
    [Test]public void LogDisplayPreservesDirectionAndRadialOrderAcrossLargeDistances()
    {
        var scene=new LocalSystemScene(Snapshot(Body(1,new(0,0,0),SystemLocationCategory.Star),Body(2,new(1e10,0,1e10)),Body(3,new(1e14,0,1e14))));
        Check.That(scene.Nodes[1].Position.Length<scene.Nodes[2].Position.Length);
        Check.That(Math.Abs(scene.Nodes[1].Position.X-scene.Nodes[1].Position.Z)<1e-12);
        Check.That(Math.Abs(scene.Nodes[2].Position.Length-4.4)<1e-9);
    }
    [Test]public void FilteringDoesNotChangeTheProjectionOfRemainingPhysicalCoordinates()
    {
        var snapshot=Snapshot(Body(1,new(0,0,0),SystemLocationCategory.Star),Body(2,new(1e10,3e9,0)),Body(3,new(1e14,0,0)));
        var full=new LocalSystemScene(snapshot);var filtered=new LocalSystemScene(snapshot,[snapshot.Locations[1]]);
        Check.Equal(full.Nodes[1].Position,filtered.Nodes[0].Position);
    }
    [Test]public void FocusAndRotationAreRealCameraOperations()
    {
        var camera=LocalSystemCamera.Overview;var point=new Vector3d(2,.3,1);
        var focused=camera.Focus(point).Project(point,1000,600)!.Value;
        Check.Equal(500d,focused.X);Check.Equal(300d,focused.Y);
        var before=camera.Project(point,1000,600)!.Value;var after=camera.Rotate(100,35).Project(point,1000,600)!.Value;
        Check.That(Math.Abs(before.X-after.X)>1&&Math.Abs(before.Y-after.Y)>1);
    }
    [Test]public void HitTestingUsesDrawDepthAndOriginalDestinationIdentity()
    {
        var first=Body(1,new(0,0,0));var second=Body(2,new(0,0,3));
        var near=new LocalSystemProjection(new(second,new(0,0,3)),200,100,3,20,new(0,0,1),false);
        var far=new LocalSystemProjection(new(first,new(0,0,0)),200,100,8,40,new(0,0,1),false);
        var hit=LocalSystemScene.HitTest([far,near],200,100);Check.Equal("identity-2",hit[0].Node.Location.Identity);
        Check.Equal(0,LocalSystemScene.HitTest([far,near],500,500).Count);
    }
    [Test]public void BehindCameraIsNotSelectableAndZoomRemainsBounded()
    {
        var camera=new LocalSystemCamera(0,0,1,new(0,0,0));
        Check.That(camera.Project(new(0,0,2),1000,600) is null);
        Check.Equal(.5,camera.Zoom(10000).Distance);Check.Equal(35d,camera.Zoom(-10000).Distance);
    }
    [Test]public void NonFiniteCameraAndOverflowingCoordinatesDoNotReachTheRenderer()
    {
        var camera=LocalSystemCamera.Overview;
        Check.That((camera with{Yaw=double.NaN}).Project(new(0,0,0),1000,600) is null);
        Check.That(camera.Project(new(0,0,0),double.PositiveInfinity,600) is null);
        var scene=new LocalSystemScene(Snapshot(Body(1,new(0,0,0),SystemLocationCategory.Star),Body(2,new(1e300,1e300,0))));
        Check.Equal(1,scene.Nodes.Count);Check.Equal(1,scene.UnpositionedCount);Check.That(double.IsFinite(scene.ExtentMetres));
    }
    [Test]public void CoincidentSignalsDoNotRequireAnInventedNonzeroLightingDirection()
    {
        var scene=new LocalSystemScene(Snapshot(Body(1,new(0,0,0),SystemLocationCategory.Star),Body(2,new(0,0,0),SystemLocationCategory.Signal)));
        var projected=scene.Project(LocalSystemCamera.Overview,1000,600,null);
        Check.Equal(2,projected.Count);Check.That(projected.All(point=>point.Light.Finite&&point.Light.Length>0));
    }
    [Test]public void OverviewKeepsTheWholeCatalogueInsideTheViewportWithSymbolMargins()
    {
        // Independently sample the full display sphere rather than one favourable system.
        foreach(var size in new[]{(W:300d,H:500d),(W:750d,H:310d),(W:600d,H:600d),(W:400d,H:140d)})
        for(var latitude=-90;latitude<=90;latitude+=10)
        for(var longitude=0;longitude<360;longitude+=10)
        {
            var a=latitude*Math.PI/180;var b=longitude*Math.PI/180;
            var point=new Vector3d(4.4*Math.Cos(a)*Math.Cos(b),4.4*Math.Sin(a),4.4*Math.Cos(a)*Math.Sin(b));
            var at=LocalSystemCamera.OverviewFor(size.W,size.H).Project(point,size.W,size.H)!.Value;
            var starMargin=36*7/at.Depth*1.8;
            Check.That(at.X-starMargin>=0&&at.X+starMargin<=size.W&&at.Y-starMargin>=0&&at.Y+starMargin<=size.H);
        }
    }
}