using XFEEDToolBox.Core.Navigation; namespace XFEEDToolBox.Core.Rendering; public sealed record LocalSystemMarkerGroup(LocalSystemProjection Anchor,IReadOnlyList Members); /// Declutters only destination markers. No physical model or orbital point is moved. public static class LocalSystemMarkerLayout { public static bool Celestial(SystemLocation location)=>location.Category is SystemLocationCategory.Star or SystemLocationCategory.Planet or SystemLocationCategory.LandablePlanet; public static IReadOnlyList Build(IReadOnlyList all,IReadOnlyList visible) { var groups=new List<(LocalSystemProjection Anchor,List Members)>(); var bodies=all.Where(point=>Celestial(point.Node.Location)).OrderByDescending(point=>point.Radius).ToArray(); foreach(var point in visible.Where(point=>!Celestial(point.Node.Location)).OrderByDescending(point=>point.Selected).ThenBy(point=>point.Depth)) { var x=point.X;var y=point.Y; foreach(var body in bodies) { var dx=x-body.X;var dy=y-body.Y;var distance=Math.Sqrt(dx*dx+dy*dy);var radius=body.Radius+20; if(distance>=radius)continue; if(distance<1){var angle=point.Node.Location.Key*2.399963229728653;dx=Math.Cos(angle);dy=Math.Sin(angle);distance=1;} x=body.X+dx/distance*radius;y=body.Y+dy/distance*radius; } var anchor=point with{X=x,Y=y,Radius=12}; var index=groups.FindIndex(group=>Math.Pow(group.Anchor.X-x,2)+Math.Pow(group.Anchor.Y-y,2)<30*30); if(index<0)groups.Add((anchor,[point]));else groups[index].Members.Add(point); } return groups.Select(group=>new LocalSystemMarkerGroup(group.Anchor,group.Members)).ToArray(); } }