using Mapsui; using Mapsui.Layers; using OperationControl.Controls; using OperationControl.Mapas.Interaction; using OperationControl.Mapas.Models; using OperationControl.Mapas.Rendering; namespace OperationControl.Mapas { public sealed partial class MapaOperacaoController { /* * ========================================================= * API PRINCIPAL DE RENDER * ========================================================= */ /// /// Prepara completamente um MapViewControl para /// representar o estado atual do subsistema de mapas. /// /// Use este método quando: /// - entrar em uma tela; /// - trocar de seção; /// - trocar mapa ativo; /// - carregar mapa novo; /// - receber mapa do rover. /// public void PrepararMapa(MapViewControl? mapaControl, MapaModoInteracao modoInteracao = MapaModoInteracao.Visualizacao, bool enquadrarDocumento = false) { if (mapaControl?.Mapa?.Map == null) { return; } RegistrarMapa(mapaControl); MapaModoInteracao modoEfetivo = _estadoEdicao.EmEdicao && _mapasEmEdicao.Contains(mapaControl) ? MapaModoInteracao.Edicao : modoInteracao; AplicarModoInteracao(mapaControl, modoEfetivo); /* * Se esta View estiver atualmente em edição, * sua fonte visual é DocumentoTrabalho. */ if ( _estadoEdicao.EmEdicao && _mapasEmEdicao.Contains( mapaControl ) ) { RenderizarEdicaoNoMapa( mapaControl ); RenderizarMovimentoNoMapa( mapaControl ); RenderizarRotaRetornoNoMapa( mapaControl ); RenderizarReferenciasGnssNoMapa( mapaControl ); RenderizarBordaGnssNoMapa( mapaControl ); RenderizarEntidadesDinamicasNoMapa( mapaControl ); mapaControl.Mapa.Refresh(); return; } /* * Ordem visual: * * 1 mapa operacional * 2 rastro / MPC * 3 retorno * 4 referência GNSS * 5 Base/Rover */ RenderizarWorkspaceNoMapa( mapaControl ); RenderizarMovimentoNoMapa( mapaControl ); RenderizarRotaRetornoNoMapa( mapaControl ); RenderizarReferenciasGnssNoMapa( mapaControl ); RenderizarBordaGnssNoMapa( mapaControl ); RenderizarEntidadesDinamicasNoMapa( mapaControl ); if (enquadrarDocumento) { EnquadrarDocumentoNoMapa( mapaControl, _workspace.Documento ); } mapaControl.Mapa.Refresh(); } public void RegistrarMapa(MapViewControl? mapaControl) { if (mapaControl?.Mapa?.Map == null) { return; } /* * Eventos são registrados uma única vez por * instância de MapViewControl. */ if (!_mapasRegistrados.Add(mapaControl)) { return; } mapaControl.MapaNovoViewportAlterado += OnMapaNovoViewportAlterado; mapaControl.MapaNovoRuaClicada += OnMapaNovoRuaClicada; mapaControl.MapaNovoPontoRetornoClicado += OnMapaNovoPontoRetornoClicado; mapaControl.MapaNovaEntidadeClicada += OnMapaNovaEntidadeClicada; mapaControl.MapaEditorFerramentaSelecionada += OnMapaEditorFerramentaSelecionada; mapaControl.MapaEditorLimparSelecaoSolicitado += OnMapaEditorLimparSelecaoSolicitado; mapaControl.MapaEditorRetanguloSelecionado += OnMapaEditorRetanguloSelecionado; mapaControl.MapaEditorPoligonoRecorteDefinido += OnMapaEditorPoligonoRecorteDefinido; mapaControl.MapaEditorDesfazerSolicitado += OnMapaEditorDesfazerSolicitado; mapaControl.MapaEditorRefazerSolicitado += OnMapaEditorRefazerSolicitado; mapaControl.MapaEditorExcluirSelecionadasSolicitado += OnMapaEditorExcluirSelecionadasSolicitado; mapaControl.MapaEditorAplicarEdicaoSolicitado += OnMapaEditorAplicarEdicaoSolicitado; mapaControl.MapaEditorCancelarEdicaoSolicitado += OnMapaEditorCancelarEdicaoSolicitado; mapaControl.MapaEditorEscopoRecorteAlterado += OnMapaEditorEscopoRecorteAlterado; mapaControl.MapaEditorBordaGnssAcaoSolicitada += OnMapaEditorBordaGnssAcaoSolicitada; mapaControl.MapaEditorRestaurarFonteSolicitado += OnMapaEditorRestaurarFonteSolicitado; } /* * ========================================================= * WORKSPACE * ========================================================= */ private void RenderizarWorkspaceNoMapa( MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } /* * Remove somente o render deste Mapsui. */ if ( _rendersMapa.TryGetValue( mapaControl, out var renderAnterior ) ) { mapaControl .Mapa .Map .Layers .Remove( renderAnterior.Layer ); _rendersMapa.Remove( mapaControl ); } else { /* * Guarda adicional durante a migração. */ var layerAnterior = mapaControl .Mapa .Map .Layers .FirstOrDefault( x => x.Name == MapaRenderService .NomeCamadaPadrao ); if (layerAnterior != null) { mapaControl .Mapa .Map .Layers .Remove( layerAnterior ); } } if (!_workspace.PossuiMapa) { mapaControl.DefinirCamadaMapaNovo( null ); return; } var render = _renderService .CriarCamada( _workspace.Documento! ); _renderService .AplicarSelecao( render, _workspace.Selecao ); mapaControl .Mapa .Map .Layers .Add( render.Layer ); mapaControl .DefinirCamadaMapaNovo( render.Layer ); _rendersMapa[ mapaControl ] = render; } private void InvalidarRendersWorkspace() { foreach ( var item in _rendersMapa.ToArray()) { try { MapViewControl mapaControl = item.Key; MapaRenderResult render = item.Value; if ( mapaControl.Mapa?.Map != null ) { mapaControl .Mapa .Map .Layers .Remove( render.Layer ); mapaControl .DefinirCamadaMapaNovo( null ); mapaControl .Mapa .Refresh(); } } catch (Exception ex) { Log( "[MAPA][RENDER][INVALIDAR][ERRO] " + ex.Message ); } } _rendersMapa.Clear(); } private void AtualizarEstiloSelecaoRua( string ruaId) { foreach ( var item in _rendersMapa.ToArray()) { try { _renderService .AtualizarEstiloRua( item.Value, _workspace.Selecao, ruaId ); item.Key .Mapa .Refresh(); } catch (Exception ex) { Log( "[MAPA][SELECAO][RENDER][ERRO] " + ex.Message ); } } } /* * ========================================================= * ROTA DE RETORNO * ========================================================= */ private void RenderizarRotaRetornoNoMapa( MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } if ( _layersRetorno.TryGetValue( mapaControl, out var camada ) ) { _rotaRenderService .AtualizarCamada( camada, _workspace.RotaRetorno ); } else { camada = _rotaRenderService .CriarCamada( _workspace.RotaRetorno ); mapaControl .Mapa .Map .Layers .Add( camada ); _layersRetorno[ mapaControl ] = camada; } } private void RenderizarRotasRegistradas() { foreach ( var mapa in _mapasRegistrados.ToArray()) { RenderizarRotaRetornoNoMapa( mapa ); GarantirEntidadesNoTopo( mapa ); mapa.Mapa.Refresh(); } } private void InvalidarRendersRotaRetorno() { foreach ( var item in _layersRetorno.ToArray()) { try { var mapaControl = item.Key; var camada = item.Value; if ( mapaControl.Mapa?.Map != null ) { mapaControl .Mapa .Map .Layers .Remove( camada ); mapaControl .Mapa .Refresh(); } } catch (Exception ex) { Log( "[MAPA][RETORNO][INVALIDAR][ERRO] " + ex.Message ); } } _layersRetorno.Clear(); } /* * ========================================================= * ENTIDADES DINÂMICAS * ========================================================= */ private void RenderizarEntidadesDinamicasNoMapa( MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } double resolution = 1.0; try { resolution = mapaControl .Mapa .Map .Navigator .Viewport .Resolution; } catch { resolution = 1.0; } if ( _layersEntidades.TryGetValue( mapaControl, out var camada ) ) { _entidadeRenderService .AtualizarCamada( camada, _estadoDinamico, resolution ); } else { camada = _entidadeRenderService .CriarCamada( _estadoDinamico, resolution ); mapaControl .Mapa .Map .Layers .Add( camada ); _layersEntidades[ mapaControl ] = camada; } mapaControl .DefinirCamadaEntidadesDinamicasNova( camada ); GarantirEntidadesNoTopo( mapaControl ); } private void GarantirEntidadesNoTopo( MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } if ( !_layersEntidades.TryGetValue( mapaControl, out var camada ) ) { return; } var layers = mapaControl .Mapa .Map .Layers; if (!layers.Contains(camada)) return; /* * Fazemos isso somente em pontos de * composição do mapa, não no mouse move. */ layers.Remove( camada ); layers.Add( camada ); } /* * ========================================================= * MOVIMENTO * ========================================================= */ private void RenderizarMovimentoNoMapa( MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } /* * RASTRO */ if ( _layersRastro.TryGetValue( mapaControl, out var camadaRastro ) ) { _rastroRenderService .AtualizarCamada( camadaRastro, _estadoMovimento ); } else { camadaRastro = _rastroRenderService .CriarCamada( _estadoMovimento ); mapaControl .Mapa .Map .Layers .Add( camadaRastro ); _layersRastro[ mapaControl ] = camadaRastro; } /* * PREDIÇÃO MPC */ if ( _layersPredicao.TryGetValue( mapaControl, out var camadaPredicao ) ) { _predicaoRenderService .AtualizarCamada( camadaPredicao, _estadoMovimento ); } else { camadaPredicao = _predicaoRenderService .CriarCamada( _estadoMovimento ); mapaControl .Mapa .Map .Layers .Add( camadaPredicao ); _layersPredicao[ mapaControl ] = camadaPredicao; } } /* * ========================================================= * REFERÊNCIA GNSS * ========================================================= */ private void RenderizarReferenciasGnssNoMapa( MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } if ( _layersReferenciaGnss .TryGetValue( mapaControl, out var camada ) ) { if (_mostrarReferenciasGnss) { _referenciaGnssRenderService .AtualizarCamada( camada, _estadoDinamico ); } else { camada.Features = Array.Empty(); } } else { camada = _referenciaGnssRenderService .CriarCamada( _estadoDinamico ); if (!_mostrarReferenciasGnss) { camada.Features = Array.Empty(); } mapaControl .Mapa .Map .Layers .Add( camada ); _layersReferenciaGnss[ mapaControl ] = camada; } } /* * ========================================================= * ENQUADRAMENTO * ========================================================= */ public void EnquadrarWorkspaceNoMapa( MapViewControl? mapaControl, double margem = 1.15) { EnquadrarDocumentoNoMapa( mapaControl, _workspace.Documento, margem ); } private void RenderizarEdicaoNoMapa(MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null || !_estadoEdicao.EmEdicao || _estadoEdicao.DocumentoTrabalho == null ) { return; } /* * Remove qualquer render de mapa operacional * atualmente apresentado nesta View. */ if ( _rendersMapa.TryGetValue( mapaControl, out var renderAnterior ) ) { mapaControl .Mapa .Map .Layers .Remove( renderAnterior.Layer ); _rendersMapa.Remove( mapaControl ); } var render = _edicaoRenderService .CriarCamada( _estadoEdicao ); mapaControl .Mapa .Map .Layers .Add( render.Layer ); /* * Para o MapViewControl, esta continua sendo * a layer de ruas interativa. * * Ele não precisa saber se é missão ou edição. */ mapaControl .DefinirCamadaMapaNovo( render.Layer ); _rendersMapa[ mapaControl ] = render; GarantirEntidadesNoTopo( mapaControl ); mapaControl .Mapa .Refresh(); } private void RenderizarDocumentoEdicaoAtual() { foreach ( var mapa in _mapasEmEdicao .ToArray()) { RenderizarEdicaoNoMapa( mapa ); RenderizarBordaGnssNoMapa( mapa ); GarantirEntidadesNoTopo( mapa ); mapa.Mapa.Refresh(); } } private void RemoverRenderEdicao(MapViewControl mapaControl) { if ( mapaControl?.Mapa?.Map == null ) { return; } if ( _rendersMapa.TryGetValue( mapaControl, out var render ) ) { mapaControl .Mapa .Map .Layers .Remove( render.Layer ); _rendersMapa.Remove( mapaControl ); } mapaControl .DefinirCamadaMapaNovo( null ); mapaControl .Mapa .Refresh(); } private static void EnquadrarDocumentoNoMapa( MapViewControl? mapaControl, MapaDocumento? documento, double margem = 1.15) { if ( mapaControl == null || documento == null ) { return; } var limites = documento.Limites; if ( limites == null || limites.IsNull ) { return; } mapaControl.EnquadrarAreaWgs84( minLongitude: limites.MinX, minLatitude: limites.MinY, maxLongitude: limites.MaxX, maxLatitude: limites.MaxY, margem: margem ); } } }