ajustes carregamento do mapa, distancia antecipar manobra e calculo erro lateral

This commit is contained in:
Diego Freitas 2026-03-30 13:24:41 -03:00
parent 13e20264fd
commit 2a907f8d5e
10 changed files with 218 additions and 62 deletions

View File

@ -45,6 +45,7 @@
this.nudTemposalvarlog = new System.Windows.Forms.NumericUpDown();
this.lblTemposalvarlog = new System.Windows.Forms.Label();
this.gpbP_Atu = new System.Windows.Forms.GroupBox();
this.chbPulverizadorAutomatico = new System.Windows.Forms.CheckBox();
this.nudAtuarem = new System.Windows.Forms.NumericUpDown();
this.lblAtuarem = new System.Windows.Forms.Label();
this.nudQtdCameras = new System.Windows.Forms.NumericUpDown();
@ -52,6 +53,7 @@
this.nudQtdBicos = new System.Windows.Forms.NumericUpDown();
this.lblQtdBicos = new System.Windows.Forms.Label();
this.gpbP_Dir = new System.Windows.Forms.GroupBox();
this.chbDirecionalAutomatico = new System.Windows.Forms.CheckBox();
this.lblAngulomax = new System.Windows.Forms.Label();
this.nudAnguloMinimo = new System.Windows.Forms.NumericUpDown();
this.nudVelocidadeMP = new System.Windows.Forms.NumericUpDown();
@ -59,6 +61,7 @@
this.nudAnguloMaximo = new System.Windows.Forms.NumericUpDown();
this.lblAngulomin = new System.Windows.Forms.Label();
this.gpbP_Mov = new System.Windows.Forms.GroupBox();
this.chbMovimentacaoAutomatica = new System.Windows.Forms.CheckBox();
this.nudVelocidadeComErvas = new System.Windows.Forms.NumericUpDown();
this.lblKmhCErvas = new System.Windows.Forms.Label();
this.lblVelocidadeComErvas = new System.Windows.Forms.Label();
@ -85,9 +88,9 @@
this.nudCapacidadereservatorio = new System.Windows.Forms.NumericUpDown();
this.lblUnCapcaidadereservatorio = new System.Windows.Forms.Label();
this.lblCapacidadereservatorio = new System.Windows.Forms.Label();
this.chbPulverizadorAutomatico = new System.Windows.Forms.CheckBox();
this.chbDirecionalAutomatico = new System.Windows.Forms.CheckBox();
this.chbMovimentacaoAutomatica = new System.Windows.Forms.CheckBox();
this.lblAnteciparManobra = new System.Windows.Forms.Label();
this.txtAnteciparManobraM = new System.Windows.Forms.TextBox();
this.lblAnteciparManobraM = new System.Windows.Forms.Label();
this.gpbModulos.SuspendLayout();
this.gpbP_Knt.SuspendLayout();
this.gpbP_Sen.SuspendLayout();
@ -162,6 +165,9 @@
//
// gpbP_Knt
//
this.gpbP_Knt.Controls.Add(this.lblAnteciparManobraM);
this.gpbP_Knt.Controls.Add(this.txtAnteciparManobraM);
this.gpbP_Knt.Controls.Add(this.lblAnteciparManobra);
this.gpbP_Knt.Controls.Add(this.chbMatrizCusto);
this.gpbP_Knt.Controls.Add(this.chbImuParadaInclinacao);
this.gpbP_Knt.Controls.Add(this.chbOakParadaObstaculo);
@ -176,10 +182,11 @@
// chbMatrizCusto
//
this.chbMatrizCusto.AutoSize = true;
this.chbMatrizCusto.Location = new System.Drawing.Point(10, 94);
this.chbMatrizCusto.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F);
this.chbMatrizCusto.Location = new System.Drawing.Point(10, 100);
this.chbMatrizCusto.Margin = new System.Windows.Forms.Padding(6);
this.chbMatrizCusto.Name = "chbMatrizCusto";
this.chbMatrizCusto.Size = new System.Drawing.Size(139, 24);
this.chbMatrizCusto.Size = new System.Drawing.Size(132, 22);
this.chbMatrizCusto.TabIndex = 13;
this.chbMatrizCusto.Text = "Matriz de Custo";
this.chbMatrizCusto.UseVisualStyleBackColor = true;
@ -323,6 +330,17 @@
this.gpbP_Atu.TabStop = false;
this.gpbP_Atu.Text = "Ajustes";
//
// chbPulverizadorAutomatico
//
this.chbPulverizadorAutomatico.AutoSize = true;
this.chbPulverizadorAutomatico.Location = new System.Drawing.Point(10, 155);
this.chbPulverizadorAutomatico.Margin = new System.Windows.Forms.Padding(6);
this.chbPulverizadorAutomatico.Name = "chbPulverizadorAutomatico";
this.chbPulverizadorAutomatico.Size = new System.Drawing.Size(109, 24);
this.chbPulverizadorAutomatico.TabIndex = 14;
this.chbPulverizadorAutomatico.Text = "Automático";
this.chbPulverizadorAutomatico.UseVisualStyleBackColor = true;
//
// nudAtuarem
//
this.nudAtuarem.Location = new System.Drawing.Point(130, 97);
@ -394,6 +412,17 @@
this.gpbP_Dir.TabStop = false;
this.gpbP_Dir.Text = "Ajustes";
//
// chbDirecionalAutomatico
//
this.chbDirecionalAutomatico.AutoSize = true;
this.chbDirecionalAutomatico.Location = new System.Drawing.Point(9, 155);
this.chbDirecionalAutomatico.Margin = new System.Windows.Forms.Padding(6);
this.chbDirecionalAutomatico.Name = "chbDirecionalAutomatico";
this.chbDirecionalAutomatico.Size = new System.Drawing.Size(109, 24);
this.chbDirecionalAutomatico.TabIndex = 15;
this.chbDirecionalAutomatico.Text = "Automático";
this.chbDirecionalAutomatico.UseVisualStyleBackColor = true;
//
// lblAngulomax
//
this.lblAngulomax.AutoSize = true;
@ -485,6 +514,17 @@
this.gpbP_Mov.TabStop = false;
this.gpbP_Mov.Text = "Ajustes";
//
// chbMovimentacaoAutomatica
//
this.chbMovimentacaoAutomatica.AutoSize = true;
this.chbMovimentacaoAutomatica.Location = new System.Drawing.Point(6, 155);
this.chbMovimentacaoAutomatica.Margin = new System.Windows.Forms.Padding(6);
this.chbMovimentacaoAutomatica.Name = "chbMovimentacaoAutomatica";
this.chbMovimentacaoAutomatica.Size = new System.Drawing.Size(109, 24);
this.chbMovimentacaoAutomatica.TabIndex = 16;
this.chbMovimentacaoAutomatica.Text = "Automático";
this.chbMovimentacaoAutomatica.UseVisualStyleBackColor = true;
//
// nudVelocidadeComErvas
//
this.nudVelocidadeComErvas.Location = new System.Drawing.Point(10, 120);
@ -773,38 +813,34 @@
this.lblCapacidadereservatorio.TabIndex = 9;
this.lblCapacidadereservatorio.Text = "Capacidade reservatório";
//
// chbPulverizadorAutomatico
// lblAnteciparManobra
//
this.chbPulverizadorAutomatico.AutoSize = true;
this.chbPulverizadorAutomatico.Location = new System.Drawing.Point(10, 155);
this.chbPulverizadorAutomatico.Margin = new System.Windows.Forms.Padding(6);
this.chbPulverizadorAutomatico.Name = "chbPulverizadorAutomatico";
this.chbPulverizadorAutomatico.Size = new System.Drawing.Size(109, 24);
this.chbPulverizadorAutomatico.TabIndex = 14;
this.chbPulverizadorAutomatico.Text = "Automático";
this.chbPulverizadorAutomatico.UseVisualStyleBackColor = true;
this.lblAnteciparManobra.AutoSize = true;
this.lblAnteciparManobra.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblAnteciparManobra.Location = new System.Drawing.Point(7, 131);
this.lblAnteciparManobra.Name = "lblAnteciparManobra";
this.lblAnteciparManobra.Size = new System.Drawing.Size(132, 18);
this.lblAnteciparManobra.TabIndex = 15;
this.lblAnteciparManobra.Text = "Antecipar manobra";
//
// chbDirecionalAutomatico
// txtAnteciparManobraM
//
this.chbDirecionalAutomatico.AutoSize = true;
this.chbDirecionalAutomatico.Location = new System.Drawing.Point(9, 155);
this.chbDirecionalAutomatico.Margin = new System.Windows.Forms.Padding(6);
this.chbDirecionalAutomatico.Name = "chbDirecionalAutomatico";
this.chbDirecionalAutomatico.Size = new System.Drawing.Size(109, 24);
this.chbDirecionalAutomatico.TabIndex = 15;
this.chbDirecionalAutomatico.Text = "Automático";
this.chbDirecionalAutomatico.UseVisualStyleBackColor = true;
this.txtAnteciparManobraM.Location = new System.Drawing.Point(10, 151);
this.txtAnteciparManobraM.Name = "txtAnteciparManobraM";
this.txtAnteciparManobraM.Size = new System.Drawing.Size(73, 26);
this.txtAnteciparManobraM.TabIndex = 16;
this.txtAnteciparManobraM.Text = "0";
this.txtAnteciparManobraM.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// chbMovimentacaoAutomatica
// lblAnteciparManobraM
//
this.chbMovimentacaoAutomatica.AutoSize = true;
this.chbMovimentacaoAutomatica.Location = new System.Drawing.Point(6, 155);
this.chbMovimentacaoAutomatica.Margin = new System.Windows.Forms.Padding(6);
this.chbMovimentacaoAutomatica.Name = "chbMovimentacaoAutomatica";
this.chbMovimentacaoAutomatica.Size = new System.Drawing.Size(109, 24);
this.chbMovimentacaoAutomatica.TabIndex = 16;
this.chbMovimentacaoAutomatica.Text = "Automático";
this.chbMovimentacaoAutomatica.UseVisualStyleBackColor = true;
this.lblAnteciparManobraM.AutoSize = true;
this.lblAnteciparManobraM.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblAnteciparManobraM.Location = new System.Drawing.Point(89, 158);
this.lblAnteciparManobraM.Name = "lblAnteciparManobraM";
this.lblAnteciparManobraM.Size = new System.Drawing.Size(21, 18);
this.lblAnteciparManobraM.TabIndex = 17;
this.lblAnteciparManobraM.Text = "m";
//
// frmParametrizacaoOperacao
//
@ -915,5 +951,8 @@
private System.Windows.Forms.CheckBox chbPulverizadorAutomatico;
private System.Windows.Forms.CheckBox chbDirecionalAutomatico;
private System.Windows.Forms.CheckBox chbMovimentacaoAutomatica;
private System.Windows.Forms.Label lblAnteciparManobraM;
private System.Windows.Forms.TextBox txtAnteciparManobraM;
private System.Windows.Forms.Label lblAnteciparManobra;
}
}

