169 lines
5.9 KiB
C#
169 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Data;
|
|
|
|
namespace OperationControl.Controls.Pulverizador
|
|
{
|
|
class Converters
|
|
{
|
|
}
|
|
|
|
public class AlturaBarraToMarginFisicaConverter : IValueConverter
|
|
{
|
|
public double GroundTop { get; set; } = 80.0; // Y do solo
|
|
public double Top80Px { get; set; } = 20.0; // Y da barra quando está a 80 cm
|
|
public double AlturaMaxCm { get; set; } = 80.0;
|
|
public double BarraOffset { get; set; } = 13.0;
|
|
|
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
if (value is double alturaCm)
|
|
{
|
|
alturaCm = Math.Clamp(alturaCm, 0, AlturaMaxCm);
|
|
|
|
double distanciaPx = GroundTop - Top80Px; // px que representam 80 cm
|
|
double pxPorCm = distanciaPx / AlturaMaxCm; // regra de 3
|
|
double alturaPx = alturaCm * pxPorCm;
|
|
|
|
double yBarra = GroundTop - alturaPx; // Y da barra na GRID
|
|
|
|
double marginTop = yBarra - BarraOffset; // compensa o offset interno
|
|
|
|
return new Thickness(33, marginTop, 33, 0);
|
|
}
|
|
|
|
return new Thickness(33, 0, 33, 0);
|
|
}
|
|
|
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
=> System.Windows.Data.Binding.DoNothing;
|
|
}
|
|
|
|
public class BicoPositionFisicaConverter : IMultiValueConverter
|
|
{
|
|
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
if (values.Length < 5)
|
|
return 0.0;
|
|
|
|
if (values[0] is not double barraWidth ||
|
|
values[1] is not int index ||
|
|
values[2] is not int qtd ||
|
|
values[3] is not double distEntreBicosCm ||
|
|
values[4] is not double comprimentoBarraCm)
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
if (qtd <= 0 || barraWidth <= 0 || comprimentoBarraCm <= 0)
|
|
return 0.0;
|
|
|
|
// garante valores válidos
|
|
distEntreBicosCm = Math.Max(0.0, distEntreBicosCm);
|
|
|
|
if (qtd == 1)
|
|
{
|
|
// 1 bico: centro da barra
|
|
return barraWidth / 2.0;
|
|
}
|
|
|
|
// span "ideal" em cm (do primeiro ao último bico)
|
|
double spanIdealCm = (qtd - 1) * distEntreBicosCm;
|
|
|
|
// Se o span ideal for maior que a barra física, comprimimos
|
|
double escala = 1.0;
|
|
if (spanIdealCm > comprimentoBarraCm && qtd > 1)
|
|
{
|
|
escala = comprimentoBarraCm / spanIdealCm;
|
|
}
|
|
|
|
double distEfetivaCm = distEntreBicosCm * escala;
|
|
double spanEfetivoCm = (qtd - 1) * distEfetivaCm;
|
|
|
|
// centraliza o conjunto de bicos na barra
|
|
double offsetCm = (comprimentoBarraCm - spanEfetivoCm) / 2.0;
|
|
|
|
// posição em cm do bico atual
|
|
double xCm = offsetCm + index * distEfetivaCm;
|
|
|
|
// regra de 3: cm → px
|
|
double pxPorCm = barraWidth / comprimentoBarraCm;
|
|
double xPx = xCm * pxPorCm;
|
|
|
|
return xPx;
|
|
}
|
|
|
|
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
|
=> throw new NotImplementedException();
|
|
}
|
|
|
|
public class RuaWidthFisicaConverter : IMultiValueConverter
|
|
{
|
|
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
if (values.Length < 3) return 0.0;
|
|
|
|
if (values[0] is not double totalWidth ||
|
|
values[1] is not double larguraRuaCm ||
|
|
values[2] is not double comprimentoBarraCm ||
|
|
totalWidth <= 0 || comprimentoBarraCm <= 0 || larguraRuaCm <= 0)
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
// px por cm na faixa do solo (usando comprimento da barra como referência física)
|
|
double pxPorCm = totalWidth / comprimentoBarraCm;
|
|
double widthPx = larguraRuaCm * pxPorCm;
|
|
|
|
// não deixa a rua ficar maior que a área disponível
|
|
if (widthPx > totalWidth) widthPx = totalWidth;
|
|
|
|
return widthPx;
|
|
}
|
|
|
|
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
|
=> throw new NotImplementedException();
|
|
}
|
|
|
|
public class RuaOffsetFisicaConverter : IMultiValueConverter
|
|
{
|
|
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
if (values.Length < 4) return new Thickness(0);
|
|
|
|
if (values[0] is not double totalWidth ||
|
|
values[1] is not double erroLateralCm ||
|
|
values[2] is not double larguraRuaCm ||
|
|
values[3] is not double comprimentoBarraCm ||
|
|
totalWidth <= 0 || comprimentoBarraCm <= 0)
|
|
{
|
|
return new Thickness(0);
|
|
}
|
|
|
|
double pxPorCm = totalWidth / comprimentoBarraCm;
|
|
double widthPx = Math.Min(totalWidth, Math.Max(0, larguraRuaCm * pxPorCm));
|
|
|
|
double center = totalWidth / 2.0;
|
|
|
|
// erro > 0 = robô desviado pra direita → rua aparece indo pra esquerda
|
|
double roadCenter = center - erroLateralCm * pxPorCm;
|
|
|
|
double left = roadCenter - widthPx / 2.0;
|
|
|
|
// SEM travas aqui: pode ser negativo ou maior que totalWidth
|
|
// o Grid com ClipToBounds cuida de cortar o desenho
|
|
|
|
return new Thickness(left, 0, 0, 0);
|
|
}
|
|
|
|
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
|
=> throw new NotImplementedException();
|
|
}
|
|
|
|
}
|