Skip to content

Commit

Permalink
Bins
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrabbers committed Jun 13, 2024
1 parent b81bd94 commit 103322b
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 168 deletions.
115 changes: 0 additions & 115 deletions .editorconfig

This file was deleted.

10 changes: 10 additions & 0 deletions BnbnavNetClient/Models/IntRect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace BnbnavNetClient.Models;

public readonly record struct IntRect(int Left, int Top, int Right, int Bottom)
{
public bool Contains(int x, int y) =>
Left <= x && x <= Right && Top <= y && y <= Bottom;

public IntRect Expand(int amt) =>
new(Left - amt, Top - amt, Right + amt, Bottom + amt);
}
102 changes: 102 additions & 0 deletions BnbnavNetClient/Models/MapBin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using Avalonia;
using DynamicData;

namespace BnbnavNetClient.Models;

public sealed class MapBins
{
public class Bin
{
public List<Node> Nodes { get; } = [];
public List<Edge> Edges { get; } = [];
}
public const int BinSideLength = 256;

private readonly Bin?[,] _bins;

private int BinsXLength => _bins.GetLength(0);
private int BinsYLength => _bins.GetLength(1);

public IntRect Bounds { get; private set; }

public MapBins(IntRect bounds, IEnumerable<Node> nodes, IEnumerable<Edge> edges)
{
Bounds = bounds.Expand(5);
var xLength = Bounds.Right - Bounds.Left;
var yLength = Bounds.Bottom - Bounds.Top;
var xNumBins = xLength / BinSideLength;
var yNumBins = yLength / BinSideLength;
_bins = new Bin?[xNumBins + 1, yNumBins + 1];

foreach (var node in nodes)
{
InsertNode(node);
}

foreach (var edge in edges)
{
Insert(edge);
}
}

public void InsertNode(Node node)
{
if (!Bounds.Contains(node.X, node.Z))
throw new NotImplementedException();

var x = node.X - Bounds.Left;
var y = node.Z - Bounds.Top;
var binX = x / BinSideLength;
var binY = y / BinSideLength;

ref var bin = ref _bins[binX, binY];
bin ??= new Bin();
bin.Nodes.Add(node);
}

public void Insert(Edge edge)
{
var minX = int.Min(edge.From.X, edge.To.X);
var minY = int.Min(edge.From.Z, edge.To.Z);
var maxX = int.Max(edge.From.X, edge.To.X);
var maxY = int.Max(edge.From.Z, edge.To.Z);
var edgeBounds = new IntRect(minX, minY, maxX, maxY);
var expandedBounds = edgeBounds.Expand(5);
var startX = (expandedBounds.Left - Bounds.Left) / BinSideLength;
var startY = (expandedBounds.Top - Bounds.Top) / BinSideLength;
var endX = (expandedBounds.Right - Bounds.Left) / BinSideLength;
var endY = (expandedBounds.Top - Bounds.Top) / BinSideLength;

for (var i = startX; i <= endX; i++)
{
for (var j = startY; j <= endY; j++)
{
ref var bin = ref _bins[i, j];
bin ??= new Bin();
bin.Edges.Add(edge);
}
}
}

public void Query(IntRect rect, ref List<Node> nodes, ref List<Edge> edges)
{
var startX = (rect.Left - Bounds.Left - BinSideLength / 2) / BinSideLength;
var startY = (rect.Top - Bounds.Top - BinSideLength / 2) / BinSideLength;
var endX = (rect.Right - Bounds.Left + BinSideLength / 2) / BinSideLength;
var endY = (rect.Bottom - Bounds.Top + BinSideLength / 2) / BinSideLength;

for (var i = startX; i <= endX; i++)
{
for (var j = startY; j <= endY; j++)
{
ref var bin = ref _bins[i, j];
if (bin is null)
continue;
foreach (var node in bin.Nodes)
nodes.Add(node);
foreach (var edge in bin.Edges)
edges.Add(edge);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ public override void Render(MapView mapView, DrawingContext context)
}
var nodeBorder = (Pen)mapView.ThemeDict["NodeBorder"]!;
var selNodeBrush = (Brush)mapView.ThemeDict["SelectedNodeFill"]!;
foreach (var (rect, _) in mapView.DrawnNodes.Where(x => ghosts.Contains(x.Item2)))
foreach (var node in mapView.DrawnNodes.Where(x => ghosts.Contains(x)))
{
var rect = node.BoundingRect(mapView);
context.DrawRectangle(selNodeBrush, nodeBorder, rect);
}
}
Expand Down
29 changes: 20 additions & 9 deletions BnbnavNetClient/Services/MapService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ public enum RouteOptions
public ReadOnlyDictionary<string, Player> Players { get; }
public bool PlayerGone { get; set; }

public MapBins MapBins { get; }

[Reactive]
public AvaloniaList<string> Worlds { get; private set; } = [];

Expand Down Expand Up @@ -108,7 +110,7 @@ public static string? AuthenticationToken
}
}

