agrobot_base/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs

366 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using static AgroBase.Models.Enums;
namespace AgroBase.Models.Operadores
{
public class VisualWorkerModel
{
public bool Iniciado { get; set; }
public DateTime IniciadoEm { get; set; }
public bool Pronto { get; set; }
public DateTime ProntoEm { get; set; }
public VisualWorkerMessageModel UltimaMensagem { get; set; }
public VisualWorkerMessageModel Leitura { get; set; } = new VisualWorkerMessageModel();
public void ReiniciarEstado()
{
Iniciado = false;
IniciadoEm = DateTime.MinValue;
Pronto = false;
ProntoEm = DateTime.MinValue;
UltimaMensagem = new VisualWorkerMessageModel();
Leitura = new VisualWorkerMessageModel();
}
}
public class VisualWorkerMessageModel
{
public DateTime _Momento { get; set; } = DateTime.MinValue;
public long momento { get; set; }
public VisualWorkerMessageType tipo_cmd { get; set; }
public VisualWorkerCommandType cmd { get; set; }
public VisualWorkerMessageResponseModel obj { get; set; } = new VisualWorkerMessageResponseModel();
public dynamic payload { get; set; }
}
public class VisualWorkerMessageResponseModel
{
public OAKCameraModel device_status { get; set; }
public VisualWorkerMessageFrameModel rgb_frame { get; set; }
public VisualWorkerMessageFrameModel heatmap_frame { get; set; }
public VisualWorkerMessageFrameModel debug_frame { get; set; }
public VisualWorkerMessageSetupModel ping { get; set; }
public VisualWorkerMessageSetupModel calibragem { get; set; }
public VisualWorkerMessageObstaculosModel obstaculos { get; set; }
public VisualWorkerMessageCorredorModel corredor { get; set; }
public VisualWorkerMessageMapaProfundidadeModel mapa_profundidade { get; set; }
public VisualWorkerMessageObstaculos3DModel obstaculos_3d { get; set; }
public VisualWorkerMessageAnaliseModel analise { get; set; } = new VisualWorkerMessageAnaliseModel();
}
public class VisualWorkerMessageFrameModel
{
public long timestamp { get; set; }
public string frame { get; set; }
public Bitmap image { get; set; } = null;
public VisualWorkerMessageFrameModel Clone()
{
return new VisualWorkerMessageFrameModel()
{
timestamp = timestamp,
frame = frame,
image = FuncoesGlobais.Base64ToBitmap(frame),
};
}
}
public class VisualWorkerMessageSetupModel
{
public long timestamp { get; set; }
public bool status { get; set; }
public VisualWorkerMessageSetupModel Clone()
{
return new VisualWorkerMessageSetupModel()
{
timestamp = timestamp,
status = status,
};
}
}
public class VisualWorkerMessageObstaculosModel
{
public long timestamp { get; set; }
public bool precisa_micro { get; set; }
public bool alerta { get; set; }
public int quantidade { get; set; }
public bool frontal_bloqueado { get; set; }
public Dictionary<Direcao, bool> laterais { get; set; }
public Direcao zona_livre { get; set; }
public double distancia_minima { get; set; }
public List<VisualWorkerMessageGridModel> detalhes { get; set; }
public VisualWorkerMessageObstaculosModel Clone()
{
return new VisualWorkerMessageObstaculosModel()
{
timestamp = timestamp,
precisa_micro = precisa_micro,
alerta = alerta,
quantidade = quantidade,
frontal_bloqueado = frontal_bloqueado,
laterais = new Dictionary<Direcao, bool>(laterais),
zona_livre = zona_livre,
distancia_minima = distancia_minima,
detalhes = new List<VisualWorkerMessageGridModel>(detalhes)
};
}
}
public class VisualWorkerMessageGridModel
{
public int linha { get; set; }
public int coluna { get; set; }
public double distancia { get; set; }
public VisualWorkerDetectionType tipo { get; set; }
public VisualWorkerRegionType regiao { get; set; }
}
public class VisualWorkerMessageCorredorModel
{
public long timestamp { get; set; }
public double largura_corredor_mm { get; set; }
public double posicao_central_fracao { get; set; }
public double[][] pontos_debug { get; set; }
public VisualWorkerMessageCorredorModel Clone()
{
return new VisualWorkerMessageCorredorModel()
{
timestamp = timestamp,
largura_corredor_mm = largura_corredor_mm,
posicao_central_fracao = posicao_central_fracao,
pontos_debug = pontos_debug
};
}
}
public class VisualWorkerMessageMapaProfundidadeModel
{
public long timestamp { get; set; }
public string resolucao { get; set; }
public string unidade { get; set; }
public double?[][] grid { get; set; }
public VisualWorkerMessageMapaProfundidadeModel Clone()
{
return new VisualWorkerMessageMapaProfundidadeModel()
{
timestamp = timestamp,
resolucao = resolucao,
unidade = unidade,
grid = grid
};
}
}
public class VisualWorkerMessageObstaculos3DModel
{
public long timestamp { get; set; }
public List<VisualWorkerMessageObstaculos3DDetectadosModel> obstaculos_detectados { get; set; }
public VisualWorkerMessageObstaculos3DModel Clone()
{
return new VisualWorkerMessageObstaculos3DModel()
{
timestamp = timestamp,
obstaculos_detectados = new List<VisualWorkerMessageObstaculos3DDetectadosModel>(obstaculos_detectados)
};
}
}
public class VisualWorkerMessageObstaculos3DDetectadosModel
{
public double posicao { get; set; }
public double distancia { get; set; }
public int largura_px { get; set; }
}
public class VisualWorkerMessageAnaliseModel
{
public long timestamp { get; set; }
public List<VisualWorkerMessageAnaliseBBoxModel> anomalias { get; set; }
public VisualWorkerMessageAnaliseSoloModel solo { get; set; }
public VisualWorkerMessageAnaliseModel Clone()
{
return new VisualWorkerMessageAnaliseModel()
{
timestamp = timestamp,
anomalias = new List<VisualWorkerMessageAnaliseBBoxModel>(anomalias),
solo = solo.Clone(),
};
}
public Bitmap PlotarAnalise(VisualWorkerMessageFrameModel frame)
{
if (frame?.image == null) return null;
try { frame.image.Clone(); } catch { return null; }
Bitmap img = new Bitmap(frame.image);
using (Graphics g = Graphics.FromImage(img))
{
Pen penObstaculo = new Pen(Color.Red, 2);
Pen penErosao = new Pen(Color.Blue, 2);
Pen penLombada = new Pen(Color.Orange, 2);
Pen penFaixaSolo = new Pen(Color.Black, 2);
Pen penGrafico = new Pen(Color.DarkGreen, 2);
Font font = new Font("Arial", 8);
Brush brush = Brushes.Black;
// 🔸 Definir brushes semi-transparentes para preenchimento
Brush brushObstaculo = new SolidBrush(Color.FromArgb(60, Color.Red));
Brush brushErosao = new SolidBrush(Color.FromArgb(60, Color.Blue));
Brush brushLombada = new SolidBrush(Color.FromArgb(60, Color.Orange));
int imgWidth = img.Width;
int imgHeight = img.Height;
// 🔸 Desenhar Bounding Boxes (Anomalias + Solo)
List<VisualWorkerMessageAnaliseBBoxModel> bboxes = new List<VisualWorkerMessageAnaliseBBoxModel>();
if (anomalias != null) bboxes.AddRange(anomalias);
if (solo?.bbox_list != null) bboxes.AddRange(solo.bbox_list);
foreach (var bbox in bboxes)
{
Pen pen = penObstaculo;
Brush fill = brushObstaculo;
if (bbox.tipo == "erosao")
{
pen = penErosao;
fill = brushErosao;
}
if (bbox.tipo == "lombada")
{
pen = penLombada;
fill = brushLombada;
}
var rect = new Rectangle(bbox.bbox[0], bbox.bbox[1], bbox.bbox[2], bbox.bbox[3]);
// 🔸 Preencher com opacidade
g.FillRectangle(fill, rect);
// 🔸 Contorno
g.DrawRectangle(pen, rect);
// 🔸 Label
string label = $"{bbox.tipo} {bbox.distancia_m}m Δ{bbox.variacao}mm";
g.DrawString(label, font, brush, rect.X, rect.Y - 12);
}
// 🔸 Linha da faixa do solo
if (solo != null)
{
int yInicio = solo.y_inicio;
g.DrawLine(penFaixaSolo, 0, yInicio, imgWidth, yInicio);
}
// 🔸 Gráfico do perfil de solo
if (solo?.perfil != null && solo.perfil.Count > 1)
{
var perfil = solo.perfil;
int setores = solo.n_setores;
int yInicio = solo.y_inicio;
int alturaRegiao = solo.altura_regiao;
double maxZ = perfil.Max();
double minZ = perfil.Min();
if (maxZ == minZ) maxZ += 1; // evita divisão por zero
for (int i = 0; i < perfil.Count - 1; i++)
{
float x1 = (float)(i * imgWidth / setores + imgWidth / (2.0 * setores));
float x2 = (float)((i + 1) * imgWidth / setores + imgWidth / (2.0 * setores));
float y1 = (float)(yInicio + alturaRegiao - ((perfil[i] - minZ) / (maxZ - minZ)) * alturaRegiao);
float y2 = (float)(yInicio + alturaRegiao - ((perfil[i + 1] - minZ) / (maxZ - minZ)) * alturaRegiao);
g.DrawLine(penGrafico, x1, y1, x2, y2);
g.FillEllipse(Brushes.DarkGreen, x1 - 3, y1 - 3, 6, 6);
}
// Desenha o último ponto
float xLast = (float)((perfil.Count - 1) * imgWidth / setores + imgWidth / (2.0 * setores));
float yLast = (float)(yInicio + alturaRegiao - ((perfil.Last() - minZ) / (maxZ - minZ)) * alturaRegiao);
g.FillEllipse(Brushes.DarkGreen, xLast - 3, yLast - 3, 6, 6);
}
}
return img;
}
}
public class VisualWorkerMessageAnaliseSoloModel
{
public List<double> perfil { get; set; }
public List<VisualWorkerMessageAnaliseBBoxModel> bbox_list { get; set; }
public int y_inicio { get; set; }
public int altura_regiao { get; set; }
public int n_setores { get; set; }
public VisualWorkerMessageAnaliseSoloModel Clone()
{
return new VisualWorkerMessageAnaliseSoloModel()
{
perfil = new List<double>(perfil),
bbox_list = new List<VisualWorkerMessageAnaliseBBoxModel>(bbox_list),
y_inicio = y_inicio,
altura_regiao = altura_regiao,
n_setores = n_setores
};
}
}
public class VisualWorkerMessageAnaliseBBoxModel
{
public string tipo { get; set; }
public List<int> bbox { get; set; } // [x, y, w, h]
public List<double> centro_percentual { get; set; } // [x%, y%]
public double? distancia_m { get; set; }
public double? largura_m { get; set; }
public double? altura_m { get; set; }
public List<double> profundidades { get; set; } // [z1, z2] ou null
public double? variacao { get; set; } // delta Z ou null
}
public enum VisualWorkerMessageType
{
TX = 1,
RX = 2
}
public enum VisualWorkerCommandType
{
Ping = 1,
Get_Status_Dispositivo = 2,
Get_RGB_Frame = 3,
Get_Heatmap_Frame = 4,
Calibrar_Grades = 5,
Get_Analise_Anomalia = 6,
Get_Analise_Solo = 7,
}
public enum VisualWorkerDetectionType
{
Seguro = 1,
Obstaculo = 2,
Depressao = 3,
}
public enum VisualWorkerRegionType
{
Solo = 1,
Aereo = 2,
}
public enum VisualWorkerAnaliseType
{
Anomalia = 1,
Solo = 2,
}
}