View File

@ -76,6 +76,8 @@ namespace AgroBase.Forms.Operacoes
chbImuParadaInclinacao.Checked = _Parametros.Controle.ImuParadaPorInclinacao;
chbOakParadaObstaculo.Checked = _Parametros.Controle.OakParadaPorObstaculo;
txtAnteciparManobraM.Text = _Parametros.Controle.AnteciparManobraCorredorM.ToString();
}
private void chbD_CheckedChanged(object sender, EventArgs e)
@ -142,6 +144,7 @@ namespace AgroBase.Forms.Operacoes
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirecionalAutomatico = chbDirecionalAutomatico.Checked;
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo = (int)(nudAnguloMaximo.Value);
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento = (int)(nudVelocidadeMP.Value);
Variaveis.OperacaoEmAndamento.Parametros.Controle.AnteciparManobraCorredorM = Convert.ToDouble(txtAnteciparManobraM.Text.Replace(".", ","));
Variaveis.OperacaoEmAndamento.tmrLogsInterval = (double)(nudTemposalvarlog.Value * 1000);
Variaveis.OperacaoEmAndamento.Parametros.QtdBicos = (int)nudQtdBicos.Value;
Variaveis.OperacaoEmAndamento.Parametros.QtdCamerasSolo = (int)nudQtdCameras.Value;