MapService(IEnumerable<Node> nodes, IEnumerable<Edge> edges, IEnumerable<Road> roads, IEnumerable<Landmark> landmarks, IEnumerable<Annotation> annotations, BnbnavWebsocketService websocketService)
MapService(IEnumerable<Node> nodes, IEnumerable<Edge> edges, IEnumerable<Road> roads, IEnumerable<Landmark> landmarks, IEnumerable<Annotation> annotations, BnbnavWebsocketService websocketService, MapBins bins)
{

_nodes = new Dictionary<string, Node>(nodes.ToDictionary(n => n.Id));
Expand All @@ -125,6 +127,7 @@ public static string? AuthenticationToken
_websocketService = websocketService;
_i18N = Locator.Current.GetI18Next();

MapBins = bins;

this.WhenAnyValue(x => x.LoggedInUsername).Subscribe(Observer.Create<string?>(_ => UpdateLoggedInPlayer()));
this.WhenPropertyChanged(x => x.Players)
Expand Down Expand Up @@ -423,17 +426,18 @@ IEnumerable<Edge> GenerateTemporaryEdgesFromPointToEdge(Node point, Edge edge, b

public static async Task<MapService> DownloadInitialMapAsync()
{
var content = await HttpClient.GetStringAsync("/api/data");
using var jsonDom = JsonDocument.Parse(content);

if (jsonDom is null)
throw new InvalidOperationException("Error in JSON document.");
var stream = await HttpClient.GetStreamAsync("/api/data");
using var jsonDom = await JsonDocument.ParseAsync(stream);

//TODO: Gracefully fail if there is no such property - this might be a new server w/o landmarks, nodes, etc.

var root = jsonDom.RootElement;
var jsonNodes = root.GetProperty("nodes"u8);
var nodes = new Dictionary<string, Node>();
var minX = int.MaxValue;
var minY = int.MaxValue;
var maxX = int.MinValue;
var maxY = int.MinValue;
foreach (var jsonNode in jsonNodes.EnumerateObject())
{
var id = jsonNode.Name;
Expand All @@ -443,6 +447,10 @@ public static async Task<MapService> DownloadInitialMapAsync()
var z = obj.GetProperty("z"u8).GetInt32();
var world = obj.GetProperty("world"u8).GetString()!;
nodes.Add(id, new Node(id, x, y, z, world));
minX = int.Min(minX, x);
minY = int.Min(minY, z);
maxX = int.Max(maxX, x);
maxY = int.Max(maxY, z);
}

var jsonLandmarks = root.GetProperty("landmarks"u8);
Expand Down Expand Up @@ -488,10 +496,13 @@ public static async Task<MapService> DownloadInitialMapAsync()
var obj = jsonAnnotation.Value;
annotations.Add(new Annotation(id, obj.Clone()));
}


var bounds = new IntRect(minX, minY, maxX, maxY);
var bins = new MapBins(bounds, nodes.Values, edges);

var ws = new BnbnavWebsocketService();
await ws.ConnectAsync(CancellationToken.None);
var service = new MapService(nodes.Values, edges, roads.Values, landmarks, annotations, ws);
var service = new MapService(nodes.Values, edges, roads.Values, landmarks, annotations, ws, bins);
_ = service.ProcessChangesAsync();
service.SetupWorlds();
return service;
Expand Down
16 changes: 7 additions & 9 deletions BnbnavNetClient/Views/MainView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,14 @@ public async void ViewLoaded(object sender, RoutedEventArgs e)
vm.RaisePropertyChanged(nameof(MainViewModel.PanText));

// c.f. issue #32 for why we disable the blur effect on windows
if (!OperatingSystem.IsWindows())
vm.WhenAnyValue<MainViewModel, ViewModel?>(x => x.Popup).Subscribe(p =>
{
vm.WhenAnyValue<MainViewModel, ViewModel?>(x => x.Popup).Subscribe(p =>
{
if (p is null)
MainUiGrid.Classes.Clear();
else
MainUiGrid.Classes.Add("blur");
});
}
if (p is null)
MainUiGrid.Classes.Clear();
else
MainUiGrid.Classes.Add("blur");
});

}

public async void ColorModeSwitch(object? _, RoutedEventArgs? __)
Expand Down
Loading

0 comments on commit 103322b

Please sign in to comment.