using Mapsui; using Mapsui.Layers; using Mapsui.Nts; using Mapsui.Projections; using Mapsui.Styles; using NetTopologySuite.Geometries; using OperationControl.Mapas.Models; using Brush = Mapsui.Styles.Brush; using Color = Mapsui.Styles.Color; using Pen = Mapsui.Styles.Pen; namespace OperationControl.Mapas.Rendering { public sealed class MapaReferenciaGnssRenderService { public const string NomeCamada = "MapaReferenciasGnssNovo"; public MemoryLayer CriarCamada( MapaEstadoDinamico estado) { if (estado == null) { throw new ArgumentNullException( nameof(estado) ); } return new MemoryLayer { Name = NomeCamada, Features = CriarFeatures( estado ), Style = null }; } public void AtualizarCamada( MemoryLayer camada, MapaEstadoDinamico estado) { if (camada == null) { throw new ArgumentNullException( nameof(camada) ); } if (estado == null) { throw new ArgumentNullException( nameof(estado) ); } camada.Features = CriarFeatures( estado ); } private static List CriarFeatures( MapaEstadoDinamico estado) { var features = new List(); foreach ( var entidade in estado.Entidades) { if ( entidade == null || !CoordenadaValida( entidade.Latitude, entidade.Longitude ) || !CoordenadaValida( entidade.LatitudeBruta, entidade.LongitudeBruta ) ) { continue; } /* * Posição utilizada pelo sistema, * já considerando a correção aplicada. */ var corrigido = SphericalMercator .FromLonLat( entidade.Longitude!.Value, entidade.Latitude!.Value ); /* * Posição GNSS de referência/bruta * anterior à correção de lever arm. */ var bruto = SphericalMercator .FromLonLat( entidade.LongitudeBruta!.Value, entidade.LatitudeBruta!.Value ); CriarLinha( features, entidade, bruto.x, bruto.y, corrigido.x, corrigido.y ); CriarPontoBruto( features, entidade, bruto.x, bruto.y ); CriarPontoCorrigido( features, entidade, corrigido.x, corrigido.y ); } return features; } private static void CriarLinha( List features, MapaEntidadeDinamica entidade, double rawX, double rawY, double corrigidoX, double corrigidoY) { var feature = new GeometryFeature { Geometry = new LineString( new[] { new Coordinate( rawX, rawY ), new Coordinate( corrigidoX, corrigidoY ) } ) }; AplicarMetadados( feature, entidade, "LigacaoLeverArm" ); feature.Styles.Add( new VectorStyle { Line = new Pen { Color = new Color( 255, 255, 255, 170 ), Width = 1, PenStyle = PenStyle.Dash } } ); features.Add( feature ); } private static void CriarPontoBruto( List features, MapaEntidadeDinamica entidade, double x, double y) { var feature = new PointFeature( new MPoint( x, y ) ); AplicarMetadados( feature, entidade, "GnssBruto" ); feature.Styles.Add( new SymbolStyle { SymbolType = SymbolType.Ellipse, SymbolScale = 0.55, Fill = new Brush( new Color( 255, 215, 0, 255 ) ), Outline = new Pen( new Color( 20, 20, 20, 230 ), 1 ) } ); features.Add( feature ); } private static void CriarPontoCorrigido( List features, MapaEntidadeDinamica entidade, double x, double y) { var feature = new PointFeature( new MPoint( x, y ) ); AplicarMetadados( feature, entidade, "GnssCorrigidoLeverArm" ); feature.Styles.Add( new SymbolStyle { SymbolType = SymbolType.Ellipse, SymbolScale = 0.50, Fill = new Brush( Color.White ), Outline = new Pen( new Color( 20, 20, 20, 230 ), 1 ) } ); features.Add( feature ); } private static void AplicarMetadados( IFeature feature, MapaEntidadeDinamica entidade, string referencia) { feature["EntidadeId"] = entidade.Id; feature["Tipo"] = "ReferenciaGnss"; feature["Referencia"] = referencia; } private static bool CoordenadaValida( double? latitude, double? longitude) { if ( !latitude.HasValue || !longitude.HasValue ) { return false; } if ( !double.IsFinite(latitude.Value) || !double.IsFinite(longitude.Value) ) { return false; } if ( latitude.Value < -90.0 || latitude.Value > 90.0 || longitude.Value < -180.0 || longitude.Value > 180.0 ) { return false; } /* * Mesma proteção que existia no legado: * não desenhar referência fake em 0,0. */ if ( Math.Abs(latitude.Value) < 0.0000001 && Math.Abs(longitude.Value) < 0.0000001 ) { return false; } return true; } } }