View File

@ -1142,8 +1142,8 @@ namespace AgroBase.Forms.Operacoes
lblPercentualBateria.Text = $"Bateria {Log.Bateria.PercentualBateria.ToString("0.00")}%";
FuncoesGlobais.PreencheValorProgressBar(pgbPercentualBateria, Log.Bateria.PercentualBateria);
lblBateriaConsumida.Text = $"Consumido {Log.Bateria.PercentualBateriaConsumidaOperacao.ToString("0.00")}%";
FuncoesGlobais.PreencheValorProgressBar(pgbBateriaConsumida, Log.Bateria.PercentualBateriaConsumidaOperacao);
lblBateriaConsumida.Text = $"Consumido {Log.Bateria.PercentualBateriaConsumida.ToString("0.00")}%";
FuncoesGlobais.PreencheValorProgressBar(pgbBateriaConsumida, Log.Bateria.PercentualBateriaConsumida);
lblPercentualReservatorio.Text = $"Reservatório {LogAtu.PercentualReservatorio.ToString("0.00")}%";
FuncoesGlobais.PreencheValorProgressBar(pgbPercentualReservatorio, LogAtu.PercentualReservatorio);
@ -1607,10 +1607,31 @@ namespace AgroBase.Forms.Operacoes
private void AtualizarInformacoesCameraCaminho()
{
double? CalcularErroLateralPctImagem(int width, List<double?[]> centrosCorredor)
{
if (width <= 0 || centrosCorredor == null || centrosCorredor.Count == 0)
return null;
var basePoint = centrosCorredor[0];
if (basePoint == null || basePoint.Length < 1 || basePoint[0] == null)
return null;
double cxImg = width / 2.0;
double xBase = basePoint[0].Value;
return ((xBase - cxImg) / cxImg) * 100.0;
}
var Log = LogsOperacao[idxMomentoAtual];
txtCamCaminhoErroAngular.Text = (Log.OperadorVisual?.Analises?.segmentacao?.erro_angular ?? 0).ToString("0.00");
txtCamCaminhoErroLateral.Text = (Log.OperadorVisual?.Analises?.segmentacao?.erro_lateral_pct ?? 0).ToString("0.00");
txtCamCaminhoErroLateral.Text = $"{(Log.OperadorVisual?.Analises?.segmentacao?.erro_lateral_pct ?? 0):F2}% ({CalcularErroLateralPctImagem(Log.OperadorVisual?.Analises?.segmentacao?.width ?? 0, Log.OperadorVisual?.Analises?.segmentacao?.centros_corredor):F2}%)";
txtCamCaminhoStatusCarro.Text = (Log.OperadorVisual?.Analises?.segmentacao?.status_corredor ?? Enums.StatusCarroMapa.Parado).ToString();
txtTempoEntrandoRua.Text = $"{(Log.Trajetoria?.CorredorAtual?.DadosVisuais?.TempoForaRuaContinuo ?? 0):F2} s";
txtTempoCaminhandoRua.Text = $"{(Log.Trajetoria?.CorredorAtual?.DadosVisuais?.TempoDentroRuaTotal ?? 0):F2} s";
txtTempoSaindoRua.Text = $"{(Log.Trajetoria?.CorredorAtual?.DadosVisuais?.JaAntecipado ?? false)}";
txtTempoParado.Text = $"{(Log.Trajetoria?.CorredorAtual?.DadosVisuais?.CorredorConfirmado ?? false)}";
txtTempoDirecionando.Text = $"{(Log.Trajetoria?.CorredorAtual?.DadosVisuais?.DistanciaForaRuaContinuo ?? 0):F2} m";
txtTempoManobrando.Text = $"{(Log.Trajetoria?.CorredorAtual?.DadosVisuais?.DistanciaRestanteAnterior ?? 0):F2} m";
//txtTempoEntrandoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.EntrandoRua).Value.ToString("0.00") + " s";
//txtTempoCaminhandoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.CaminhandoRua).Value.ToString("0.00") + " s";

View File

@ -390,6 +390,7 @@ namespace AgroBase.Models
OakParadaPorObstaculo = false,
MpcMatrizCusto = false,
MpcHorizonte = 4.0,
AnteciparManobraCorredorM = 0,
MovVelocidadeSErvasPercent = 35,
MovVelocidadeCErvasPercent = 12,
@ -498,6 +499,7 @@ namespace AgroBase.Models
OakParadaPorObstaculo = true,
MpcMatrizCusto = false,
MpcHorizonte = 4.0,
AnteciparManobraCorredorM = 10.0,
MovVelocidadeSErvasPercent = 50,
MovVelocidadeCErvasPercent = 20,
@ -636,6 +638,7 @@ namespace AgroBase.Models
OakParadaPorObstaculo = false,
MpcMatrizCusto = false,
MpcHorizonte = 4.0,
AnteciparManobraCorredorM = 0,
MovVelocidadeSErvasPercent = 50,
MovVelocidadeCErvasPercent = 20,
@ -772,6 +775,7 @@ namespace AgroBase.Models
OakParadaPorObstaculo = true,
MpcMatrizCusto = false,
MpcHorizonte = 4.0,
AnteciparManobraCorredorM = 10.0,
MovVelocidadeSErvasPercent = 40,
MovVelocidadeCErvasPercent = 20,
@ -869,6 +873,7 @@ namespace AgroBase.Models
OakParadaPorObstaculo = true,
MpcMatrizCusto = false,
MpcHorizonte = 4.0,
AnteciparManobraCorredorM = 0,
MovVelocidadeSErvasPercent = 60,
MovVelocidadeCErvasPercent = 20,
@ -2424,6 +2429,7 @@ namespace AgroBase.Models
}
public bool EmFreio { get; set; } = false;
//public Direcao Direcao { get; set; } = Direcao.Parado;
[JsonIgnore]
public List<AtuadorBicoModel> Bicos => Variaveis.OperacaoEmAndamento.DispAtu?.Dados?.BicosPulverizadores;
public double AlturaBarra { get; set; }
private TipoMovimentoDirecional _tipoMovimento = TipoMovimentoDirecional.Diagnostico;

