373 lines
15 KiB
C#
373 lines
15 KiB
C#
using AgroBase.Models;
|
|
using AgroBase.Models.Operadores;
|
|
using AgroBase.Services.Operadores;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Forms.DataVisualization.Charting;
|
|
|
|
namespace AgroBase.Forms
|
|
{
|
|
public partial class frmOperarioSonar : Form
|
|
{
|
|
AsyncTaskTimerModel tmrLeitura;
|
|
|
|
public frmOperarioSonar()
|
|
{
|
|
InitializeComponent();
|
|
|
|
pnlInclinacao.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlInclinacao, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
|
|
}
|
|
|
|
private void frmOperarioSonar_Load(object sender, EventArgs e)
|
|
{
|
|
AtualizarListaCameras();
|
|
ConfigurarGridDeteccoes(dgvAnomalias);
|
|
ConfigurarGridDeteccoes(dgvSolo);
|
|
tmrLeitura = new AsyncTaskTimerModel("tmrLeitura_VisalWorker", tmrLeitura_Tick, 100, this);
|
|
tmrLeitura.Start();
|
|
}
|
|
|
|
private async void frmOperarioSonar_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
tmrLeitura?.Stop();
|
|
}
|
|
|
|
private void AtualizarListaCameras()
|
|
{
|
|
cmbCameras.Items.Clear();
|
|
cmbCameras.Items.AddRange(CameraWorkerService.GetListaCameras().Select(x => x.Name).ToArray());
|
|
cmbCameras.SelectedIndex = -1;
|
|
}
|
|
|
|
private async Task tmrLeitura_Tick()
|
|
{
|
|
if (!chbReqAutomatico.Checked) return;
|
|
|
|
/*btnLeituraIMU_Click(new object(), new EventArgs());
|
|
EnviarComandoReqFrame(VisualWorkerCommandType.Get_RGB_Frame);
|
|
EnviarComandoReqFrame(VisualWorkerCommandType.Get_Heatmap_Frame);
|
|
EnviarComandoAnalise(VisualWorkerCommandType.Get_Analise_Anomalia);
|
|
EnviarComandoAnalise(VisualWorkerCommandType.Get_Analise_Solo);
|
|
EnviarComandoReqFrame(VisualWorkerCommandType.Get_Radar_2D);
|
|
EnviarComandoReqFrame(VisualWorkerCommandType.Get_Segmentacao_Semantica);*/
|
|
}
|
|
|
|
private async void btnAtualizarCameras_Click(object sender, EventArgs e)
|
|
{
|
|
AtualizarListaCameras();
|
|
}
|
|
|
|
private async void btnIniciarProcessamento_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void btnPing_Click(object sender, EventArgs e)
|
|
{
|
|
//EnviarComando(VisualWorkerCommandType.Ping);
|
|
}
|
|
|
|
private void btnCalibrarGrades_Click(object sender, EventArgs e)
|
|
{
|
|
VisualWorkerService.RecalibrarGridProfundidade();
|
|
}
|
|
|
|
private async void btnLeituraRGB_Click(object sender, EventArgs e)
|
|
{
|
|
EnviarComandoReqFrame(CameraFrameType.Rgb);
|
|
}
|
|
|
|
private void btnLeituraHeatmap_Click(object sender, EventArgs e)
|
|
{
|
|
EnviarComandoReqFrame(CameraFrameType.Heatmap);
|
|
}
|
|
|
|
private void btnLeituraRadar2D_Click(object sender, EventArgs e)
|
|
{
|
|
EnviarComandoReqFrame(CameraFrameType.RadarTopDown);
|
|
}
|
|
|
|
private void btnLeituraSegmentacaoSemantica_Click(object sender, EventArgs e)
|
|
{
|
|
EnviarComandoReqFrame(CameraFrameType.Segmentacao);
|
|
}
|
|
|
|
private async void EnviarComandoReqFrame(CameraFrameType tipo)
|
|
{
|
|
OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(tipo);
|
|
|
|
PictureBox pic =
|
|
tipo == CameraFrameType.Rgb ? picRGB :
|
|
tipo == CameraFrameType.Heatmap ? picHeatmap :
|
|
tipo == CameraFrameType.RadarTopDown ? picRadar2D :
|
|
tipo == CameraFrameType.Segmentacao ? picSegmentacaoSemantica :
|
|
new PictureBox();
|
|
Label lbl =
|
|
tipo == CameraFrameType.Rgb ? lblLeituraRGB :
|
|
tipo == CameraFrameType.Heatmap ? lblLeituraHeatmap :
|
|
tipo == CameraFrameType.RadarTopDown ? lblLeituraRadar2D :
|
|
tipo == CameraFrameType.Segmentacao ? lblLeituraSegmentacaoSemantica :
|
|
new Label();
|
|
|
|
pic.Image?.Dispose();
|
|
try { pic.Image = frame?.image(); } catch { }
|
|
lbl.Text = $"Leitura em: " + frame?.timestamp.ToString("dd/MM/yyyy HH:mm:ss");
|
|
|
|
if (tipo == CameraFrameType.RadarTopDown && VisualWorkerService.DadosLeitura.Analises != null)
|
|
{
|
|
//pic.Image = VariaveisOperacao.Operadores.VisualWorker.DadosLeitura.Leitura.obj.radar_2d.PlotarAnalsie(frame.image);
|
|
|
|
//PlotarGraficoPerfilCorredor(VisualWorkerService.DadosLeitura.Analises.corredor_prof);
|
|
}
|
|
}
|
|
|
|
private void btnReqStatusDispositivo_Click(object sender, EventArgs e)
|
|
{
|
|
//EnviarComando(VisualWorkerCommandType.Get_Status_Dispositivo);
|
|
}
|
|
|
|
private void btnReqAnomalias_Click(object sender, EventArgs e)
|
|
{
|
|
AtualizarDadosAnalise();
|
|
}
|
|
|
|
private void btnReqSolo_Click(object sender, EventArgs e)
|
|
{
|
|
AtualizarDadosAnalise();
|
|
}
|
|
|
|
private async void btnLeituraIMU_Click(object sender, EventArgs e)
|
|
{
|
|
pnlInclinacao.Invalidate();
|
|
lblLeituraIMU.Text = $"Leitura em: {FuncoesGlobais.TimestampToDate(VisualWorkerService.DadosLeitura.Imu?.timestamp ?? 0)}";
|
|
}
|
|
|
|
private void AtualizarDadosAnalise()
|
|
{
|
|
var analise = VisualWorkerService.DadosLeitura.Analises;
|
|
|
|
lblLeituraDebug.Text = $"Leitura em: " + (analise?.timestamp ?? DateTime.MinValue).ToString("dd/MM/yyyy HH:mm:ss");
|
|
OAKCameraFrameModel frame = VisualWorkerService.DadosLeitura.CameraFrames[CameraFrameType.Heatmap];
|
|
picDebug.Image?.Dispose();
|
|
picDebug.Image = analise.PlotarAnalise(frame);
|
|
|
|
//PreencherGridAnomalias(analise.anomalias ?? new List<VisualWorkerMessageAnaliseBBoxModel>());
|
|
//PreencherGridSolo(analise.solo?.bbox_list ?? new List<VisualWorkerMessageAnaliseBBoxModel>());
|
|
//PlotarGraficoPerfilSolo(analise.solo?.perfil ?? new List<double>());
|
|
}
|
|
|
|
void ConfigurarGridDeteccoes(DataGridView dgv)
|
|
{
|
|
dgv.Columns.Clear();
|
|
|
|
dgv.Columns.Add("Tipo", "Tipo");
|
|
dgv.Columns.Add("X", "X");
|
|
dgv.Columns.Add("Y", "Y");
|
|
dgv.Columns.Add("W", "Largura (px)");
|
|
dgv.Columns.Add("H", "Altura (px)");
|
|
dgv.Columns.Add("Centro", "Centro (%)");
|
|
dgv.Columns.Add("Distancia", "Distância (m)");
|
|
dgv.Columns.Add("LarguraM", "Largura (m)");
|
|
dgv.Columns.Add("AlturaM", "Altura (m)");
|
|
dgv.Columns.Add("Variacao", "Variação (mm)");
|
|
|
|
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
|
|
dgv.ReadOnly = true;
|
|
dgv.AllowUserToAddRows = false;
|
|
dgv.AllowUserToDeleteRows = false;
|
|
}
|
|
|
|
void PreencherGridAnomalias(List<VisualWorkerMessageAnaliseBBoxModel> bboxes)
|
|
{
|
|
dgvAnomalias.Rows.Clear();
|
|
|
|
foreach (var bbox in bboxes)
|
|
{
|
|
int rowIndex = dgvAnomalias.Rows.Add(
|
|
bbox.tipo,
|
|
bbox.bbox[0], bbox.bbox[1], bbox.bbox[2], bbox.bbox[3],
|
|
$"{bbox.centro_percentual[0]:0.0}%, {bbox.centro_percentual[1]:0.0}%",
|
|
bbox.distancia_m?.ToString("0.00") ?? "-",
|
|
bbox.largura_m?.ToString("0.00") ?? "-",
|
|
bbox.altura_m?.ToString("0.00") ?? "-",
|
|
bbox.variacao?.ToString("0.0") ?? "-"
|
|
);
|
|
|
|
if (bbox.distancia_m < 1.0)
|
|
{
|
|
dgvAnomalias.Rows[rowIndex].DefaultCellStyle.BackColor = Color.LightCoral;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PreencherGridSolo(List<VisualWorkerMessageAnaliseBBoxModel> bboxes)
|
|
{
|
|
dgvSolo.Rows.Clear();
|
|
|
|
foreach (var bbox in bboxes)
|
|
{
|
|
dgvSolo.Rows.Add(
|
|
bbox.tipo,
|
|
bbox.bbox[0], bbox.bbox[1], bbox.bbox[2], bbox.bbox[3],
|
|
$"{bbox.centro_percentual[0]:0.0}%, {bbox.centro_percentual[1]:0.0}%",
|
|
bbox.distancia_m?.ToString("0.00") ?? "-",
|
|
bbox.largura_m?.ToString("0.00") ?? "-",
|
|
bbox.altura_m?.ToString("0.00") ?? "-",
|
|
bbox.variacao?.ToString("0.0") ?? "-"
|
|
);
|
|
}
|
|
}
|
|
|
|
void PlotarGraficoPerfilSolo(List<double> perfil)
|
|
{
|
|
if (perfil == null || perfil.Count == 0) return;
|
|
|
|
chartPerfilSolo.Series.Clear();
|
|
var serie = chartPerfilSolo.Series.Add("Perfil");
|
|
serie.ChartType = SeriesChartType.Line;
|
|
|
|
for (int i = 0; i < perfil.Count; i++)
|
|
{
|
|
serie.Points.AddXY(i + 1, perfil[i]);
|
|
}
|
|
|
|
// 🔸 Calcula os limites com margem
|
|
double min = perfil.Min();
|
|
double max = perfil.Max();
|
|
|
|
double margem = 5;
|
|
|
|
chartPerfilSolo.ChartAreas[0].AxisY.Minimum = min - margem;
|
|
chartPerfilSolo.ChartAreas[0].AxisY.Maximum = max + margem;
|
|
|
|
// (Opcional) Deixa os grids bonitos
|
|
chartPerfilSolo.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.LightGray;
|
|
chartPerfilSolo.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.LightGray;
|
|
|
|
// 🔥 Legenda embaixo
|
|
chartPerfilSolo.Legends[0].Docking = Docking.Bottom;
|
|
}
|
|
|
|
void PlotarGraficoPerfilCorredor(List<VisualWorkerMessageRadar2DPerfilModel> perfilCorredor)
|
|
{
|
|
chartCorredor.Series.Clear();
|
|
|
|
var serieEsquerda = chartCorredor.Series.Add("Esquerda");
|
|
var serieDireita = chartCorredor.Series.Add("Direita");
|
|
//var serieLargura = chartCorredor.Series.Add("Largura Total");
|
|
|
|
serieEsquerda.ChartType = SeriesChartType.Line;
|
|
serieDireita.ChartType = SeriesChartType.Line;
|
|
//serieLargura.ChartType = SeriesChartType.Line;
|
|
|
|
// Estilo diferenciado pra largura
|
|
//serieLargura.BorderDashStyle = ChartDashStyle.Dash;
|
|
//serieLargura.Color = Color.Gray;
|
|
|
|
double maxLado = 0;
|
|
|
|
foreach (var item in perfilCorredor)
|
|
{
|
|
double distancia = item.distancia_m;
|
|
double esquerda = item.esquerda_m;
|
|
double direita = item.direita_m;
|
|
double largura = item.largura_m;
|
|
|
|
// Calcula o maior lado
|
|
maxLado = Math.Max(maxLado, Math.Max(esquerda, direita));
|
|
|
|
// Esquerda negativa
|
|
serieEsquerda.Points.AddXY(-esquerda, distancia);
|
|
serieDireita.Points.AddXY(direita, distancia);
|
|
//serieLargura.Points.AddXY(largura, distancia);
|
|
}
|
|
|
|
// 🔥 Define os limites simétricos
|
|
chartCorredor.ChartAreas[0].AxisX.Minimum = -maxLado - 0.1;
|
|
chartCorredor.ChartAreas[0].AxisX.Maximum = maxLado + 0.1;
|
|
|
|
// 🔥 Legenda embaixo
|
|
chartCorredor.Legends[0].Docking = Docking.Bottom;
|
|
|
|
// 🔥 Configurações de eixo
|
|
chartCorredor.ChartAreas[0].AxisX.Title = "Espaço Lateral (m)";
|
|
chartCorredor.ChartAreas[0].AxisY.Title = "Distância Frente (m)";
|
|
chartCorredor.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.LightGray;
|
|
chartCorredor.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.LightGray;
|
|
|
|
chartCorredor.ChartAreas[0].AxisX.Crossing = 0; // 🔥 Eixo X cruza no centro (0 lateral)
|
|
|
|
}
|
|
|
|
private void pnlInclinacao_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
Panel _pnlInclinacao = sender as Panel;
|
|
double AnguloX = VisualWorkerService.DadosLeitura.Imu?.roll ?? 0;
|
|
double AnguloY = VisualWorkerService.DadosLeitura.Imu?.pitch ?? 0;
|
|
|
|
Graphics g = e.Graphics;
|
|
int centerX = _pnlInclinacao.Width / 2;
|
|
int centerY = _pnlInclinacao.Height / 2;
|
|
int radius = 10;
|
|
|
|
// Desenhar fundo com bordas arredondadas
|
|
GraphicsPath path = new GraphicsPath();
|
|
int cornerRadius = 20;
|
|
path.AddArc(0, 0, cornerRadius, cornerRadius, 180, 90);
|
|
path.AddArc(_pnlInclinacao.Width - cornerRadius, 0, cornerRadius, cornerRadius, 270, 90);
|
|
path.AddArc(_pnlInclinacao.Width - cornerRadius, _pnlInclinacao.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90);
|
|
path.AddArc(0, _pnlInclinacao.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
|
|
path.CloseAllFigures();
|
|
|
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|
g.FillPath(new SolidBrush(Color.LightBlue), path);
|
|
g.DrawPath(new Pen(Color.DarkBlue, 2), path);
|
|
|
|
// Desenhar linhas de referência
|
|
Pen pen = new Pen(Color.Gray, 1);
|
|
g.DrawLine(pen, centerX, 0, centerX, _pnlInclinacao.Height);
|
|
g.DrawLine(pen, 0, centerY, _pnlInclinacao.Width, centerY);
|
|
|
|
// Desenhar linhas adicionais para ângulos
|
|
for (int i = -90; i <= 90; i += 15)
|
|
{
|
|
int posX = centerX + (int)(i * (_pnlInclinacao.Width / 2 - radius) / 90);
|
|
int posY = centerY - (int)(i * (_pnlInclinacao.Height / 2 - radius) / 90);
|
|
g.DrawLine(pen, centerX, centerY, posX, centerY);
|
|
g.DrawLine(pen, centerX, centerY, centerX, posY);
|
|
}
|
|
|
|
// Desenhar régua na linha central
|
|
for (int i = -90; i <= 90; i += 15)
|
|
{
|
|
int posX = centerX + (int)(i * (_pnlInclinacao.Width / 2 - radius) / 90);
|
|
int posY = centerY - (int)(i * (_pnlInclinacao.Height / 2 - radius) / 90);
|
|
|
|
// Marcas horizontais
|
|
g.DrawLine(pen, posX, centerY - 5, posX, centerY + 5);
|
|
g.DrawString(i.ToString(), new Font("Arial", 8), Brushes.Black, posX - 10, centerY + 10);
|
|
|
|
// Marcas verticais
|
|
g.DrawLine(pen, centerX - 5, posY, centerX + 5, posY);
|
|
g.DrawString(i.ToString(), new Font("Arial", 8), Brushes.Black, centerX + 10, posY - 5);
|
|
}
|
|
|
|
// Calcular a posição do círculo com base nos ângulos
|
|
int circlePosX = centerX + (int)(AnguloX * (_pnlInclinacao.Width / 2 - radius) / 90);
|
|
int circlePosY = centerY - (int)(AnguloY * (_pnlInclinacao.Height / 2 - radius) / 90);
|
|
|
|
// Desenhar o círculo
|
|
Brush brush = new SolidBrush(Color.Red);
|
|
g.FillEllipse(brush, circlePosX - radius, circlePosY - radius, radius * 2, radius * 2);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|