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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
namespace XFEEDToolBox.Core.Navigation;

public static class SurfaceApproachGeometry
{
    public static double SurfaceRange(Vector3d ship,Vector3d site,Vector3d centre,double radius)
        =>Math.Acos(Math.Clamp(Vector3d.Dot((ship-centre).Unit(),(site-centre).Unit()),-1,1))*radius;
    public static Vector3d EntryPoint(PlanetApproachFrame planet,Vector3d ship)
    {
        var limits=planet.Limits;if(!limits.Valid)throw new ArgumentException("行星进近参数未校验。");
        var site=(planet.SurfaceDestination-planet.Centre).Unit();var radial=(ship-planet.Centre).Unit();
        var toward=radial-site*Vector3d.Dot(radial,site);
        if(toward.Length<1e-6)toward=FlightGeometry.Perpendicular(site,planet.North);
        var range=(limits.GlideEntryAltitude-limits.GlideExitAltitude)/Math.Tan(limits.PreferredGlideAngleDegrees*Math.PI/180);
        var arc=Math.Clamp(range/limits.Radius,0,Math.PI/3);
        return planet.Centre+(site*Math.Cos(arc)+toward.Unit()*Math.Sin(arc))*(limits.Radius+limits.GlideEntryAltitude*1.08);
    }
    public static Vector3d ShallowApproach(PlanetApproachFrame planet,Vector3d ship,Vector3d forward)
    {
        var radial=(ship-planet.Centre).Unit();var toward=planet.SurfaceDestination-ship;
        var tangent=toward-radial*Vector3d.Dot(toward,radial);
        if(tangent.Length<1)tangent=FlightGeometry.Perpendicular(radial,forward);
        return (tangent.Unit()-radial*Math.Tan(planet.Limits.PreferredGlideAngleDegrees*Math.PI/180)).Unit();
    }
    public static Vector3d LevelDirection(PlanetApproachFrame planet,Vector3d ship,Vector3d forward)
    {
        var up=(ship-planet.Centre).Unit();var toward=planet.SurfaceDestination-ship;
        var tangent=toward-up*Vector3d.Dot(toward,up);
        return tangent.Length>1?tangent.Unit():FlightGeometry.Perpendicular(up,forward);
    }
    public static bool IntersectsPlanet(Vector3d from,Vector3d to,Vector3d centre,double radius)
    {
        var delta=to-from;var lengthSquared=Vector3d.Dot(delta,delta);
        if(lengthSquared<1)return (from-centre).Length<radius;
        var t=Math.Clamp(Vector3d.Dot(centre-from,delta)/lengthSquared,0,1);
        return (from+delta*t-centre).Length<radius;
    }
}