View File

@ -261,6 +261,20 @@ namespace AgroBase.Models.Operacoes
}
}
private double _anteciparManobraCorredorM;
public double AnteciparManobraCorredorM
{
get => _anteciparManobraCorredorM;
set
{
if (_anteciparManobraCorredorM != value)
{
_anteciparManobraCorredorM = value;
OnPropertyChanged(nameof(AnteciparManobraCorredorM));
}
}
}
private bool _registrarDadosPosProcessamento;
public bool RegistrarDadosPosProcessamento
{

View File

@ -563,6 +563,7 @@ namespace AgroBase.Models.Operadores
public StatusCarroMapa status_corredor_anterior { get; set; }
public VisualWorkerMessageSegmentacaoSemanticaDebugCorredorModel status_corredor_debug { get; set; }
public List<double?[]> centros_corredor { get; set; }
public List<int> larguras_px { get; set; }
public VisualWorkerMessageSegmentacaoSemanticaModel Clone()
{
@ -576,7 +577,8 @@ namespace AgroBase.Models.Operadores
status_corredor = status_corredor,
status_corredor_anterior = status_corredor_anterior,
status_corredor_debug = status_corredor_debug,
centros_corredor = new List<double?[]>(centros_corredor ?? new List<double?[]>())
centros_corredor = new List<double?[]>(centros_corredor ?? new List<double?[]>()),
larguras_px = new List<int>(larguras_px ?? new List<int>()),
};
}
}

