Skip to content
Snippets Groups Projects
Commit 87698add authored by Paul-Winpenny's avatar Paul-Winpenny
Browse files

Updated to use the image (lidar method)

parent f905cd1a
Branches
No related tags found
No related merge requests found
......@@ -209,7 +209,7 @@ namespace RobobinApp.Networking
public async Task SendCallMeRequest(string endPoint)
{
Debug.WriteLine("Call me request");
await SendMessageAsync("CALLME " + endPoint);
await SendMessageAsync("CALLMELIDAR " + endPoint);
}
public async Task SendPingMessage()
......
App/RobobinApp/Resources/Images/lab_map.jpg

44.7 KiB

......@@ -48,11 +48,21 @@
<AndroidResource Remove="Platforms\Android\Resources\mipmap\robobinlogo1.png" />
</ItemGroup>
<ItemGroup>
<MauiImage Remove="Resources\Images\lab_map.jpg" />
</ItemGroup>
<ItemGroup>
<None Remove="Platforms\Android\Resources\drawable\bin.svg" />
<None Remove="Platforms\Android\Resources\mipmap\robobinlogo1.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Images\lab_map.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.91" />
......
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Microsoft.Extensions.Logging;
......@@ -58,15 +59,26 @@ namespace RobobinApp.ViewModels
ToggleModeCommand = new Command(async () => await OnToggleMode());
GetNewGraphCommand = new Command(async () => await GetNewGraph());
var graphNodes1 = new List<Node>
{
new Node("No graph loaded", 50, 50),
new Node("1", 347, 276),
new Node("2", 321, 280),
new Node("3", 350, 318),
new Node("4", 326, 317),
new Node("5", 357, 360),
new Node("6", 328, 355),
new Node("7", 355, 404),
new Node("8", 332, 390),
new Node("9", 359, 455),
new Node("10", 334, 425),
new Node("11", 423, 443),
new Node("12", 417, 400),
new Node("13", 417, 355),
new Node("14", 416, 313),
new Node("15", 417, 269)
};
var graphMatrix1 = CalculatePolarConnections(graphNodes1, new bool[,]
{
{ false } });
var graphMatrix1 = CalculatePolarConnections(graphNodes1, new bool[graphNodes1.Count, graphNodes1.Count]);
var mapdata = App.WifiManager.MapData;
Debug.WriteLine($"Mapdata : { mapdata}");
var graphNodes = graphNodes1;
......
using Microsoft.Maui.Graphics;
using Robobin.Models;
using RobobinApp.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace RobobinApp.Views
{
public class GraphicsDrawable : IDrawable
{
private Graph _graph;
private (float, float) _location;
public const float BaseNodeRadius = 5f; // Make this public if needed elsewhere
public const float NodeRadius = 5f; // Fixed radius for nodes
private static readonly Color DefaultNodeColor = Colors.Red;
private static readonly Color HomeNodeColor = Colors.Green;
private static readonly Color BackgroundColor = Color.FromHex("#2C2F33");
private static readonly Color ConnectionColor = Colors.Grey;
private static readonly Color HighlightedNodeColor = Colors.Yellow; // For the highlighted node
private static readonly Color PathColor = Colors.Blue; // For the path
private static readonly Color HighlightedNodeColor = Colors.Yellow; // Highlighted node color
private RectF storedDirtyRect;
public float CurrentScale { get; private set; } = 1.0f;
public (float X, float Y) CurrentOffset { get; private set; } = (0, 0);
private Node _highlightedNode;
private List<Node> _path;
public void SetGraph(Graph graph)
{
_graph = graph ?? throw new ArgumentNullException(nameof(graph));
_highlightedNode = null;
_path = null;
}
public void SetLocation((float, float) location)
public void HighlightNode(Node node)
{
_location = location;
_highlightedNode = node;
}
public void Draw(ICanvas canvas, RectF dirtyRect)
......@@ -44,127 +32,68 @@ namespace RobobinApp.Views
storedDirtyRect = dirtyRect;
if (_graph == null) return;
// Draw the background image
DrawBackground(canvas, dirtyRect);
(float minX, float minY, float maxX, float maxY) = CalculateBounds();
CurrentScale = CalculateScale(dirtyRect, minX, minY, maxX, maxY);
(float offsetX, float offsetY) = CalculateOffsets(dirtyRect, minX, minY, maxX, maxY, CurrentScale);
CurrentOffset = (offsetX, offsetY);
float nodeRadius = BaseNodeRadius * CurrentScale;
DrawConnections(canvas, CurrentScale, offsetX, offsetY);
DrawPath(canvas, CurrentScale, offsetX, offsetY);
DrawNodes(canvas, CurrentScale, offsetX, offsetY, nodeRadius, _highlightedNode);
DrawLocation(canvas, CurrentScale, offsetX, offsetY);
}
private void DrawLocation(ICanvas canvas, float scale, float offsetX, float offsetY)
{
Debug.WriteLine($"Drawing Location {_location.Item1} {_location.Item2}");
float scaledX = _location.Item1 * scale + offsetX;
float flippedY = storedDirtyRect.Height - (_location.Item2 * scale + offsetY);
canvas.FillColor = Colors.Yellow;
canvas.FillCircle(scaledX, flippedY, 5);
canvas.FontColor = Colors.White;
canvas.DrawString($"Robobin ({_location.Item1} {_location.Item2})", scaledX + 7, flippedY - 5, HorizontalAlignment.Left);
// Draw the nodes on top of the image
DrawNodes(canvas, NodeRadius, _highlightedNode);
}
private void DrawBackground(ICanvas canvas, RectF dirtyRect)
{
canvas.FillColor = BackgroundColor;
canvas.FillRectangle(dirtyRect);
}
private (float minX, float minY, float maxX, float maxY) CalculateBounds()
try
{
float minX = _graph.Nodes.Min(node => node.X);
float minY = _graph.Nodes.Min(node => node.Y);
float maxX = _graph.Nodes.Max(node => node.X);
float maxY = _graph.Nodes.Max(node => node.Y);
return (minX, minY, maxX, maxY);
}
// Load the embedded image resource
var assembly = typeof(GraphicsDrawable).Assembly;
var resourceStream = assembly.GetManifestResourceStream("Robobin.Resources.Images.lab_map.jpg");
private float CalculateScale(RectF dirtyRect, float minX, float minY, float maxX, float maxY)
if (resourceStream != null)
{
float graphWidth = maxX - minX;
float graphHeight = maxY - minY;
float scaleX = dirtyRect.Width / graphWidth;
float scaleY = dirtyRect.Height / graphHeight;
return Math.Min(scaleX, scaleY) * 0.8f;
var image = Microsoft.Maui.Graphics.Platform.PlatformImage.FromStream(resourceStream);
canvas.DrawImage(image, dirtyRect.Left, dirtyRect.Top, dirtyRect.Width, dirtyRect.Height);
}
private (float offsetX, float offsetY) CalculateOffsets(RectF dirtyRect, float minX, float minY, float maxX, float maxY, float scale)
else
{
float offsetX = dirtyRect.Center.X - ((minX + maxX) * 0.5f) * scale;
float offsetY = dirtyRect.Center.Y - ((minY + maxY) * 0.5f) * scale;
return (offsetX, offsetY);
throw new Exception("Embedded resource not found.");
}
private void DrawConnections(ICanvas canvas, float scale, float offsetX, float offsetY)
{
canvas.StrokeColor = ConnectionColor;
canvas.StrokeSize = 2;
foreach (var node in _graph.Nodes)
{
int nodeIndex = _graph.Nodes.IndexOf(node);
float startX = node.X * scale + offsetX;
float startY = storedDirtyRect.Height - (node.Y * scale + offsetY); // flip Y
for (int j = 0; j < _graph.Nodes.Count; j++)
{
var (magnitude, angle) = _graph.AdjacencyMatrix[nodeIndex, j];
if (magnitude > 0)
}
catch (Exception ex)
{
float targetX = (node.X + magnitude * MathF.Cos(MathF.PI * angle / 180)) * scale + offsetX;
float targetRawY = (node.Y + magnitude * MathF.Sin(MathF.PI * angle / 180)) * scale + offsetY;
float targetY = storedDirtyRect.Height - targetRawY; // flip Y
Debug.WriteLine($"Error loading image: {ex.Message}");
canvas.DrawLine(startX, startY, targetX, targetY);
}
}
// Fallback: fill background with a color if the image is unavailable
canvas.FillColor = Colors.Black;
canvas.FillRectangle(dirtyRect);
}
}
private void DrawNodes(ICanvas canvas, float scale, float offsetX, float offsetY, float nodeRadius, Node highlightedNode)
private void DrawNodes(ICanvas canvas, float nodeRadius, Node highlightedNode)
{
foreach (var node in _graph.Nodes)
{
float scaledX = node.X * scale + offsetX;
float flippedY = storedDirtyRect.Height - (node.Y * scale + offsetY); // flip Y
float x = node.X; // Use the original X-coordinate
float y = node.Y; // Use the original Y-coordinate
// Set fill color based on whether the node is highlighted
canvas.FillColor = (highlightedNode == node) ? HighlightedNodeColor : DefaultNodeColor;
canvas.FillColor = (highlightedNode == node)
? HighlightedNodeColor
: (node.Name == "Home" ? HomeNodeColor : DefaultNodeColor);
// Draw the node as a circle
canvas.FillCircle(x, y, nodeRadius);
canvas.FillCircle(scaledX, flippedY, nodeRadius);
// Optionally, draw node name or other details
canvas.FontColor = Colors.White;
var nodeDetails = $"{node.Name}";
canvas.DrawString(nodeDetails, scaledX + nodeRadius + 2, flippedY - nodeRadius, HorizontalAlignment.Left);
canvas.DrawString(node.Name, x + nodeRadius + 2, y - nodeRadius, HorizontalAlignment.Left);
}
}
public Node FindNearestNode(float clickX, float clickY, float scale, float offsetX, float offsetY)
public Node FindNearestNode(float tapPointX, float tapPointY)
{
// The coordinates given (clickX, clickY) are in the original coordinate system
// where the y-axis goes down. We must transform them similarly to how we did
// when drawing: flip the Y using storedDirtyRect.
float flippedClickY = clickY;
Node nearestNode = null;
float minDistance = float.MaxValue;
Node nearestNode = null;
foreach (var node in _graph.Nodes)
{
float scaledX = node.X * scale + offsetX;
// Flip Y when comparing distances
float flippedY = storedDirtyRect.Height - (node.Y * scale + offsetY);
float dx = clickX - scaledX;
float dy = flippedClickY - flippedY;
float distance = MathF.Sqrt(dx * dx + dy * dy);
float distance = (float)Math.Sqrt(Math.Pow(node.X - tapPointX, 2) + Math.Pow(node.Y - tapPointY, 2));
if (distance < minDistance)
{
minDistance = distance;
......@@ -174,109 +103,5 @@ namespace RobobinApp.Views
return nearestNode;
}
public void HighlightNode(Node node)
{
_highlightedNode = node;
}
public List<Node> AStarPathfinding(Node startNode, Node targetNode)
{
var openSet = new List<Node> { startNode };
var cameFrom = new Dictionary<Node, Node>();
var gScore = new Dictionary<Node, float>();
var fScore = new Dictionary<Node, float>();
foreach (var node in _graph.Nodes)
{
gScore[node] = float.MaxValue;
fScore[node] = float.MaxValue;
}
gScore[startNode] = 0;
fScore[startNode] = Heuristic(startNode, targetNode);
while (openSet.Count > 0)
{
Node currentNode = openSet.OrderBy(node => fScore[node]).First();
if (currentNode == targetNode)
{
return ReconstructPath(cameFrom, currentNode);
}
openSet.Remove(currentNode);
foreach (var edge in currentNode.Edges)
{
Node neighbor = edge.TargetNode;
float tentativeGScore = gScore[currentNode] + edge.Cost;
if (tentativeGScore < gScore[neighbor])
{
cameFrom[neighbor] = currentNode;
gScore[neighbor] = tentativeGScore;
fScore[neighbor] = gScore[neighbor] + Heuristic(neighbor, targetNode);
if (!openSet.Contains(neighbor))
{
openSet.Add(neighbor);
}
}
}
}
return new List<Node>();
}
private float Heuristic(Node a, Node b)
{
return MathF.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
}
private List<Node> ReconstructPath(Dictionary<Node, Node> cameFrom, Node currentNode)
{
var totalPath = new List<Node> { currentNode };
while (cameFrom.ContainsKey(currentNode))
{
currentNode = cameFrom[currentNode];
totalPath.Add(currentNode);
}
totalPath.Reverse();
return totalPath;
}
public Node GetHomeNode()
{
return _graph.Nodes.FirstOrDefault(n => n.Name == "Home");
}
public List<Node> Path
{
get => _path;
set => _path = value;
}
private void DrawPath(ICanvas canvas, float scale, float offsetX, float offsetY)
{
if (_path != null && _path.Count > 0)
{
canvas.StrokeColor = PathColor;
canvas.StrokeSize = 3;
for (int i = 0; i < _path.Count - 1; i++)
{
float startX = _path[i].X * scale + offsetX;
float startRawY = _path[i].Y * scale + offsetY;
float startY = storedDirtyRect.Height - startRawY; // flip Y
float endX = _path[i + 1].X * scale + offsetX;
float endRawY = _path[i + 1].Y * scale + offsetY;
float endY = storedDirtyRect.Height - endRawY; // flip Y
canvas.DrawLine(startX, startY, endX, endY);
}
}
}
}
}
......@@ -52,40 +52,32 @@ namespace RobobinApp.Views
private void OnGraphicsViewTapped(object sender, TappedEventArgs e)
{
if (App.WifiManager.Mode != "Call")
{
DisplayAlert("NO CALL","Bin must be in call mode to use this feature!","Sorry!");
return;
}
//if (App.WifiManager.Mode != "Call")
//{
// DisplayAlert("NO CALL","Bin must be in call mode to use this feature!","Sorry!");
// return;
//}
var tapPoint = e.GetPosition(GraphicsView);
var drawable = (GraphicsDrawable)Resources["drawable"];
float scale = drawable.CurrentScale;
var offset = drawable.CurrentOffset;
var tapPointX = (float)tapPoint.Value.X;
var tapPointY = (float)tapPoint.Value.Y;
Debug.WriteLine($"position: {tapPointX}, {tapPointY}");
(float,float) endPoint = (tapPointX, tapPointY);
var nearestNode = drawable.FindNearestNode(tapPointX, tapPointY, scale, offset.X, offset.Y);
Task task = App.WifiManager.SendCallMeRequest(nearestNode.Name);
// Highlight the nearest node
drawable.HighlightNode(nearestNode);
var nearestNode = drawable.FindNearestNode(tapPointX, tapPointY);
if (nearestNode != null)
{
// Find the home node
Node homeNode = drawable.GetHomeNode();
if (homeNode != null)
{
List<Node> path = drawable.AStarPathfinding(nearestNode, homeNode);
drawable.Path = path;
GraphicsView.Invalidate();
}
if (nearestNode != null)
{
Task task = App.WifiManager.SendCallMeRequest(nearestNode.Name);
// Highlight the nearest node
drawable.HighlightNode(nearestNode);
DisplayAlert("Node Clicked", $"You clicked on node: {nearestNode.Name}", "OK");
}
else
......@@ -113,7 +105,7 @@ namespace RobobinApp.Views
{
var drawable = (GraphicsDrawable)Resources["drawable"];
Debug.WriteLine($"VM Location { viewModel.Location }");
drawable.SetLocation(viewModel.Location);
//drawable.SetLocation(viewModel.Location);
drawable.SetGraph(viewModel.Graph);
GraphicsView.Invalidate(); // Redraw the GraphicsView
Debug.WriteLine("Graph updated and redrawn.");
......
......@@ -34,8 +34,6 @@ namespace RobobinApp.Views
var tapPoint = e.GetPosition(GraphicsView);
var drawable = (GraphicsDrawable)Resources["drawable"];
float scale = drawable.CurrentScale;
var offset = drawable.CurrentOffset;
var tapPointX = (float)tapPoint.Value.X;
var tapPointY = (float)tapPoint.Value.Y;
......@@ -43,23 +41,13 @@ namespace RobobinApp.Views
(float, float) endPoint = (tapPointX, tapPointY);
var nearestNode = drawable.FindNearestNode(tapPointX, tapPointY, scale, offset.X, offset.Y);
var nearestNode = drawable.FindNearestNode(tapPointX, tapPointY);
Task task = App.WifiManager.SendCallMeRequest(nearestNode.Name);
// Highlight the nearest node
drawable.HighlightNode(nearestNode);
if (nearestNode != null)
{
// Find the home node
Node homeNode = drawable.GetHomeNode();
if (homeNode != null)
{
List<Node> path = drawable.AStarPathfinding(nearestNode, homeNode);
drawable.Path = path;
GraphicsView.Invalidate();
}
DisplayAlert("Node Clicked", $"You clicked on node: {nearestNode.Name}", "OK");
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment