using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Galaxy;
public sealed record GalaxyQueryBounds(Coordinates Minimum,Coordinates Maximum)
{
public bool Contains(Coordinates p)=>p.X>=Minimum.X&&p.X<=Maximum.X&&p.Y>=Minimum.Y&&p.Y<=Maximum.Y&&p.Z>=Minimum.Z&&p.Z<=Maximum.Z;
public static GalaxyQueryBounds FromViewport(GalaxyViewport viewport)
{
var points=new List<Coordinates>();
if(viewport.Camera is {} camera)
{
foreach(var depth in new[]{camera.Near,camera.QueryFar})foreach(var sx in new[]{-1,1})foreach(var sy in new[]{-1,1})
{
var delta=camera.Forward*depth+camera.Right*(sx*depth*camera.Width/(2*camera.FocalLength))+camera.Up*(sy*depth*camera.Height/(2*camera.FocalLength));
points.Add(new(camera.Eye.X+delta.X,camera.Eye.Y+delta.Y,camera.Eye.Z+delta.Z));
}
}
else foreach(var sx in new[]{-1,1})foreach(var sy in new[]{-1,1})foreach(var sz in new[]{-1,1})
{
var d=viewport.Right*(sx*viewport.HalfWidth)+viewport.Up*(sy*viewport.HalfHeight)+viewport.Depth*(sz*viewport.HalfDepth);
points.Add(new(viewport.Focus.X+d.X,viewport.Focus.Y+d.Y,viewport.Focus.Z+d.Z));
}
return new(new(points.Min(p=>p.X),points.Min(p=>p.Y),points.Min(p=>p.Z)),new(points.Max(p=>p.X),points.Max(p=>p.Y),points.Max(p=>p.Z)));
}
public GalaxyQueryBounds Child(int index)
{
var mid=new Coordinates((Minimum.X+Maximum.X)/2,(Minimum.Y+Maximum.Y)/2,(Minimum.Z+Maximum.Z)/2);
return new(new((index&1)==0?Minimum.X:mid.X,(index&2)==0?Minimum.Y:mid.Y,(index&4)==0?Minimum.Z:mid.Z),new((index&1)==0?mid.X:Maximum.X,(index&2)==0?mid.Y:Maximum.Y,(index&4)==0?mid.Z:Maximum.Z));
}
public Coordinates Centre=>new((Minimum.X+Maximum.X)/2,(Minimum.Y+Maximum.Y)/2,(Minimum.Z+Maximum.Z)/2);
public double Radius=>Minimum.DistanceTo(Maximum)/2;
}
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Galaxy;
public sealed record GalaxyQueryBounds(Coordinates Minimum,Coordinates Maximum)
{
public bool Contains(Coordinates p)=>p.X>=Minimum.X&&p.X<=Maximum.X&&p.Y>=Minimum.Y&&p.Y<=Maximum.Y&&p.Z>=Minimum.Z&&p.Z<=Maximum.Z;
public static GalaxyQueryBounds FromViewport(GalaxyViewport viewport)
{
var points=new List<Coordinates>();
if(viewport.Camera is {} camera)
{
foreach(var depth in new[]{camera.Near,camera.QueryFar})foreach(var sx in new[]{-1,1})foreach(var sy in new[]{-1,1})
{
var delta=camera.Forward*depth+camera.Right*(sx*depth*camera.Width/(2*camera.FocalLength))+camera.Up*(sy*depth*camera.Height/(2*camera.FocalLength));
points.Add(new(camera.Eye.X+delta.X,camera.Eye.Y+delta.Y,camera.Eye.Z+delta.Z));
}
}
else foreach(var sx in new[]{-1,1})foreach(var sy in new[]{-1,1})foreach(var sz in new[]{-1,1})
{
var d=viewport.Right*(sx*viewport.HalfWidth)+viewport.Up*(sy*viewport.HalfHeight)+viewport.Depth*(sz*viewport.HalfDepth);
points.Add(new(viewport.Focus.X+d.X,viewport.Focus.Y+d.Y,viewport.Focus.Z+d.Z));
}
return new(new(points.Min(p=>p.X),points.Min(p=>p.Y),points.Min(p=>p.Z)),new(points.Max(p=>p.X),points.Max(p=>p.Y),points.Max(p=>p.Z)));
}
public GalaxyQueryBounds Child(int index)
{
var mid=new Coordinates((Minimum.X+Maximum.X)/2,(Minimum.Y+Maximum.Y)/2,(Minimum.Z+Maximum.Z)/2);
return new(new((index&1)==0?Minimum.X:mid.X,(index&2)==0?Minimum.Y:mid.Y,(index&4)==0?Minimum.Z:mid.Z),new((index&1)==0?mid.X:Maximum.X,(index&2)==0?mid.Y:Maximum.Y,(index&4)==0?mid.Z:Maximum.Z));
}
public Coordinates Centre=>new((Minimum.X+Maximum.X)/2,(Minimum.Y+Maximum.Y)/2,(Minimum.Z+Maximum.Z)/2);
public double Radius=>Minimum.DistanceTo(Maximum)/2;
}