@* 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) {
Robot Model Image @if (RobotModel.ImageWidth > 0 && RobotModel.ImageHeight > 0) { }
} 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; } } }