View File

@ -773,14 +773,16 @@ namespace AgroBase.Models
private void VerificaFimCorredorSegmentacao()
{
// Limiar de "margem" para considerar proximidade do fim
//double limiarDistanciaMargem = DistanciaErroMapaPlantacao > -1 ? DistanciaErroMapaPlantacao : 10.0;
double limiarDistanciaMargem = Variaveis.OperacaoEmAndamento.Parametros?.Controle?.AnteciparManobraCorredorM ?? 0;
if (limiarDistanciaMargem <= 0) return;
if (CorredorAtual == null) return;
if (CorredorAtual.DadosVisuais.JaAntecipado) return;
bool modoSimulador = false && Variaveis.OperacaoEmAndamento.Simulando;
// Limiar de "margem" para considerar proximidade do fim
double limiarDistanciaMargem = DistanciaErroMapaPlantacao > -1 ? DistanciaErroMapaPlantacao : 5.0;
double distanciaCorredor = CorredorAtual.DistanciaTotal;
double distanciaRestanteCorredor = CorredorAtual.DistanciaRestante;
double distanciaUltimoPontoCorredor = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual.Pontos.LastOrDefault().Posicao);
@ -855,11 +857,10 @@ namespace AgroBase.Models
dv.DistanciaRestanteAnterior = distanciaRestanteCorredor;
// 2) Confirmar se este corredor realmente existiu (teve cana)
const double MIN_DIST_CORREDOR_CONFIRMADO = 5.0; // metros dentro da rua
const double MIN_TEMPO_CORREDOR_CONFIRMADO = 10.0; // segundos dentro da rua
if (!dv.CorredorConfirmado)
{
const double MIN_DIST_CORREDOR_CONFIRMADO = 5.0; // metros dentro da rua
const double MIN_TEMPO_CORREDOR_CONFIRMADO = 10.0; // segundos dentro da rua
if (dv.DistanciaDentroRuaTotal >= MIN_DIST_CORREDOR_CONFIRMADO || dv.TempoDentroRuaTotal >= MIN_TEMPO_CORREDOR_CONFIRMADO)
{
dv.CorredorConfirmado = true;
@ -876,7 +877,7 @@ namespace AgroBase.Models
bool foraDoCorredorAgora = (statusAtual == StatusCarroMapa.Direcionando);
// Limiar de "quanto tempo/distância já estou fora do corredor" para evitar buracos pontuais
const double MIN_TEMPO_FORA_CORREDOR = 2.0; // segundos
const double MIN_TEMPO_FORA_CORREDOR = 1.0; // segundos
const double MIN_DIST_FORA_CORREDOR = 1.0; // metros
bool foraContinuoSuficiente = dv.TempoForaRuaContinuo >= MIN_TEMPO_FORA_CORREDOR || dv.DistanciaForaRuaContinuo >= MIN_DIST_FORA_CORREDOR;

View File

@ -180,9 +180,8 @@ class SegmentacaoManager:
erro_lateral_pct = 0.0
if centros and centros[base_ix][0] is not None:
x_base, _ = centros[base_ix]
w_base = max(1, larguras[base_ix])
err_px = cx_img - x_base
erro_lateral_pct = (err_px / w_base) * 100.0
err_px = x_base - cx_img
erro_lateral_pct = (err_px / cx_img) * 100.0
if getattr(self, "_ema_lat", None) is None:
self._ema_lat = float(erro_lateral_pct)

View File

@ -151,7 +151,7 @@ namespace OperationControl.Controls
private void HighlightRoad(MIFeature? feature = null, string? id = null)
{
if (string.IsNullOrEmpty(id))
id = GetAttr(feature, "Id");
id = GetAttr(feature, "IdCorrigido");
var rua = RuasMapaCarregado.FirstOrDefault(x => x.Id == id);
if (rua == null) return;
@ -854,38 +854,66 @@ namespace OperationControl.Controls
var reader = new GeoJsonReader();
var fc = reader.Read<FeatureCollection>(geojson);
// 1) Converte NTS -> IFeature (GeometryFeature) mantendo WGS84
RuasMapaCarregado = new List<StreetMapDictionaryModel>();
var idsUsados = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
int idsCorrigidos = 0;
int total = 0;
foreach (var f in fc)
{
if (f.Geometry == null) continue;
if (f.Geometry == null)
continue;
total++;
var gf = new GeometryFeature
{
Geometry = f.Geometry // NTS geometry em WGS84 (lon/lat)
Geometry = f.Geometry
};
// copia atributos (opcional)
// copia atributos
foreach (var name in f.Attributes.GetNames())
gf[name] = f.Attributes[name];
bool foiGeradoAutomaticamente;
string idFinal = ResolveUniqueStreetId(gf, RuasMapaCarregado.Count, idsUsados, out foiGeradoAutomaticamente);
// guarda o original, se quiser rastrear/debugar
var idOriginal = GetAttr(gf, "Id") ??
GetAttr(gf, "ID") ??
GetAttr(gf, "id");
gf["IdCorrigido"] = idFinal;
if (!string.IsNullOrWhiteSpace(idOriginal))
gf["IdOriginal"] = idOriginal;
if (foiGeradoAutomaticamente)
idsCorrigidos++;
RuasMapaCarregado.Add(new StreetMapDictionaryModel()
{
Id = GetAttr(gf, "Id"),
Id = idFinal,
Feature = gf,
Selected = false,
Selected = false,
Status = StreetMapStyle.Normal
});
}
// 2) Provider em WGS84 (fonte)
if (idsCorrigidos > 0)
{
Models.Variaveis.MostrarLog(
$"Mapa carregado com correção automática de IDs. " +
$"Total de ruas: {RuasMapaCarregado.Count}. " +
$"IDs corrigidos/gerados: {idsCorrigidos}.");
}
var mem = new MemoryProvider(RuasMapaCarregado.Select(x => x.Feature))
{
CRS = "EPSG:4326"
};
// 3) Projeta on-the-fly para o CRS do mapa (WebMercator)
// Garanta que seu Mapa.Map.CRS esteja em "EPSG:3857" quando criar o Map.
var projecting = new ProjectingProvider(mem)
{
CRS = "EPSG:3857"
@ -894,7 +922,6 @@ namespace OperationControl.Controls
if (Mapa.Map.Layers.Any(x => x.Name == MapaPlantacao_Layer?.Name))
Mapa.Map.Layers.Remove(MapaPlantacao_Layer);
// 4) Camada
MapaPlantacao_Layer = new Layer("GeoJson")
{
DataSource = projecting,
@ -910,11 +937,6 @@ namespace OperationControl.Controls
markers.BringMarkersToFront();
Mapa.Refresh();
// 5) Auto-zoom usando o próprio provider projetado
//var extent = projecting.GetExtent();
//if (extent != null)
// Mapa.Map.Navigator?.ZoomToBox(extent);
try
{
double _long = ((dynamic)RuasMapaCarregado[0].Feature).Geometry.Coordinate.X;
@ -927,6 +949,52 @@ namespace OperationControl.Controls
}
}
private string ResolveUniqueStreetId(GeometryFeature feature, int index, HashSet<string> idsUsados, out bool foiGeradoAutomaticamente)
{
foiGeradoAutomaticamente = false;
// tenta achar algum campo comum de ID
string? idOriginal =
GetAttr(feature, "Id") ??
GetAttr(feature, "ID") ??
GetAttr(feature, "id") ??
GetAttr(feature, "OBJECTID") ??
GetAttr(feature, "ObjectID") ??
GetAttr(feature, "FID");
idOriginal = idOriginal?.Trim();
// caso esteja vazio/null
if (string.IsNullOrWhiteSpace(idOriginal))
{
string novoId = $"AUTO_{index + 1:D4}";
idsUsados.Add(novoId);
foiGeradoAutomaticamente = true;
return novoId;
}
// se ainda não foi usado, aceita
if (!idsUsados.Contains(idOriginal))
{
idsUsados.Add(idOriginal);
return idOriginal;
}
// se repetiu, mantém rastreabilidade mas torna único
int sufixo = 2;
string candidato;
do
{
candidato = $"{idOriginal}_{sufixo:D2}";
sufixo++;
}
while (idsUsados.Contains(candidato));
idsUsados.Add(candidato);
foiGeradoAutomaticamente = true;
return candidato;
}
private void OnCenterAreaClicked(object sender, RoutedEventArgs e)
{
NavigateToView();

View File

@ -174,6 +174,9 @@
<TextBlock Text="Horizonte (m)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MpcHorizonte, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
<TextBlock Text="Antecipar Fim do Corredor (m)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AnteciparManobraCorredorM, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>