@*
Component: RobotModelImagePreview
Purpose: Displays robot model image with navigation point overlay visualization.
The navigation point is shown as arrows (X+ in red, Y+ in green) and a blue marker.
Uses SVG viewBox to automatically scale overlay to match displayed image size.
*@
@using RobotNet10.FleetManager.Shared.DTOs.RobotModel
@using RobotNet10.FleetManager.Client.Services
@inject RobotModelApiService ApiService
@if (imageBase64 != null)
{
}
else
{
No image available
}
@code {
[Parameter]
public RobotModelDto RobotModel { get; set; } = null!;
private string? imageBase64;
private double svgX;
private double svgY;
private double arrowLength;
private ElementReference imageElement;
private string uniqueId = Guid.NewGuid().ToString("N")[..8]; // Unique ID for SVG markers
protected override async Task OnInitializedAsync()
{
await LoadImageAsync();
}
protected override async Task OnParametersSetAsync()
{
await LoadImageAsync();
}
private void OnImageLoaded()
{
CalculateNavigationPoint();
}
private void CalculateNavigationPoint()
{
if (RobotModel.ImageWidth > 0 && RobotModel.ImageHeight > 0 && RobotModel.Length > 0 && RobotModel.Width > 0)
{
// Calculate scale: pixels per meter in original image
// This converts from robot coordinate system (meters) to image coordinate system (pixels)
var scaleX = RobotModel.ImageWidth / RobotModel.Length;
var scaleY = RobotModel.ImageHeight / RobotModel.Width;
// Navigation point coordinates are relative to the bottom-left corner of the image (in meters)
// Image coordinate system: (0,0) is at bottom-left corner
// X-axis: left to right (0 to ImageWidth)
// Y-axis: bottom to top (0 to ImageHeight in robot coords, but SVG Y increases downward)
// Convert navigation point from meters to pixels
// NavigationPointX: distance from left edge (in meters)
// NavigationPointY: distance from bottom edge (in meters)
var navX = RobotModel.NavigationPointX * scaleX;
var navY = RobotModel.NavigationPointY * scaleY;
// Final position in SVG coordinates (using original image coordinate system)
// SVG viewBox will automatically scale to match the displayed image size
// X: from left edge (0 is left, ImageWidth is right)
svgX = navX;
// Y: from bottom edge (0 is bottom in robot coords, but SVG Y=0 is top, Y=ImageHeight is bottom)
// So we need to invert: svgY = ImageHeight - navY
svgY = RobotModel.ImageHeight - navY;
// Arrow length: 15% of the smaller dimension for better visibility
arrowLength = Math.Min(RobotModel.ImageWidth, RobotModel.ImageHeight) * 0.15;
StateHasChanged();
}
}
private async Task LoadImageAsync()
{
try
{
imageBase64 = await ApiService.GetImageAsync(RobotModel.Id);
if (imageBase64 != null)
{
// Calculate navigation point when image loads
CalculateNavigationPoint();
}
}
catch (Exception)
{
imageBase64 = null;
}
}
}