agrobot_base/AgroBase/OperationControl/ViewModels/Views/PreparacaoMapa/PreparacaoMapaBottomViewMod...

977 lines
29 KiB
C#

using OperationControl.Helpers;
using OperationControl.Models;
using OperationControl.Windows;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Input;
using static OperationControl.Services.BaseFixService;
using static OperationControl.Services.GpsService;
namespace OperationControl.ViewModels
{
public class MetodoFixacaoItem
{
public MetodoFixacaoBase Valor { get; set; }
public string Nome { get; set; } = string.Empty;
}
public class PreparacaoMapaBottomViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public event Action<string, AgroBase.Models.Enums.TipoMapaOperacao>? CarregarMapaSolicitado;
public event Action? CriarMapaSolicitado;
public event Action? EditarMapaSolicitado;
// Método, latitude, longitude, altitude, offset frontal cm, offset lateral cm
public event Action<MetodoFixacaoBase, double?, double?, double?>? FixarBaseSolicitado;
// Offset frontal cm, offset lateral cm
public event Action<double?, double?>? AplicarOffsetSolicitado;
public event Action? UsarGnssMovelSolicitado;
public event Action? ContinuarSolicitado;
public event Action? VoltarSolicitado;
public List<MetodoFixacaoItem> MetodosFixacaoDisponiveis { get; } = new()
{
new MetodoFixacaoItem
{
Valor =
MetodoFixacaoBase.Ntrip,
Nome =
"Correção pela rede (NTRIP)"
},
new MetodoFixacaoItem
{
Valor =
MetodoFixacaoBase.SurveyIn,
Nome =
"Determinar posição no local"
},
new MetodoFixacaoItem
{
Valor =
MetodoFixacaoBase.Manual,
Nome =
"Informar posição conhecida"
}
};
public ICommand CarregarMapaCommand { get; }
public ICommand CriarMapaCommand { get; }
public ICommand EditarMapaCommand { get; }
public ICommand FixarBaseCommand { get; }
public ICommand AplicarOffsetCommand { get; }
public ICommand UsarGnssMovelCommand { get; }
public ICommand ContinuarCommand { get; }
public ICommand VoltarCommand { get; }
public PreparacaoMapaBottomViewModel()
{
CarregarMapaCommand = new RelayCommand(_ => ExecutarCarregarMapa(), _ => PodeCarregarMapa);
CriarMapaCommand = new RelayCommand(_ => CriarMapaSolicitado?.Invoke(), _ => PodeCriarMapa);
EditarMapaCommand = new RelayCommand(_ => EditarMapaSolicitado?.Invoke(), _ => PodeEditarMapa);
FixarBaseCommand = new RelayCommand(_ => ExecutarFixarBase(), _ => PodeFixarBase);
AplicarOffsetCommand = new RelayCommand(_ => ExecutarAplicarOffset(), _ => PodeEditarOffsetBase);
UsarGnssMovelCommand = new RelayCommand(_ => ExecutarUsarGnssMovel(), _ => PodeUsarGnssMovel);
ContinuarCommand = new RelayCommand(_ => ContinuarSolicitado?.Invoke(), _ => PodeContinuar);
VoltarCommand = new RelayCommand(_ => VoltarSolicitado?.Invoke());
MetodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip;
OffsetFrontalBaseTexto = "0";
OffsetLateralBaseTexto = "0";
StatusTexto = "Carregue o mapa da operação e prepare o GNSS.";
}
private MetodoFixacaoBase _metodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip;
public MetodoFixacaoBase MetodoFixacaoSelecionado
{
get => _metodoFixacaoSelecionado;
set
{
if (_metodoFixacaoSelecionado != value)
{
_metodoFixacaoSelecionado = value;
OnPropertyChanged(nameof(MetodoFixacaoSelecionado));
OnPropertyChanged(nameof(ExibirCamposManuais));
OnPropertyChanged(nameof(ExibirProgresso));
OnPropertyChanged(nameof(PodeEditarCoordenadasManuais));
OnPropertyChanged(nameof(PodeFixarBase));
OnPropertyChanged(nameof(TextoBotaoFixarBase));
if (!FixacaoEmAndamento)
{
StatusTexto = _metodoFixacaoSelecionado switch
{
MetodoFixacaoBase.Ntrip =>
"Método selecionado: NTRIP. A base será fixada via correção RTK pela rede.",
MetodoFixacaoBase.SurveyIn =>
"Método selecionado: Survey-In. A base calculará sua posição média localmente.",
MetodoFixacaoBase.Manual =>
"Método selecionado: Manual. Informe latitude, longitude e altitude conhecidas da base.",
_ =>
"Pronto para fixar a posição da base."
};
}
}
}
}
private bool _mapaCarregado;
private bool _edicaoMapaAtiva;
private bool _criacaoMapaAtiva;
/// <summary>
/// Enquanto o editor estiver aberto nesta etapa:
/// - não trocamos o arquivo de mapa;
/// - não navegamos para outra etapa;
/// - não abrimos uma segunda sessão de edição.
///
/// Os controles de GNSS permanecem disponíveis porque
/// o levantamento de borda pode depender do modo móvel.
/// </summary>
public bool EdicaoMapaAtiva =>
_edicaoMapaAtiva;
public bool CriacaoMapaAtiva =>
_criacaoMapaAtiva;
public bool PodeCriarMapa =>
!_edicaoMapaAtiva &&
!_criacaoMapaAtiva &&
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public bool PodeEditarMapa =>
_mapaCarregado &&
!_edicaoMapaAtiva &&
!_criacaoMapaAtiva &&
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public bool PodeContinuar =>
_mapaCarregado &&
!_edicaoMapaAtiva &&
!_criacaoMapaAtiva &&
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public bool PodeVoltar =>
!_edicaoMapaAtiva &&
!_criacaoMapaAtiva &&
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public void DefinirMapaCarregado(bool carregado)
{
if (
_mapaCarregado ==
carregado
)
{
return;
}
_mapaCarregado =
carregado;
OnPropertyChanged(
nameof(PodeEditarMapa)
);
OnPropertyChanged(
nameof(PodeContinuar)
);
}
public void DefinirEdicaoMapaAtiva(bool ativa)
{
if (
_edicaoMapaAtiva ==
ativa
)
{
return;
}
_edicaoMapaAtiva =
ativa;
OnPropertyChanged(
nameof(EdicaoMapaAtiva)
);
OnPropertyChanged(
nameof(PodeEditarMapa)
);
OnPropertyChanged(
nameof(PodeCriarMapa)
);
OnPropertyChanged(
nameof(PodeCarregarMapa)
);
OnPropertyChanged(
nameof(PodeContinuar)
);
OnPropertyChanged(
nameof(PodeVoltar)
);
}
public void DefinirCriacaoMapaAtiva(bool ativa)
{
if (_criacaoMapaAtiva == ativa)
return;
_criacaoMapaAtiva = ativa;
OnPropertyChanged(nameof(CriacaoMapaAtiva));
OnPropertyChanged(nameof(PodeCriarMapa));
OnPropertyChanged(nameof(PodeEditarMapa));
OnPropertyChanged(nameof(PodeCarregarMapa));
OnPropertyChanged(nameof(PodeContinuar));
OnPropertyChanged(nameof(PodeVoltar));
}
private GnssPapelEstacao _papelGnssAtual = GnssPapelEstacao.Indefinido;
public GnssPapelEstacao PapelGnssAtual
{
get =>
_papelGnssAtual;
private set
{
if (
_papelGnssAtual ==
value
)
{
return;
}
_papelGnssAtual =
value;
OnPropertyChanged(
nameof(PapelGnssAtual)
);
OnPropertyChanged(
nameof(PapelGnssTexto)
);
OnPropertyChanged(
nameof(PapelGnssDescricao)
);
OnPropertyChanged(
nameof(PapelGnssCor)
);
OnPropertyChanged(
nameof(TextoBotaoModoGnss)
);
OnPropertyChanged(
nameof(PodeUsarGnssMovel)
);
OnPropertyChanged(
nameof(TextoBotaoFixarBase)
);
}
}
private bool _alteracaoPapelGnssEmAndamento;
public bool AlteracaoPapelGnssEmAndamento {
get =>
_alteracaoPapelGnssEmAndamento;
private set
{
if (
_alteracaoPapelGnssEmAndamento ==
value
)
{
return;
}
_alteracaoPapelGnssEmAndamento =
value;
OnPropertyChanged(
nameof(
AlteracaoPapelGnssEmAndamento
)
);
OnPropertyChanged(
nameof(PapelGnssTexto)
);
OnPropertyChanged(
nameof(PapelGnssDescricao)
);
OnPropertyChanged(
nameof(PapelGnssCor)
);
OnPropertyChanged(
nameof(PodeUsarGnssMovel)
);
OnPropertyChanged(
nameof(PodeCarregarMapa)
);
OnPropertyChanged(
nameof(PodeEditarMapa)
);
OnPropertyChanged(
nameof(PodeCriarMapa)
);
OnPropertyChanged(
nameof(PodeEditarMetodoFixacao)
);
OnPropertyChanged(
nameof(PodeEditarCoordenadasManuais)
);
OnPropertyChanged(
nameof(PodeEditarOffsetBase)
);
OnPropertyChanged(
nameof(PodeFixarBase)
);
OnPropertyChanged(
nameof(PodeContinuar)
);
OnPropertyChanged(
nameof(PodeVoltar)
);
}
}
public string PapelGnssTexto
{
get
{
if (AlteracaoPapelGnssEmAndamento)
return "CONFIGURANDO...";
if (FixacaoEmAndamento)
return "FIXANDO BASE...";
return PapelGnssAtual switch
{
GnssPapelEstacao.Movel =>
"LEVANTAMENTO MÓVEL",
GnssPapelEstacao.BaseFixa =>
"BASE FIXA",
_ =>
"NÃO DEFINIDO"
};
}
}
public string PapelGnssDescricao
{
get
{
if (AlteracaoPapelGnssEmAndamento)
{
return
"Aguarde enquanto o modo do receptor GNSS é alterado.";
}
if (FixacaoEmAndamento)
{
return
"A posição da estação está sendo determinada.";
}
return PapelGnssAtual switch
{
GnssPapelEstacao.Movel =>
"A antena pode ser movimentada e usada para levantamento e edição do mapa.",
GnssPapelEstacao.BaseFixa =>
"A estação está fixa e pronta para fornecer referência à operação.",
_ =>
"Escolha o modo móvel para levantamento ou fixe a estação como base."
};
}
}
public Brush PapelGnssCor =>
AlteracaoPapelGnssEmAndamento ||
FixacaoEmAndamento
? Brushes.Gold
: PapelGnssAtual switch
{
GnssPapelEstacao.Movel =>
Brushes.DeepSkyBlue,
GnssPapelEstacao.BaseFixa =>
Brushes.LimeGreen,
_ =>
Brushes.Gray
};
public string TextoBotaoModoGnss =>
PapelGnssAtual switch
{
GnssPapelEstacao.BaseFixa =>
"Liberar para levantamento",
GnssPapelEstacao.Movel =>
"Levantamento ativo",
_ =>
"Usar para levantamento"
};
public bool PodeUsarGnssMovel =>
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento &&
PapelGnssAtual !=
GnssPapelEstacao.Movel;
private bool _fixacaoEmAndamento;
public bool FixacaoEmAndamento
{
get => _fixacaoEmAndamento;
set
{
if (_fixacaoEmAndamento != value)
{
_fixacaoEmAndamento = value;
OnPropertyChanged(nameof(FixacaoEmAndamento));
OnPropertyChanged(nameof(PodeCarregarMapa));
OnPropertyChanged(nameof(PodeEditarMapa));
OnPropertyChanged(nameof(PodeCriarMapa));
OnPropertyChanged(nameof(PodeEditarMetodoFixacao));
OnPropertyChanged(nameof(PodeEditarCoordenadasManuais));
OnPropertyChanged(nameof(PodeEditarOffsetBase));
OnPropertyChanged(nameof(PodeFixarBase));
OnPropertyChanged(nameof(TextoBotaoFixarBase));
OnPropertyChanged(
nameof(PapelGnssTexto)
);
OnPropertyChanged(
nameof(PapelGnssDescricao)
);
OnPropertyChanged(
nameof(PapelGnssCor)
);
OnPropertyChanged(
nameof(PodeUsarGnssMovel)
);
OnPropertyChanged(
nameof(PodeContinuar)
);
OnPropertyChanged(
nameof(PodeVoltar)
);
}
}
}
public bool PodeCarregarMapa =>
!_edicaoMapaAtiva &&
!_criacaoMapaAtiva &&
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public bool PodeEditarMetodoFixacao =>
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public bool PodeEditarCoordenadasManuais =>
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento &&
MetodoFixacaoSelecionado ==
MetodoFixacaoBase.Manual;
public bool PodeEditarOffsetBase =>
!FixacaoEmAndamento &&
!AlteracaoPapelGnssEmAndamento;
public bool ExibirCamposManuais => MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual;
public bool ExibirProgresso => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual;
private bool _exibirOffsets;
public bool ExibirOffsets
{
get { return _exibirOffsets; }
set
{
_exibirOffsets = value;
OnPropertyChanged(nameof(ExibirOffsets));
}
}
public bool PodeFixarBase
{
get
{
if (AlteracaoPapelGnssEmAndamento)
return false;
if (FixacaoEmAndamento)
return true; // botão vira "Parar"
if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual)
return true;
return LatitudeManual.HasValue &&
LongitudeManual.HasValue &&
AltitudeManual.HasValue;
}
}
public string TextoBotaoFixarBase
{
get
{
if (FixacaoEmAndamento)
return "Parar";
if (
MetodoFixacaoSelecionado ==
MetodoFixacaoBase.Manual
)
{
return PapelGnssAtual ==
GnssPapelEstacao.BaseFixa
? "Reposicionar base"
: "Aplicar posição da base";
}
return PapelGnssAtual ==
GnssPapelEstacao.BaseFixa
? "Reposicionar base"
: "Fixar como base";
}
}
private double? _latitudeManual;
public double? LatitudeManual
{
get => _latitudeManual;
private set
{
if (_latitudeManual != value)
{
_latitudeManual = value;
OnPropertyChanged(nameof(LatitudeManual));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private double? _longitudeManual;
public double? LongitudeManual
{
get => _longitudeManual;
private set
{
if (_longitudeManual != value)
{
_longitudeManual = value;
OnPropertyChanged(nameof(LongitudeManual));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private double? _altitudeManual;
public double? AltitudeManual
{
get => _altitudeManual;
private set
{
if (_altitudeManual != value)
{
_altitudeManual = value;
OnPropertyChanged(nameof(AltitudeManual));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private string _latitudeManualTexto = string.Empty;
public string LatitudeManualTexto
{
get => _latitudeManualTexto;
set
{
if (_latitudeManualTexto != value)
{
_latitudeManualTexto = value;
LatitudeManual = TryParseDouble(value);
OnPropertyChanged(nameof(LatitudeManualTexto));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private string _longitudeManualTexto = string.Empty;
public string LongitudeManualTexto
{
get => _longitudeManualTexto;
set
{
if (_longitudeManualTexto != value)
{
_longitudeManualTexto = value;
LongitudeManual = TryParseDouble(value);
OnPropertyChanged(nameof(LongitudeManualTexto));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private string _altitudeManualTexto = string.Empty;
public string AltitudeManualTexto
{
get => _altitudeManualTexto;
set
{
if (_altitudeManualTexto != value)
{
_altitudeManualTexto = value;
AltitudeManual = TryParseDouble(value);
OnPropertyChanged(nameof(AltitudeManualTexto));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private double? _offsetFrontalBaseCm = 0;
public double? OffsetFrontalBaseCm
{
get => _offsetFrontalBaseCm;
private set
{
if (_offsetFrontalBaseCm != value)
{
_offsetFrontalBaseCm = value;
OnPropertyChanged(nameof(OffsetFrontalBaseCm));
}
}
}
private double? _offsetLateralBaseCm = 0;
public double? OffsetLateralBaseCm
{
get => _offsetLateralBaseCm;
private set
{
if (_offsetLateralBaseCm != value)
{
_offsetLateralBaseCm = value;
OnPropertyChanged(nameof(OffsetLateralBaseCm));
}
}
}
private string _offsetFrontalBaseTexto = "0";
public string OffsetFrontalBaseTexto
{
get => _offsetFrontalBaseTexto;
set
{
if (_offsetFrontalBaseTexto != value)
{
_offsetFrontalBaseTexto = value;
OffsetFrontalBaseCm = TryParseDouble(value);
OnPropertyChanged(nameof(OffsetFrontalBaseTexto));
}
}
}
private string _offsetLateralBaseTexto = "0";
public string OffsetLateralBaseTexto
{
get => _offsetLateralBaseTexto;
set
{
if (_offsetLateralBaseTexto != value)
{
_offsetLateralBaseTexto = value;
OffsetLateralBaseCm = TryParseDouble(value);
OnPropertyChanged(nameof(OffsetLateralBaseTexto));
}
}
}
private double _progressoFixacao;
public double ProgressoFixacao
{
get => _progressoFixacao;
set
{
if (Math.Abs(_progressoFixacao - value) > 0.001)
{
_progressoFixacao = value;
OnPropertyChanged(nameof(ProgressoFixacao));
OnPropertyChanged(nameof(ProgressoFixacaoTexto));
}
}
}
public string ProgressoFixacaoTexto => $"{ProgressoFixacao:F0}%";
private string _statusTexto = string.Empty;
public string StatusTexto
{
get => _statusTexto;
set
{
if (_statusTexto != value)
{
_statusTexto = value;
OnPropertyChanged(nameof(StatusTexto));
}
}
}
private void ExecutarCarregarMapa()
{
var dlgTipo = new SelecaoTipoMapa
{
Owner = Variaveis.Dock
};
if (dlgTipo.ShowDialog() != true || dlgTipo.Resultado == null)
return;
var tipoMapa = dlgTipo.Resultado.Value;
var dlg = new Microsoft.Win32.OpenFileDialog
{
Filter = "Arquivos de mapa|*.geojson;*.json;*.shp",
Title = "Selecione o arquivo de mapa"
};
if (dlg.ShowDialog() == true)
{
StatusTexto = $"Mapa selecionado: {System.IO.Path.GetFileName(dlg.FileName)} ({tipoMapa})";
CarregarMapaSolicitado?.Invoke(dlg.FileName, tipoMapa);
}
}
private void ExecutarFixarBase()
{
if (FixacaoEmAndamento)
{
FixarBaseSolicitado?.Invoke(MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, AltitudeManual);
return;
}
if (MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual)
{
if (!LatitudeManual.HasValue || !LongitudeManual.HasValue || !AltitudeManual.HasValue)
{
System.Windows.MessageBox.Show(
"Preencha latitude, longitude e altitude para aplicar a posição manual da base.",
"Dados incompletos",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
}
StatusTexto = "Pronto para aplicar a posição manual da base.";
}
FixarBaseSolicitado?.Invoke(MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, AltitudeManual);
}
private void ExecutarAplicarOffset()
{
AplicarOffsetSolicitado?.Invoke(OffsetFrontalBaseCm, OffsetLateralBaseCm);
}
public void IniciarFixacao()
{
FixacaoEmAndamento = true;
ProgressoFixacao = 0;
StatusTexto = MetodoFixacaoSelecionado switch
{
MetodoFixacaoBase.Ntrip => "Iniciando fixação da base via NTRIP...",
MetodoFixacaoBase.SurveyIn => "Iniciando Survey-In da base...",
MetodoFixacaoBase.Manual => "Aplicando posição manual da base...",
_ => "Iniciando fixação da posição da base..."
};
}
public void AtualizarProgresso(double progresso, string status)
{
ProgressoFixacao = progresso;
StatusTexto = status;
}
public void FinalizarFixacao(bool sucesso, string? mensagem = null)
{
ExibirOffsets = sucesso;
FixacaoEmAndamento = false;
if (sucesso) ProgressoFixacao = 100;
StatusTexto = !string.IsNullOrWhiteSpace(mensagem)
? mensagem
: sucesso
? "Fixação da base concluída com sucesso."
: "Fixação da base encerrada.";
}
public void CancelarFixacao(string? mensagem = null)
{
FixacaoEmAndamento = false;
StatusTexto = mensagem ?? "Fixação da base cancelada.";
}
public void LimparCamposManuais()
{
LatitudeManualTexto = string.Empty;
LongitudeManualTexto = string.Empty;
AltitudeManualTexto = string.Empty;
LatitudeManual = null;
LongitudeManual = null;
AltitudeManual = null;
}
private void ExecutarUsarGnssMovel()
{
if (!PodeUsarGnssMovel)
return;
UsarGnssMovelSolicitado?.Invoke();
}
public void IniciarAlteracaoPapelGnss()
{
AlteracaoPapelGnssEmAndamento =
true;
StatusTexto =
"Configurando o GNSS para levantamento...";
}
public void FinalizarAlteracaoPapelGnss(bool sucesso, GnssPapelEstacao papel, string mensagem)
{
PapelGnssAtual =
papel;
AlteracaoPapelGnssEmAndamento =
false;
if (
papel !=
GnssPapelEstacao.BaseFixa
)
{
ExibirOffsets =
false;
}
StatusTexto =
mensagem;
}
public void AtualizarPapelGnss(GnssPapelEstacao papel)
{
PapelGnssAtual =
papel;
if (
papel !=
GnssPapelEstacao.BaseFixa
)
{
ExibirOffsets =
false;
}
}
private double? TryParseDouble(string? texto)
{
if (string.IsNullOrWhiteSpace(texto))
return null;
texto = texto.Trim().Replace(",", ".");
if (double.TryParse(texto, NumberStyles.Any, CultureInfo.InvariantCulture, out var valor))
return valor;
return null;
}
private void OnPropertyChanged(string nome)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
CommandManager.InvalidateRequerySuggested();
}
}
}