2025-02-03 19:54:39 +00:00
|
|
|
|
using AgroBase.Services;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
2025-02-04 17:50:42 +00:00
|
|
|
|
using System.Net;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
using static AgroBase.Models.Enums;
|
|
|
|
|
|
|
|
|
|
|
|
namespace AgroBase.Models
|
|
|
|
|
|
{
|
|
|
|
|
|
public class TrajetoriaMapaOperacaoModel
|
|
|
|
|
|
{
|
|
|
|
|
|
public TrajetoriaMapaOperacaoModel(List<List<GPSModel>> RuasMapa)
|
|
|
|
|
|
{
|
|
|
|
|
|
RuasPlantacao = new List<List<GPSModel>>(RuasMapa);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
#region PARAMETROS
|
|
|
|
|
|
|
|
|
|
|
|
public double DistanciaProjecaoRua { get; set; } = 0.8;
|
|
|
|
|
|
public static double DistanciaEntrePontos { get; set; } = 1.0;
|
|
|
|
|
|
public static double DistanciaEntrePontosCurva { get; set; } = 0.25;
|
|
|
|
|
|
private double DistanciaManobraEntreRuas { get; set; } = 3.0;
|
|
|
|
|
|
private const int RANGE_ATUALIZACAO = 100; // Define o tamanho da janela de pontos a atualizar
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
public DateTime UltimaAtualizacaoDados { get; set; } = DateTime.MinValue;
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public List<List<GPSModel>> RuasPlantacao { get; set; }
|
|
|
|
|
|
public List<List<GPSModel>> Corredores { get; set; }
|
2025-02-04 17:50:42 +00:00
|
|
|
|
public GPSModel PrimeiroPontoRuaMapa
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Verifica se o índice é válido e se a rua não está vazia
|
|
|
|
|
|
if (IdxCorredorAtual < RuasPlantacao.Count && RuasPlantacao[IdxCorredorAtual].Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return RuasPlantacao[IdxCorredorAtual][0]; // Acessa diretamente o primeiro ponto da rua
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return new GPSModel(); // Pode ser null se preferir
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
public GPSModel UltimoPontoRuaMapa
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Verifica se o índice é válido e se a rua não está vazia
|
|
|
|
|
|
if (IdxCorredorAtual < RuasPlantacao.Count && RuasPlantacao[IdxCorredorAtual].Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return RuasPlantacao[IdxCorredorAtual][RuasPlantacao.Count - 1]; // Acessa diretamente o ultimo ponto da rua
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new GPSModel(); // Pode ser null se preferir
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
public int ExtremoMaisProximoMapa
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
double distPP = GPSService.DistanciaEntrePontos(GPSService.UltimaLeitura, PrimeiroPontoRuaMapa);
|
|
|
|
|
|
double distUP = GPSService.DistanciaEntrePontos(GPSService.UltimaLeitura, UltimoPontoRuaMapa);
|
|
|
|
|
|
|
|
|
|
|
|
// 0 para mais próximo do primeiro ponto da rua (ENTRANDO)
|
|
|
|
|
|
// 1 para mais próximo do último ponto da rua (SAINDO)
|
|
|
|
|
|
return (distPP < distUP) ? 0 : 1;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private List<int> _corredoresNaoFinalizados;
|
|
|
|
|
|
public List<int> CorredoresNaoFinalizados
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _corredoresNaoFinalizados;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
private void AtualizarCorredoresNaoFinalizados()
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
var corredores = new HashSet<int>();
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
foreach (var ponto in _TrajetoriaFixa)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ponto.Visitado)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
corredores.Add(ponto.idxCorredor); // Adiciona apenas corredores com pontos não visitados
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
_corredoresNaoFinalizados = corredores.ToList();
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private List<double> CorredoresLarguras { get; set; }
|
|
|
|
|
|
public List<PontoTrajetoriaModel> _TrajetoriaFixa { get; set; }
|
|
|
|
|
|
public Dictionary<int, List<PontoTrajetoriaModel>> _Corredores { get; set; }
|
|
|
|
|
|
public List<GPSModel> TrajetoriaFixa => _TrajetoriaFixa.ConvertAll(x => x.Posicao);
|
|
|
|
|
|
public List<GPSModel> TrajetoriaDinamica
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Cria a lista com a última leitura do robô
|
|
|
|
|
|
var trajetoria = new List<GPSModel> { GPSService.UltimaLeitura };
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Se a trajetória fixa estiver vazia, retorna apenas a leitura atual
|
|
|
|
|
|
if (_TrajetoriaFixa.Count == 0)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return trajetoria;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
// Adiciona os pontos não visitados, já ordenados por idxPonto
|
|
|
|
|
|
foreach (var ponto in _TrajetoriaFixa)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
if (!ponto.Visitado)
|
|
|
|
|
|
{
|
|
|
|
|
|
trajetoria.Add(ponto.Posicao);
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
return trajetoria;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
public static double DistanciaMaximaEntreLeituras { get; private set; }
|
|
|
|
|
|
public void AtualizarDistanciaMaximaEntreLeituras(double velocidadeCarroMs)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
double distanciaMaxima = (velocidadeCarroMs / GPSService.TaxaAmostragemHz);
|
|
|
|
|
|
DistanciaMaximaEntreLeituras = distanciaMaxima;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AtualizarPropriedadesPontosTrajetoria()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_TrajetoriaFixa.Count == 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
// Define os limites da janela de atualização
|
|
|
|
|
|
int idxInicial = Math.Max(0, PontoAtual.idxPonto - RANGE_ATUALIZACAO / 2);
|
|
|
|
|
|
int idxFinal = Math.Min(_TrajetoriaFixa.Count, PontoAtual.idxPonto + RANGE_ATUALIZACAO / 2);
|
|
|
|
|
|
|
|
|
|
|
|
// Atualiza apenas os pontos dentro do intervalo definido
|
|
|
|
|
|
for (int i = idxInicial; i < idxFinal; i++)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
_TrajetoriaFixa[i].AtualizarPropriedades();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
public int IdxCorredorAtual
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return PontoAtual?.idxCorredor ?? 0;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public Enums.DirecaoCarroRua DirecaoCaminho
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return PontoAtual?.Direcao ?? Enums.DirecaoCarroRua.Parado;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public double AnguloMedioCorredor
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return GPSService.CalcularOrientacao(PontoAtual.Posicao, ProximoPonto.Posicao);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public double AnguloCaminho
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
GPSModel pontoComparar = ProximoPonto != null ? ProximoPonto.Posicao : PontoAtual.Posicao;
|
|
|
|
|
|
double angulo = GPSService.CalcularOrientacao(GPSService.UltimaLeitura, pontoComparar);
|
|
|
|
|
|
return angulo;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private double _distanciaEsquerda;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public double DistanciaEsquerda
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _distanciaEsquerda;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private double _distanciaDireita;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public double DistanciaDireita
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _distanciaDireita;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void AtualizarDistanciasLaterais()
|
|
|
|
|
|
{
|
|
|
|
|
|
_distanciaEsquerda = CalcularDistanciaLateral(true);
|
|
|
|
|
|
_distanciaDireita = CalcularDistanciaLateral(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
private double CalcularDistanciaLateral(bool ladoEsquerdo)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Verifica se o corredor atual existe
|
|
|
|
|
|
if (!_Corredores.ContainsKey(IdxCorredorAtual))
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
var pontosDoCorredor = _Corredores[IdxCorredorAtual];
|
|
|
|
|
|
if (pontosDoCorredor.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Pega o primeiro ponto do corredor atual
|
|
|
|
|
|
var pontoCorredor = pontosDoCorredor[0];
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Calcula as distâncias até os extremos da rua
|
|
|
|
|
|
double distPP = GPSService.DistanciaEntrePontos(pontoCorredor.Posicao, PrimeiroPontoRuaMapa);
|
|
|
|
|
|
double distUP = GPSService.DistanciaEntrePontos(pontoCorredor.Posicao, UltimoPontoRuaMapa);
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
int extremoInicial = (distPP < distUP) ? 0 : 1;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Determina a rua correta de acordo com o lado e a posição do extremo inicial
|
|
|
|
|
|
List<GPSModel> rua;
|
|
|
|
|
|
if (ladoEsquerdo)
|
|
|
|
|
|
{
|
|
|
|
|
|
rua = (extremoInicial == 0) ? RuasPlantacao[IdxCorredorAtual + 1] : RuasPlantacao[IdxCorredorAtual];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
rua = (extremoInicial == 0) ? RuasPlantacao[IdxCorredorAtual] : RuasPlantacao[IdxCorredorAtual + 1];
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Evita erro de índice (se for o último corredor, não há IdxCorredorAtual + 1)
|
|
|
|
|
|
int idxMax = RuasPlantacao.Count - 1;
|
|
|
|
|
|
int idxRua = Math.Min(IdxCorredorAtual + (ladoEsquerdo ? 1 : 0), idxMax);
|
|
|
|
|
|
rua = RuasPlantacao[idxRua];
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Calcula a menor distância entre o robô e a rua
|
|
|
|
|
|
double distancia = GPSService.CalcularMenorDistanciaAteTrecho(GPSService.UltimaLeitura, rua);
|
|
|
|
|
|
|
|
|
|
|
|
// Ajusta a largura do robô no cálculo final
|
|
|
|
|
|
double larguraAjuste = ladoEsquerdo ? VariaveisEquipamento.LarguraEsquerda : VariaveisEquipamento.LarguraDireita;
|
|
|
|
|
|
distancia -= (larguraAjuste / 100.0);
|
|
|
|
|
|
|
|
|
|
|
|
return distancia;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private PontoTrajetoriaModel _pontoAtual;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public PontoTrajetoriaModel PontoAtual
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _pontoAtual;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void DefinirPontoAtual()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_TrajetoriaFixa == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_pontoAtual = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Busca eficiente: percorre de trás para frente para achar o último visitado
|
|
|
|
|
|
for (int i = _TrajetoriaFixa.Count - 1; i >= 0; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_TrajetoriaFixa[i].Visitado)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
_pontoAtual = _TrajetoriaFixa[i];
|
|
|
|
|
|
return;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
_pontoAtual = null;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private PontoTrajetoriaModel _proximoPonto;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public PontoTrajetoriaModel ProximoPonto
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _proximoPonto;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void DefinirProximoPonto()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_TrajetoriaFixa == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_proximoPonto = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Busca eficiente: percorre do começo ao fim para achar o primeiro não visitado
|
|
|
|
|
|
for (int i = 0; i < _TrajetoriaFixa.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_TrajetoriaFixa[i].Visitado)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
_proximoPonto = _TrajetoriaFixa[i];
|
|
|
|
|
|
return;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
_proximoPonto = PontoAtual; // Se não houver pontos não visitados, retorna o último ponto visitado
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private bool _naMargemDoCorredor;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public bool NaMargemDoCorredor
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _naMargemDoCorredor;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
private void AtualizarNaMargemDoCorredor()
|
|
|
|
|
|
{
|
|
|
|
|
|
_naMargemDoCorredor = false;
|
|
|
|
|
|
foreach (var ponto in _TrajetoriaFixa)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ponto.NaMargem && ponto.PontoBorda)
|
|
|
|
|
|
{
|
|
|
|
|
|
_naMargemDoCorredor = true; // Paramos a busca assim que encontramos um ponto válido
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool _dentroCorredor;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public bool DentroCorredor
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _dentroCorredor;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void AtualizaDentroCorredor()
|
|
|
|
|
|
{
|
|
|
|
|
|
_dentroCorredor = false;
|
|
|
|
|
|
if (_Corredores == null || !_Corredores.ContainsKey(IdxCorredorAtual))
|
|
|
|
|
|
return;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Itera diretamente sem criar uma lista temporária
|
|
|
|
|
|
foreach (var ponto in _Corredores[IdxCorredorAtual])
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ponto.NaMargem && (ponto.Tipo == Enums.TipoPontoRua.Rua || ponto.PontoBorda))
|
|
|
|
|
|
{
|
|
|
|
|
|
_dentroCorredor = true;
|
|
|
|
|
|
return; // Encontramos um ponto válido, podemos sair
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private bool _manobrandoEntreRuas;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public bool ManobrandoEntreRuas
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
return _manobrandoEntreRuas;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
private void AtualizarManobrandoEntreRuas()
|
|
|
|
|
|
{
|
|
|
|
|
|
bool proximoAentrada = (ProximoPonto.PontoBorda || ProximoPonto.PontoLigacao) && ProximoPonto.DistanciaAtual < DistanciaManobraEntreRuas;
|
|
|
|
|
|
_manobrandoEntreRuas = (proximoAentrada && StatusAtual == StatusCarroMapa.Direcionando) || NaMargemDoCorredor;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
private Enums.StatusCarroMapa _statusAtual = Enums.StatusCarroMapa.Parado;
|
|
|
|
|
|
public Enums.StatusCarroMapa StatusAtual
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _statusAtual;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
private void AtualizarStatusAtual()
|
|
|
|
|
|
{
|
|
|
|
|
|
_statusAtual = Enums.StatusCarroMapa.Parado;
|
|
|
|
|
|
if (ProximoPonto != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!DentroCorredor && (PontoAtual.Tipo == TipoPontoRua.PosicaoRobo || PontoAtual.PontoLigacao || ProximoPonto.PontoLigacao))
|
|
|
|
|
|
{
|
|
|
|
|
|
_statusAtual = Enums.StatusCarroMapa.Direcionando;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (DentroCorredor && !NaMargemDoCorredor)
|
|
|
|
|
|
{
|
|
|
|
|
|
_statusAtual = Enums.StatusCarroMapa.CaminhandoRua;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (!DentroCorredor && (!PontoAtual.PontoLigacao && !ProximoPonto.PontoLigacao))
|
|
|
|
|
|
{
|
|
|
|
|
|
_statusAtual = Enums.StatusCarroMapa.Manobrando;
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
else if (_TrajetoriaFixa.Any(x => x.NaMargem && x.Tipo == Enums.TipoPontoRua.BordaEntrada))
|
|
|
|
|
|
{
|
|
|
|
|
|
_statusAtual = Enums.StatusCarroMapa.EntrandoRua;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else if (_TrajetoriaFixa.Any(x => x.NaMargem && x.Tipo == Enums.TipoPontoRua.BordaSaida))
|
|
|
|
|
|
{
|
|
|
|
|
|
_statusAtual = Enums.StatusCarroMapa.SaindoRua;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AtualizarDadosTrajetoria()
|
|
|
|
|
|
{
|
|
|
|
|
|
DefinirPontoAtual();
|
|
|
|
|
|
DefinirProximoPonto();
|
|
|
|
|
|
AtualizarDistanciasLaterais();
|
|
|
|
|
|
AtualizarNaMargemDoCorredor();
|
|
|
|
|
|
AtualizaDentroCorredor();
|
|
|
|
|
|
AtualizarManobrandoEntreRuas();
|
|
|
|
|
|
AtualizarStatusAtual();
|
|
|
|
|
|
AtualizarCorredoresNaoFinalizados();
|
|
|
|
|
|
|
|
|
|
|
|
double velocidadeCarroMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP);
|
|
|
|
|
|
AtualizarDistanciaMaximaEntreLeituras(velocidadeCarroMs);
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
|
|
|
|
|
public double DistanciaTotal { get; private set; }
|
|
|
|
|
|
public double DistanciaPercorrida
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
double percorrido = GPSService.DistanciaDoTrecho(Variaveis.OperacaoEmAndamento.GPSTrajetoria);
|
|
|
|
|
|
return percorrido;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public double DistanciaRestante
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
double restante = GPSService.DistanciaDoTrecho(TrajetoriaDinamica);
|
|
|
|
|
|
return restante;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public string TempoEstimadoOperacao(double velocidadeSemErvas, double velocidadeComErvas)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Conversão de velocidades para m/s
|
|
|
|
|
|
double velocidadeSemErvasMs = ((velocidadeSemErvas * 1000.0) / 3600.0) * 0.8; // 80%
|
|
|
|
|
|
double velocidadeComErvasMs = (velocidadeComErvas * 1000.0) / 3600.0;
|
|
|
|
|
|
|
|
|
|
|
|
// Supondo que metade do percurso tem ervas e a outra metade não tem
|
|
|
|
|
|
double distanciaComErvas = DistanciaTotal * VariaveisOperacao.PercentualComErvas;
|
|
|
|
|
|
double distanciaSemErvas = DistanciaTotal * VariaveisOperacao.PercentualSemErvas;
|
|
|
|
|
|
|
|
|
|
|
|
// Tempo em segundos para cada parte do percurso
|
|
|
|
|
|
double tempoSemErvas = velocidadeSemErvasMs > 0 ? distanciaSemErvas / velocidadeSemErvasMs : 0;
|
|
|
|
|
|
double tempoComErvas = velocidadeComErvasMs > 0 ? distanciaComErvas / velocidadeComErvasMs : 0;
|
|
|
|
|
|
|
|
|
|
|
|
// Tempo total em segundos
|
|
|
|
|
|
double tempoTotalSegundos = tempoSemErvas + tempoComErvas;
|
|
|
|
|
|
|
|
|
|
|
|
// Conversão para horas, minutos e segundos
|
|
|
|
|
|
TimeSpan tempoTotal = TimeSpan.FromSeconds(tempoTotalSegundos);
|
|
|
|
|
|
|
|
|
|
|
|
return $"{tempoTotal.Hours:D2}:{tempoTotal.Minutes:D2}:{tempoTotal.Seconds:D2}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public string TempoEstimadoRestante()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Velocidades em RPM
|
|
|
|
|
|
double velocidadeSemErvas = FuncoesMatematicas.CalculaVelocidadeRPM(Variaveis.OperacaoEmAndamento.Controle.RPM_Max) * 0.8;
|
|
|
|
|
|
double velocidadeComErvas = FuncoesMatematicas.CalculaVelocidadeRPM(Variaveis.OperacaoEmAndamento.Controle.RPM_Min);
|
|
|
|
|
|
|
|
|
|
|
|
// Conversão de velocidades para m/s
|
|
|
|
|
|
double velocidadeSemErvasMs = (velocidadeSemErvas * 1000) / 3600;
|
|
|
|
|
|
double velocidadeComErvasMs = (velocidadeComErvas * 1000) / 3600;
|
|
|
|
|
|
|
|
|
|
|
|
// Distâncias (em metros)
|
|
|
|
|
|
double distanciaRestante = DistanciaRestante;
|
|
|
|
|
|
|
|
|
|
|
|
// Calcular a distância restante sem ervas e com ervas
|
|
|
|
|
|
double distanciaSemErvasRestante = distanciaRestante * VariaveisOperacao.PercentualSemErvas;
|
|
|
|
|
|
double distanciaComErvasRestante = distanciaRestante * VariaveisOperacao.PercentualComErvas;
|
|
|
|
|
|
|
|
|
|
|
|
// Calcular o tempo restante para as áreas sem ervas e com ervas
|
|
|
|
|
|
double tempoRestanteSemErvas = distanciaSemErvasRestante / velocidadeSemErvasMs;
|
|
|
|
|
|
double tempoRestanteComErvas = distanciaComErvasRestante / velocidadeComErvasMs;
|
|
|
|
|
|
|
|
|
|
|
|
// Tempo total restante em segundos
|
|
|
|
|
|
double tempoTotalRestanteSegundos = tempoRestanteSemErvas + tempoRestanteComErvas;
|
|
|
|
|
|
|
|
|
|
|
|
// Conversão para horas, minutos e segundos
|
|
|
|
|
|
TimeSpan tempoTotalRestante = TimeSpan.FromSeconds(tempoTotalRestanteSegundos);
|
|
|
|
|
|
|
|
|
|
|
|
return $"{tempoTotalRestante.Hours:D2}:{tempoTotalRestante.Minutes:D2}:{tempoTotalRestante.Seconds:D2}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LoopAtualizaDados()
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
double dt = Math.Min((1.0 / GPSService.TaxaAmostragemHz), (UltimaAtualizacaoDados - GPSService.UltimaLeitura.Momento).TotalSeconds);
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
#region ATUALIZAR PONTOS VISITADOS
|
|
|
|
|
|
|
|
|
|
|
|
/*if (_TrajetoriaFixa.Any(x => x.NaMargem && !x.Visitado))
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
double velocidadeCarroMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP);
|
|
|
|
|
|
|
|
|
|
|
|
// Distância máxima percorrida entre leituras
|
|
|
|
|
|
double distanciaMaxima = (velocidadeCarroMs / GPSService.TaxaAmostragemHz);
|
|
|
|
|
|
|
|
|
|
|
|
double distanciaEntrePontos = PontoAtual.Tipo == TipoPontoRua.CruvaEntreCorredores ? DistanciaEntrePontosCurva : DistanciaEntrePontos;
|
|
|
|
|
|
|
|
|
|
|
|
// Quantidade de pontos que podem ser cobertos na margem
|
|
|
|
|
|
int pontosCobertos = (int)Math.Ceiling(distanciaMaxima / distanciaEntrePontos) * 2;
|
|
|
|
|
|
|
|
|
|
|
|
// Marcar como visitados todos os pontos dentro da margem
|
|
|
|
|
|
double limiteDistancia = pontosCobertos * distanciaEntrePontos;
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Melhor filtro: Seleciona diretamente os pontos não visitados e que estão na margem
|
|
|
|
|
|
var pontosParaAtualizar = _TrajetoriaFixa
|
|
|
|
|
|
.Where(x => x.NaMargem && !x.Visitado && x.DistanciaTrajeto <= limiteDistancia)
|
|
|
|
|
|
.Take(pontosCobertos)
|
|
|
|
|
|
.ToList();
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
// Atualiza diretamente os pontos visitados
|
|
|
|
|
|
foreach (var ponto in pontosParaAtualizar)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
ponto.Visitado = true;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
double velocidadeCarroMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP);
|
|
|
|
|
|
AtualizarDistanciaMaximaEntreLeituras(velocidadeCarroMs);
|
|
|
|
|
|
|
|
|
|
|
|
AtualizarPropriedadesPontosTrajetoria();
|
|
|
|
|
|
|
|
|
|
|
|
AtualizarDadosTrajetoria();
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
UltimaAtualizacaoDados = GPSService.UltimaLeitura.Momento;
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
|
|
|
|
|
|
|
|
|
|
|
|
GPSService.AtualizarTrajetoriaDinamica();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
private (List<List<GPSModel>>, List<double>) ProjetarCorredores()
|
|
|
|
|
|
{
|
|
|
|
|
|
var corredores = new List<List<GPSModel>>();
|
|
|
|
|
|
var larguras = new List<double>();
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < RuasPlantacao.Count - 1; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var rua1 = RuasPlantacao[i];
|
|
|
|
|
|
var rua2 = RuasPlantacao[i + 1];
|
|
|
|
|
|
|
|
|
|
|
|
// Garantir que as ruas tenham o mesmo número de pontos
|
|
|
|
|
|
if (rua1.Count != rua2.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (rua1.Count > rua2.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
rua2 = GPSService.InterpolarRota(rua2, rua1.Count);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
rua1 = GPSService.InterpolarRota(rua1, rua2.Count);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var corredor = new List<GPSModel>();
|
|
|
|
|
|
|
|
|
|
|
|
// Calcular pontos médios entre as duas ruas e interpolar a cada 25 cm
|
|
|
|
|
|
for (int j = 0; j < rua1.Count - 1; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var ponto1Rua1 = rua1[j];
|
|
|
|
|
|
var ponto2Rua1 = rua1[j + 1];
|
|
|
|
|
|
var ponto1Rua2 = rua2[j];
|
|
|
|
|
|
var ponto2Rua2 = rua2[j + 1];
|
|
|
|
|
|
|
|
|
|
|
|
var pontoMedioInicial = GPSService.PontoMedio(ponto1Rua1, ponto1Rua2);
|
|
|
|
|
|
var pontoMedioFinal = GPSService.PontoMedio(ponto2Rua1, ponto2Rua2);
|
|
|
|
|
|
|
|
|
|
|
|
var distancia = GPSService.DistanciaEntrePontos(pontoMedioInicial, pontoMedioFinal);
|
|
|
|
|
|
|
|
|
|
|
|
int numInterpolacoes = (int)(distancia / DistanciaEntrePontos);
|
|
|
|
|
|
|
|
|
|
|
|
for (int k = 0; k <= numInterpolacoes; k++)
|
|
|
|
|
|
{
|
|
|
|
|
|
double t = k / (double)numInterpolacoes;
|
|
|
|
|
|
var pontoInterpolado = GPSService.InterpolarPonto(pontoMedioInicial, pontoMedioFinal, t);
|
|
|
|
|
|
corredor.Add(pontoInterpolado);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Remover pontos que estão a menos de 25 cm de distância
|
|
|
|
|
|
corredor = RemoverPontosMuitoProximos(corredor, DistanciaEntrePontos);
|
|
|
|
|
|
|
|
|
|
|
|
// Calcular largura média entre as duas ruas
|
|
|
|
|
|
double larguraCorredor = CalcularLarguraMediaDoCorredor(rua1, rua2);
|
|
|
|
|
|
|
|
|
|
|
|
corredores.Add(corredor);
|
|
|
|
|
|
larguras.Add(larguraCorredor);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (corredores, larguras);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Método auxiliar para remover pontos muito próximos
|
|
|
|
|
|
private List<GPSModel> RemoverPontosMuitoProximos(List<GPSModel> pontos, double distanciaMinima)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pontos == null || pontos.Count == 0)
|
|
|
|
|
|
return pontos;
|
|
|
|
|
|
|
|
|
|
|
|
var resultado = new List<GPSModel> { pontos[0] }; // Sempre incluir o primeiro ponto
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < pontos.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var distancia = GPSService.DistanciaEntrePontos(resultado.Last(), pontos[i]);
|
|
|
|
|
|
if (distancia >= distanciaMinima)
|
|
|
|
|
|
{
|
|
|
|
|
|
resultado.Add(pontos[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return resultado;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static double CalcularLarguraMediaDoCorredor(List<GPSModel> rua1, List<GPSModel> rua2)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. Interpolar as duas ruas para garantir pontos uniformemente distribuídos
|
|
|
|
|
|
List<GPSModel> rua1Interpolada = GPSService.InterpolarRota(rua1, Convert.ToInt32(GPSService.DistanciaDoTrecho(rua1)));
|
|
|
|
|
|
List<GPSModel> rua2Interpolada = GPSService.InterpolarRota(rua2, Convert.ToInt32(GPSService.DistanciaDoTrecho(rua2)));
|
|
|
|
|
|
|
|
|
|
|
|
double somaDistancias = 0;
|
|
|
|
|
|
int totalPontos = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Para cada ponto da rua1 interpolada, encontrar o mais próximo na rua2 interpolada
|
|
|
|
|
|
foreach (var ponto1 in rua1Interpolada)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pontoMaisProximo = rua2Interpolada.OrderBy(ponto2 => GPSService.DistanciaEntrePontos(ponto1, ponto2)).First();
|
|
|
|
|
|
|
|
|
|
|
|
double distancia = GPSService.DistanciaEntrePontos(ponto1, pontoMaisProximo);
|
|
|
|
|
|
|
|
|
|
|
|
somaDistancias += distancia;
|
|
|
|
|
|
totalPontos++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Retorna a largura média do corredor
|
|
|
|
|
|
return totalPontos > 0 ? somaDistancias / totalPontos : 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public double DistanciaEntreRuas(List<List<GPSModel>> ruas)
|
|
|
|
|
|
{
|
|
|
|
|
|
double distanciaTotal = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (ruas.Count < 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Se houver menos de duas ruas, não há distância a calcular
|
|
|
|
|
|
return distanciaTotal;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double menorDistancia = double.MaxValue;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ruas.Count - 1; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<GPSModel> ruaAtual = ruas[i];
|
|
|
|
|
|
List<GPSModel> proximaRua = ruas[i + 1];
|
|
|
|
|
|
|
|
|
|
|
|
// Calcule a distância entre as duas ruas (rua atual e próxima rua)
|
|
|
|
|
|
// Aqui você pode usar o método GPSService.CalcularDistanciaPontos
|
|
|
|
|
|
// ou uma função personalizada para calcular a distância entre as ruas
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (GPSModel pontoAtual in ruaAtual)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (GPSModel pontoProxima in proximaRua)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Calcular a distância entre pontoAtual e pontoProxima
|
|
|
|
|
|
double distancia = GPSService.DistanciaEntrePontos(pontoAtual, pontoProxima);
|
|
|
|
|
|
|
|
|
|
|
|
// Verifique se esta é a menor distância
|
|
|
|
|
|
if (distancia < menorDistancia)
|
|
|
|
|
|
{
|
|
|
|
|
|
menorDistancia = distancia;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Adiciona a menor distância encontrada à distância total
|
|
|
|
|
|
distanciaTotal += menorDistancia;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double distanciaMedia = distanciaTotal / ruas.Count();
|
|
|
|
|
|
|
|
|
|
|
|
return menorDistancia;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<PontoTrajetoriaModel> ProjetarTrajetoriaFixa()
|
|
|
|
|
|
{
|
|
|
|
|
|
List<PontoTrajetoriaModel> _trajetoriaFixa = new List<PontoTrajetoriaModel>();
|
|
|
|
|
|
(Corredores, CorredoresLarguras) = ProjetarCorredores();
|
|
|
|
|
|
|
|
|
|
|
|
double larguraCorredorPadrao = 1.5;
|
|
|
|
|
|
Enums.DirecaoCarroRua direcaoAtual = ExtremoMaisProximoMapa == 0 ? Enums.DirecaoCarroRua.Ida : Enums.DirecaoCarroRua.Volta;
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
PontoTrajetoriaModel PontoRobo = new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
idxCorredor = 0,
|
|
|
|
|
|
idxPonto = _trajetoriaFixa.Count(),
|
|
|
|
|
|
idxPontoCorredor = 0,
|
|
|
|
|
|
Posicao = GPSService.UltimaLeitura,
|
|
|
|
|
|
Direcao = direcaoAtual,
|
|
|
|
|
|
Orientacao = 0,
|
|
|
|
|
|
Visitado = true,
|
|
|
|
|
|
LarguraCorredor = 1.0
|
|
|
|
|
|
};
|
|
|
|
|
|
_trajetoriaFixa.Add(PontoRobo);
|
|
|
|
|
|
|
|
|
|
|
|
for (int idx = 0; idx < Corredores.Count(); idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<GPSModel> CorredorAtual = Corredores[idx];
|
|
|
|
|
|
|
|
|
|
|
|
if (idx % 2 != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
CorredorAtual.Reverse();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double anguloProjetar1 = GPSService.CalcularOrientacao(CorredorAtual.Skip(1).First(), CorredorAtual.First());
|
|
|
|
|
|
GPSModel PrimeiroPonto = GPSService.ProjetarPontoDeslocado(CorredorAtual.First(), DistanciaProjecaoRua, anguloProjetar1);
|
|
|
|
|
|
double anguloProjetar2 = GPSService.CalcularOrientacao(CorredorAtual.Skip(CorredorAtual.Count() - 2).First(), CorredorAtual.Last());
|
|
|
|
|
|
GPSModel UltimoPonto = GPSService.ProjetarPontoDeslocado(CorredorAtual.Last(), DistanciaProjecaoRua, anguloProjetar2);
|
|
|
|
|
|
|
|
|
|
|
|
var ultimoPontoTrajetoria = _trajetoriaFixa.LastOrDefault();
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
PontoTrajetoriaModel PontoInicial = new PontoTrajetoriaModel(TipoPontoRua.LigacaoEntrada)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
idxCorredor = idx,
|
|
|
|
|
|
idxPonto = _trajetoriaFixa.Count(),
|
|
|
|
|
|
idxPontoCorredor = _trajetoriaFixa.Count(x => x.idxCorredor == idx),
|
|
|
|
|
|
Posicao = PrimeiroPonto,
|
|
|
|
|
|
Direcao = direcaoAtual,
|
|
|
|
|
|
Orientacao = GPSService.CalcularOrientacao(ultimoPontoTrajetoria.Posicao, PrimeiroPonto),
|
|
|
|
|
|
Visitado = false,
|
|
|
|
|
|
LarguraCorredor = larguraCorredorPadrao
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
bool PontoInicialAdicionado = false;
|
|
|
|
|
|
// Criar curva suave para ligacao dos corredores
|
|
|
|
|
|
if (idx > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Verifica se a distância entre o ultimo ponto da rua anterior e o primeiro ponto da nova rua é curto o bastante para gerar a curva de manobra
|
|
|
|
|
|
double distancia = GPSService.DistanciaEntrePontos(ultimoPontoTrajetoria.Posicao, PontoInicial.Posicao);
|
|
|
|
|
|
bool distanciaMinima = distancia < DistanciaManobraEntreRuas;
|
|
|
|
|
|
|
|
|
|
|
|
if (distanciaMinima)
|
|
|
|
|
|
{
|
|
|
|
|
|
int pontosAdicionr = Convert.ToInt32(CorredoresLarguras[idx] / DistanciaEntrePontosCurva);
|
|
|
|
|
|
bool CurvaParaEsquerda = (ExtremoMaisProximoMapa == 0 && direcaoAtual == DirecaoCarroRua.Volta) || (ExtremoMaisProximoMapa == 1 && direcaoAtual == DirecaoCarroRua.Ida);
|
|
|
|
|
|
GPSModel P0 = CalcularPontoControle(_trajetoriaFixa[_trajetoriaFixa.Count() - 2].Posicao, ultimoPontoTrajetoria.Posicao, PrimeiroPonto, DistanciaProjecaoRua);
|
|
|
|
|
|
List<GPSModel> CurvaConexao = GerarCurvaConexao(ultimoPontoTrajetoria.Posicao, PrimeiroPonto, P0, pontosAdicionr);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var ponto in CurvaConexao)
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
bool pontoLigacao = CurvaConexao.IndexOf(ponto) == CurvaConexao.Count() - 1;
|
|
|
|
|
|
_trajetoriaFixa.Add(new PontoTrajetoriaModel(pontoLigacao ? TipoPontoRua.LigacaoEntrada : TipoPontoRua.CruvaEntreCorredores)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
idxCorredor = idx,
|
|
|
|
|
|
idxPonto = _trajetoriaFixa.Count(),
|
|
|
|
|
|
idxPontoCorredor = _trajetoriaFixa.Count(x => x.idxCorredor == idx),
|
|
|
|
|
|
Posicao = ponto,
|
2025-02-04 17:50:42 +00:00
|
|
|
|
Direcao = pontoLigacao ? direcaoAtual : DirecaoCarroRua.Manobra,
|
2025-02-03 19:54:39 +00:00
|
|
|
|
Orientacao = GPSService.CalcularOrientacao(_trajetoriaFixa.Last().Posicao, ponto),
|
|
|
|
|
|
Visitado = false,
|
|
|
|
|
|
LarguraCorredor = larguraCorredorPadrao
|
|
|
|
|
|
});
|
2025-02-04 17:50:42 +00:00
|
|
|
|
pontoLigacao = false;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
PontoInicialAdicionado = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!PontoInicialAdicionado)
|
|
|
|
|
|
{
|
|
|
|
|
|
_trajetoriaFixa.Add(PontoInicial);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (GPSModel pontoAtual in CorredorAtual)
|
|
|
|
|
|
{
|
|
|
|
|
|
int idxPonto = CorredorAtual.IndexOf(pontoAtual);
|
|
|
|
|
|
bool bordaEntrada = idxPonto == 0;
|
|
|
|
|
|
bool bordaSaida = idxPonto == CorredorAtual.Count() - 1;
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
PontoTrajetoriaModel PontoTrajetoria = new PontoTrajetoriaModel(bordaEntrada ? TipoPontoRua.BordaEntrada : bordaSaida ? TipoPontoRua.BordaSaida : TipoPontoRua.Rua)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
idxCorredor = idx,
|
|
|
|
|
|
idxPonto = _trajetoriaFixa.Count(),
|
|
|
|
|
|
idxPontoCorredor = _trajetoriaFixa.Count(x => x.idxCorredor == idx),
|
|
|
|
|
|
Posicao = pontoAtual,
|
|
|
|
|
|
Direcao = direcaoAtual,
|
|
|
|
|
|
Orientacao = GPSService.CalcularOrientacao(_trajetoriaFixa.Last().Posicao, pontoAtual),
|
|
|
|
|
|
Visitado = false,
|
|
|
|
|
|
LarguraCorredor = CorredoresLarguras[idx]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
_trajetoriaFixa.Add(PontoTrajetoria);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
PontoTrajetoriaModel PontoFinal = new PontoTrajetoriaModel(TipoPontoRua.LigacaoSaida)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
|
|
|
|
|
idxCorredor = idx,
|
|
|
|
|
|
idxPonto = _trajetoriaFixa.Count(),
|
|
|
|
|
|
idxPontoCorredor = _trajetoriaFixa.Count(x => x.idxCorredor == idx),
|
|
|
|
|
|
Posicao = UltimoPonto,
|
|
|
|
|
|
Direcao = direcaoAtual,
|
|
|
|
|
|
Orientacao = GPSService.CalcularOrientacao(_trajetoriaFixa.Last().Posicao, UltimoPonto),
|
|
|
|
|
|
Visitado = false,
|
|
|
|
|
|
LarguraCorredor = larguraCorredorPadrao
|
|
|
|
|
|
};
|
|
|
|
|
|
_trajetoriaFixa.Add(PontoFinal);
|
|
|
|
|
|
|
|
|
|
|
|
direcaoAtual = direcaoAtual == Enums.DirecaoCarroRua.Ida ? Enums.DirecaoCarroRua.Volta : Enums.DirecaoCarroRua.Ida;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_TrajetoriaFixa = new List<PontoTrajetoriaModel>(_trajetoriaFixa);
|
2025-02-04 17:50:42 +00:00
|
|
|
|
_Corredores = _TrajetoriaFixa.GroupBy(x => x.idxCorredor).ToDictionary(g => g.Key, g => g.ToList());
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
|
|
|
|
|
DistanciaTotal = GPSService.DistanciaDoTrecho(_trajetoriaFixa.Select(x => x.Posicao).ToList());
|
|
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
AtualizarDadosTrajetoria();
|
|
|
|
|
|
AtualizarPropriedadesPontosTrajetoria();
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
return _TrajetoriaFixa;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static GPSModel CalcularPontoControle(GPSModel penultimoPontoRuaAtual, GPSModel ultimoPontoRuaAtual, GPSModel primeiroPontoProximaRua, double distancia)
|
|
|
|
|
|
{
|
|
|
|
|
|
double anguloCurva = GPSService.CalcularOrientacao(penultimoPontoRuaAtual, ultimoPontoRuaAtual);
|
|
|
|
|
|
double angulo = GPSService.CalcularOrientacao(ultimoPontoRuaAtual, primeiroPontoProximaRua);
|
|
|
|
|
|
double lat = (ultimoPontoRuaAtual.Latitude + primeiroPontoProximaRua.Latitude) / 2;
|
|
|
|
|
|
double lon = (ultimoPontoRuaAtual.Longitude + primeiroPontoProximaRua.Longitude) / 2;
|
|
|
|
|
|
GPSModel pontoMedio = new GPSModel()
|
|
|
|
|
|
{
|
|
|
|
|
|
Latitude = lat,
|
|
|
|
|
|
Longitude = lon,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
bool ParaDentro = (angulo - anguloCurva) > 0;
|
|
|
|
|
|
|
|
|
|
|
|
// Ajuste o ângulo com base na direção da curva
|
|
|
|
|
|
double ajusteAngulo = (ParaDentro ? 270 : 90);
|
|
|
|
|
|
|
|
|
|
|
|
// Projetar um ponto a uma certa distância na direção ajustada
|
|
|
|
|
|
return GPSService.ProjetarPontoDeslocado(pontoMedio, distancia, angulo + ajusteAngulo);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static List<GPSModel> GerarCurvaConexao(GPSModel ultimoPontoRuaAtual, GPSModel primeiroPontoProximaRua, GPSModel pontoControle, int numeroPontos)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<GPSModel> pontosCurva = new List<GPSModel>();
|
|
|
|
|
|
for (int i = 0; i <= numeroPontos; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
double t = i / (double)numeroPontos;
|
|
|
|
|
|
pontosCurva.Add(CalcularBezierQuadratica(ultimoPontoRuaAtual, pontoControle, primeiroPontoProximaRua, t));
|
|
|
|
|
|
}
|
|
|
|
|
|
return pontosCurva;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static GPSModel CalcularBezierQuadratica(GPSModel p0, GPSModel p1, GPSModel p2, double t)
|
|
|
|
|
|
{
|
|
|
|
|
|
double x = Math.Pow(1 - t, 2) * p0.Latitude + 2 * (1 - t) * t * p1.Latitude + Math.Pow(t, 2) * p2.Latitude;
|
|
|
|
|
|
double y = Math.Pow(1 - t, 2) * p0.Longitude + 2 * (1 - t) * t * p1.Longitude + Math.Pow(t, 2) * p2.Longitude;
|
|
|
|
|
|
return new GPSModel { Latitude = x, Longitude = y };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void AjustarTrajetoriaParaDesvio(Obstaculo obstaculo)
|
|
|
|
|
|
{
|
|
|
|
|
|
GPSModel posicaoAtual = GPSService.UltimaLeitura;
|
|
|
|
|
|
|
|
|
|
|
|
double distanciaObstaculo = ((double)obstaculo.DistanciaMedia_mm / 1000);
|
|
|
|
|
|
double larguraObstaculo = ((double)obstaculo.Largura_mm / 1000);
|
|
|
|
|
|
double anguloCaminho = AnguloCaminho;
|
|
|
|
|
|
double anguloDesvioInicial = anguloCaminho + obstaculo.AnguloParaDesvio;
|
|
|
|
|
|
double anguloDesvioFinal = anguloCaminho - obstaculo.AnguloParaDesvio;
|
|
|
|
|
|
|
|
|
|
|
|
GPSModel ponto1 = GPSService.GerarPontoDeslocado(posicaoAtual, anguloDesvioInicial, distanciaObstaculo);
|
|
|
|
|
|
GPSModel ponto2 = GPSService.GerarPontoDeslocado(ponto1, anguloCaminho, larguraObstaculo);
|
|
|
|
|
|
GPSModel ponto3 = GPSService.GerarPontoDeslocado(ponto2, anguloDesvioFinal, distanciaObstaculo);
|
|
|
|
|
|
List<GPSModel> lista = new List<GPSModel>()
|
|
|
|
|
|
{
|
|
|
|
|
|
ponto1,
|
|
|
|
|
|
ponto2,
|
|
|
|
|
|
ponto3
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var idxRemover = EncontrarIndiceFinalDesvio(TrajetoriaDinamica, ponto3, distanciaObstaculo);
|
|
|
|
|
|
TrajetoriaDinamica.RemoveRange(1, idxRemover);
|
|
|
|
|
|
TrajetoriaDinamica.InsertRange(1, lista);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int EncontrarIndiceFinalDesvio(List<GPSModel> trajetoria, GPSModel ultimoWaypointDesvio, double distanciaSeguranca)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Encontrar o índice do waypoint que está imediatamente após o retorno do desvio
|
|
|
|
|
|
// Este é um método simplificado. A lógica exata pode variar dependendo da precisão necessária.
|
|
|
|
|
|
double distanciaAnterior = 0;
|
|
|
|
|
|
for (int i = 0; i < trajetoria.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
double distancia = GPSService.DistanciaEntrePontos(trajetoria[i], ultimoWaypointDesvio);
|
|
|
|
|
|
bool aumentando = distancia > distanciaAnterior;
|
|
|
|
|
|
distanciaAnterior = distancia;
|
|
|
|
|
|
if (distancia < distanciaSeguranca)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (aumentando)
|
|
|
|
|
|
{
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0; // Se não encontrar, assuma o último waypoint
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class PontoTrajetoriaModel
|
|
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
public int idxCorredor { get; set; }
|
|
|
|
|
|
public int idxPonto { get; set; }
|
|
|
|
|
|
public int idxPontoCorredor { get; set; }
|
2025-02-03 19:54:39 +00:00
|
|
|
|
public GPSModel Posicao { get; set; }
|
|
|
|
|
|
public double Orientacao { get; set; }
|
|
|
|
|
|
public Enums.DirecaoCarroRua Direcao { get; set; }
|
2025-02-04 17:50:42 +00:00
|
|
|
|
public Enums.TipoPontoRua Tipo { get; }
|
|
|
|
|
|
public double LarguraCorredor { get; set; }
|
|
|
|
|
|
public bool Visitado { get; set; } = false;
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Agora, propriedades podem ser atualizadas com `set; private`
|
|
|
|
|
|
public double OrientacaoAtual { get; private set; }
|
|
|
|
|
|
public double OrientacaoAnterior { get; private set; }
|
|
|
|
|
|
public double DistanciaTrajeto { get; private set; }
|
|
|
|
|
|
public double DistanciaAtual { get; private set; }
|
|
|
|
|
|
public double DistanciaAnterior { get; private set; }
|
|
|
|
|
|
public bool Aproximando { get; private set; }
|
|
|
|
|
|
public bool NaMargem { get; private set; }
|
|
|
|
|
|
public bool PontoBorda { get; private set; }
|
|
|
|
|
|
public bool PontoLigacao { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Construtor: Calcula propriedades fixas uma única vez
|
|
|
|
|
|
public PontoTrajetoriaModel(TipoPontoRua tipo)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
Tipo = tipo;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
PontoBorda = Tipo == Enums.TipoPontoRua.BordaEntrada || Tipo == Enums.TipoPontoRua.BordaSaida;
|
|
|
|
|
|
PontoLigacao = Tipo == Enums.TipoPontoRua.LigacaoEntrada || Tipo == Enums.TipoPontoRua.LigacaoSaida;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
public void AtualizarPropriedades()
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
AtualizarDistanciaAtual();
|
|
|
|
|
|
AtualizarDistanciaAnterior();
|
|
|
|
|
|
AtualizarOrientacaoAtual();
|
|
|
|
|
|
AtualizarOrientacaoAnterior();
|
|
|
|
|
|
AtualizarNaMargem();
|
|
|
|
|
|
AtualizarAproximando();
|
|
|
|
|
|
AtualizarDistanciaTrajeto();
|
|
|
|
|
|
AtualizarVisitado();
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private void AtualizarVisitado()
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
if (Visitado) return; // Se já foi visitado, não faz nada
|
|
|
|
|
|
|
|
|
|
|
|
double distanciaEntrePontos =
|
|
|
|
|
|
Tipo == TipoPontoRua.CruvaEntreCorredores ? (TrajetoriaMapaOperacaoModel.DistanciaEntrePontosCurva * 1.0) :
|
|
|
|
|
|
TrajetoriaMapaOperacaoModel.DistanciaEntrePontos;
|
|
|
|
|
|
|
|
|
|
|
|
// Define o limite de distância para considerar o ponto como visitado
|
|
|
|
|
|
double limiteDistancia = Math.Ceiling(TrajetoriaMapaOperacaoModel.DistanciaMaximaEntreLeituras / distanciaEntrePontos) * 2 * distanciaEntrePontos;
|
|
|
|
|
|
|
|
|
|
|
|
// Se o ponto está dentro da margem e dentro do limite de distância, marca como visitado
|
|
|
|
|
|
if (NaMargem && DistanciaTrajeto <= limiteDistancia)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
Visitado = true;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private void AtualizarOrientacaoAtual()
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
OrientacaoAtual = GPSService.CalcularOrientacao(GPSService.UltimaLeitura, Posicao);
|
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
2025-02-04 17:50:42 +00:00
|
|
|
|
private void AtualizarOrientacaoAnterior()
|
|
|
|
|
|
{
|
|
|
|
|
|
OrientacaoAnterior = GPSService.CalcularOrientacao(GPSService.PenultimaLeitura, Posicao);
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private void AtualizarDistanciaTrajeto()
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
var pontoAtual = Variaveis.OperacaoEmAndamento.Trajetoria.PontoAtual;
|
|
|
|
|
|
int idxPontoAtual = pontoAtual.idxPonto;
|
|
|
|
|
|
int qtdPontos = Math.Abs(idxPonto - idxPontoAtual) + 1; // Sempre positivo
|
|
|
|
|
|
|
|
|
|
|
|
if (qtdPontos == 1)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
DistanciaTrajeto = pontoAtual.Aproximando ? pontoAtual.DistanciaAtual : -pontoAtual.DistanciaAtual;
|
|
|
|
|
|
return;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
// ✅ Definimos corretamente o intervalo da trajetória
|
|
|
|
|
|
int idxInicio = Math.Min(idxPontoAtual, idxPonto);
|
|
|
|
|
|
int idxFim = Math.Max(idxPontoAtual, idxPonto);
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Pega os pontos corretos, independentemente de direção
|
|
|
|
|
|
List<GPSModel> trecho = Variaveis.OperacaoEmAndamento.Trajetoria._TrajetoriaFixa
|
|
|
|
|
|
.Skip(idxInicio)
|
|
|
|
|
|
.Take(qtdPontos)
|
|
|
|
|
|
.ToList()
|
|
|
|
|
|
.ConvertAll(x => x.Posicao);
|
|
|
|
|
|
|
|
|
|
|
|
double distancia = GPSService.DistanciaDoTrecho(trecho);
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Agora decidimos se devemos somar ou subtrair a distância do ponto atual
|
|
|
|
|
|
double distanciaP0 = pontoAtual.Aproximando ? pontoAtual.DistanciaAtual : -pontoAtual.DistanciaAtual;
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Se o ponto está atrás, invertemos a distância final
|
|
|
|
|
|
if (idxPonto < idxPontoAtual)
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
distanciaP0 *= -1;
|
|
|
|
|
|
distancia *= -1;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
DistanciaTrajeto = distancia + distanciaP0;
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
private void AtualizarDistanciaAtual()
|
2025-02-03 19:54:39 +00:00
|
|
|
|
{
|
2025-02-04 17:50:42 +00:00
|
|
|
|
DistanciaAtual = GPSService.DistanciaEntrePontos(GPSService.UltimaLeitura, Posicao);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AtualizarDistanciaAnterior()
|
|
|
|
|
|
{
|
|
|
|
|
|
DistanciaAnterior = GPSService.DistanciaEntrePontos(GPSService.PenultimaLeitura, Posicao);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AtualizarAproximando()
|
|
|
|
|
|
{
|
|
|
|
|
|
// ✅ Agora verificamos tudo de uma vez sem variáveis intermediárias
|
|
|
|
|
|
Aproximando = Math.Abs(OrientacaoAtual - OrientacaoAnterior) <= 10.0
|
|
|
|
|
|
&& DistanciaAtual < DistanciaAnterior
|
|
|
|
|
|
&& Math.Abs(OrientacaoAtual - OrientacaoAnterior) < 90.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AtualizarNaMargem()
|
|
|
|
|
|
{
|
|
|
|
|
|
NaMargem = DistanciaAtual < (LarguraCorredor / 1.2);
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-04 17:50:42 +00:00
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
|
}
|