Cambios de directorio

This commit is contained in:
Miguel 2024-05-25 12:53:34 +02:00
parent 25da24d042
commit e54dba175a
44 changed files with 411 additions and 308 deletions

View File

@ -216,6 +216,28 @@ namespace CtrEditor.Convertidores
}
}
public class DoubleToFormattedStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double floatValue)
{
return floatValue.ToString("0.00", culture); // Formatear a dos decimales
}
return value; // Devolver el valor original si no es un float
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string stringValue && double.TryParse(stringValue, NumberStyles.Float, culture, out double result))
{
return result;
}
return value; // Devolver el valor original si no se puede convertir
}
}
public class UnitConverter
{
// La escala representa cuántos metros hay en un píxel

View File

@ -9,7 +9,6 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="ObjetosSim\ucBasicExample.xaml.cs" />
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
<Compile Remove="Simulacion\GeometrySimulator.cs" />
</ItemGroup>
@ -41,7 +40,6 @@
</ItemGroup>
<ItemGroup>
<Page Remove="ObjetosSim\ucBasicExample.xaml" />
<Page Remove="ObjetosSim\ucTransporteCurva.xaml" />
</ItemGroup>

View File

@ -4,30 +4,29 @@ using System.Windows.Controls;
using System.Windows.Input;
using Ookii.Dialogs.Wpf;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.Windows.Threading;
using CtrEditor.ObjetosSim;
using CtrEditor.Siemens;
using System.IO;
// using System.Windows.Forms;
using Newtonsoft.Json;
using System.Windows.Data;
using System.Windows;
using CtrEditor.Convertidores;
using CtrEditor.Simulacion;
using System.Diagnostics;
using System.Reflection;
using CommunityToolkit.Mvvm.ComponentModel;
namespace CtrEditor
{
public class MainViewModel : INotifyPropertyChanged
public partial class MainViewModel : ObservableObject
{
public DatosDeTrabajo datosDeTrabajo { get; }
public ObservableCollection<string> listaImagenes { get; private set; } // Publicación de las claves del diccionario
public ObservableCollection<TipoSimulable> ListaOsBase { get; } = new ObservableCollection<TipoSimulable>();
public Stopwatch stopwatch_PLCRefresh;
public Stopwatch stopwatch_SimRefresh;
public Stopwatch stopwatch_Sim;
private double stopwatch_SimPLC_last;
private double stopwatch_SimModel_last;
private float TiempoDesdeStartSimulacion;
private bool Debug_SimulacionCreado = false;
@ -35,6 +34,15 @@ namespace CtrEditor
private readonly DispatcherTimer _timerSimulacion;
[ObservableProperty]
private DatosDeTrabajo datosDeTrabajo;
[ObservableProperty]
private ObservableCollection<string> listaImagenes; // Publicación de las claves del diccionario
[ObservableProperty]
public ObservableCollection<TipoSimulable> listaOsBase;
public ICommand StartSimulationCommand { get; }
public ICommand StopSimulationCommand { get; }
public ICommand ItemDoubleClickCommand { get; private set; }
@ -48,7 +56,6 @@ namespace CtrEditor
public ICommand TBEliminarUserControlCommand { get; }
public ICommand TBDuplicarUserControlCommand { get; }
public ICommand OpenWorkDirectoryCommand { get; }
// Evento que se dispara cuando se selecciona una nueva imagen
@ -57,59 +64,34 @@ namespace CtrEditor
// Propiedades
private bool isSimulationRunning;
private bool isConnected;
private bool habilitarEliminarUserControl;
public PLCViewModel plcViewModelData;
private osBase _selectedItemOsList;
private string _selectedImage = null;
private float _left;
private float _top;
private MainWindow mainWindow;
public MainWindow MainWindow { get => mainWindow; set => mainWindow = value; }
public float CanvasLeft
{
get => _left;
set
{
_left = value;
OnPropertyChanged(nameof(CanvasLeft));
}
}
public float CanvasTop
{
get => _top;
set
{
_top = value;
OnPropertyChanged(nameof(CanvasTop));
}
}
[ObservableProperty]
private float canvasLeft;
public bool IsSimulationRunning
[ObservableProperty]
private float canvasTop;
[ObservableProperty]
private bool isSimulationRunning;
partial void OnIsSimulationRunningChanged(bool value)
{
get => isSimulationRunning;
set
{
isSimulationRunning = value;
OnPropertyChanged(nameof(IsSimulationRunning));
CommandManager.InvalidateRequerySuggested(); // Notificar que el estado de los comandos ha cambiado
}
}
public bool IsConnected
[ObservableProperty]
private bool isConnected;
partial void OnIsConnectedChanged(bool value)
{
get => isConnected;
set
{
isConnected = value;
OnPropertyChanged(nameof(IsConnected));
CommandManager.InvalidateRequerySuggested();
}
}
public string directorioTrabajo
{
@ -120,89 +102,50 @@ namespace CtrEditor
{
EstadoPersistente.Instance.directorio = value; // Actualizar el estado persistente
EstadoPersistente.Instance.GuardarEstado(); // Guardar el estado actualizado
datosDeTrabajo.CargarImagenes();
listaImagenes = new ObservableCollection<string>(datosDeTrabajo.Imagenes.Keys); // Actualizar claves
DatosDeTrabajo.CargarImagenes();
ListaImagenes = new ObservableCollection<string>(DatosDeTrabajo.Imagenes.Keys); // Actualizar claves
SelectedImage = null;
if (listaImagenes.FirstOrDefault() != null)
SelectedImage = listaImagenes.FirstOrDefault();
if (ListaImagenes.FirstOrDefault() != null)
SelectedImage = ListaImagenes.FirstOrDefault();
OnPropertyChanged(nameof(directorioTrabajo)); // Notificar el cambio de propiedad
OnPropertyChanged(nameof(listaImagenes)); // Notificar que la lista de imágenes ha cambiado
OnPropertyChanged(nameof(ListaImagenes)); // Notificar que la lista de imágenes ha cambiado
}
}
}
public PLCViewModel PLCViewModel
{
get { return plcViewModelData; }
set
{
plcViewModelData = value;
OnPropertyChanged(nameof(PLCViewModel));
}
}
[ObservableProperty]
private PLCViewModel pLCViewModel;
public string SelectedImage
[ObservableProperty]
private string selectedImage;
partial void OnSelectedImageChanged(string value)
{
get => _selectedImage;
set
{
if (_selectedImage != value && value != null)
if (value != null)
{
StopSimulation();
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
_selectedImage = value;
// SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
LoadStateObjetosSimulables();
}
_selectedImage = value;
OnPropertyChanged(nameof(SelectedImage));
}
}
public osBase SelectedItemOsList
{
get => _selectedItemOsList;
set
{
if (_selectedItemOsList != value)
[ObservableProperty]
private osBase selectedItemOsList;
partial void OnSelectedItemOsListChanged(osBase value)
{
if (value != null)
habilitarEliminarUserControl = true;
else
habilitarEliminarUserControl = false;
_selectedItemOsList = value;
OnPropertyChanged(nameof(SelectedItemOsList));
}
}
}
private TipoSimulable _selectedItem = null;
public TipoSimulable SelectedItem
{
get => _selectedItem;
set
{
if (_selectedItem != value)
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem)); // Notificar que la propiedad ha cambiado
}
}
}
[ObservableProperty]
private TipoSimulable selectedItem;
public ObservableCollection<osBase> ObjetosSimulables
{
get => _objetosSimulables;
set
{
if (_objetosSimulables != value)
{
_objetosSimulables = value;
OnPropertyChanged(nameof(ObjetosSimulables));
}
}
}
[ObservableProperty]
public ObservableCollection<osBase> objetosSimulables;
//
// Constructor
@ -213,9 +156,12 @@ namespace CtrEditor
OpenWorkDirectoryCommand = new RelayCommand(OpenWorkDirectory);
datosDeTrabajo = new DatosDeTrabajo();
ObjetosSimulables = new ObservableCollection<osBase>();
ListaOsBase = new ObservableCollection<TipoSimulable>();
// Inicializa el PLCViewModel
plcViewModelData = new PLCViewModel();
plcViewModelData.RefreshEvent += OnRefreshEvent;
PLCViewModel = new PLCViewModel();
PLCViewModel.RefreshEvent += OnRefreshEvent;
InitializeTipoSimulableList();
@ -237,8 +183,8 @@ namespace CtrEditor
TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl);
TBDuplicarUserControlCommand = new RelayCommand(DuplicarUserControl, () => habilitarEliminarUserControl);
stopwatch_PLCRefresh = new Stopwatch();
stopwatch_SimRefresh = new Stopwatch();
stopwatch_Sim = new Stopwatch();
stopwatch_Sim.Start();
}
public void LoadInitialData()
@ -386,8 +332,6 @@ namespace CtrEditor
Debug_SimulacionCreado = true;
_timerSimulacion.Start();
simulationManager.stopwatch.Start();
stopwatch_SimRefresh.Start();
}
private void StopSimulation()
@ -403,24 +347,19 @@ namespace CtrEditor
Debug_SimulacionCreado = false;
}
_timerSimulacion.Stop();
simulationManager.stopwatch.Stop();
stopwatch_SimRefresh.Stop();
}
private void OnTickSimulacion(object sender, EventArgs e)
{
// Detener el cronómetro y obtener el tiempo transcurrido en milisegundos
stopwatch_SimRefresh.Stop();
float elapsedMilliseconds = (float)stopwatch_SimRefresh.Elapsed.TotalMilliseconds;
var elapsedMilliseconds = stopwatch_Sim.Elapsed.TotalMilliseconds - stopwatch_SimModel_last;
stopwatch_SimModel_last = stopwatch_Sim.Elapsed.TotalMilliseconds;
// Eliminar el diseño de Debug luego de 2 segundos
if (TiempoDesdeStartSimulacion > 2000)
simulationManager.Debug_ClearSimulationShapes();
else
TiempoDesdeStartSimulacion += elapsedMilliseconds;
// Reiniciar el cronómetro para la próxima medición
stopwatch_SimRefresh.Restart();
TiempoDesdeStartSimulacion += (float)elapsedMilliseconds;
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.UpdateGeometryStep();
@ -441,13 +380,12 @@ namespace CtrEditor
private void ConnectPLC()
{
plcViewModelData.Connect();
PLCViewModel.Connect();
}
private void DisconnectPLC()
{
plcViewModelData.Disconnect();
PLCViewModel.Disconnect();
IsConnected = false;
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.SetPLC(null);
@ -456,28 +394,23 @@ namespace CtrEditor
private void OnRefreshEvent(object sender, EventArgs e)
{
if (plcViewModelData.IsConnected)
if (PLCViewModel.IsConnected)
{
if (!isConnected)
{
IsConnected = true;
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.SetPLC(plcViewModelData.PLCInterface);
objetoSimulable.SetPLC(PLCViewModel.PLCInterface);
}
// Detener el cronómetro y obtener el tiempo transcurrido en milisegundos
stopwatch_PLCRefresh.Stop();
float elapsedMilliseconds = (float)stopwatch_PLCRefresh.Elapsed.TotalMilliseconds;
var elapsedMilliseconds = stopwatch_Sim.Elapsed.TotalMilliseconds - stopwatch_SimPLC_last;
stopwatch_SimPLC_last = stopwatch_Sim.Elapsed.TotalMilliseconds;
// Reiniciar el cronómetro para la próxima medición
stopwatch_PLCRefresh.Restart();
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.UpdatePLC(plcViewModelData.PLCInterface, (int) elapsedMilliseconds);
} else
stopwatch_PLCRefresh.Stop();
objetoSimulable.UpdatePLC(PLCViewModel.PLCInterface, (int) elapsedMilliseconds);
}
}
private void OpenWorkDirectory()
@ -500,13 +433,13 @@ namespace CtrEditor
public void SaveStateObjetosSimulables()
{
if (_selectedImage != null)
if (SelectedImage != null)
{
StopSimulation();
DisconnectPLC();
// Ruta del archivo a ser guardado
var path = datosDeTrabajo.ObtenerPathImagenConExtension(_selectedImage, ".json");
var path = DatosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
// Verificar si el archivo ya existe y crear un respaldo
if (File.Exists(path))
@ -552,9 +485,9 @@ namespace CtrEditor
DisconnectPLC();
ObjetosSimulables.Clear();
simulationManager.Clear();
if (_selectedImage != null)
if (SelectedImage != null)
{
string jsonPath = datosDeTrabajo.ObtenerPathImagenConExtension(_selectedImage, ".json");
string jsonPath = datosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
if (File.Exists(jsonPath))
{
string jsonString = File.ReadAllText(jsonPath);
@ -580,7 +513,7 @@ namespace CtrEditor
PixelToMeter.Instance.calc = simulationData.UnitConverter;
// Re-register to the events
plcViewModelData.RefreshEvent += OnRefreshEvent;
PLCViewModel.RefreshEvent += OnRefreshEvent;
// Recorrer la colección de objetos simulables
foreach (var objetoSimulable in ObjetosSimulables)
@ -598,14 +531,6 @@ namespace CtrEditor
UserControlFactory.CargarPropiedadesosDatos(selectedObject,PanelEdicion, Resources);
}
// Implementación de INotifyPropertyChanged...
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private RelayCommand saveCommand;
public ICommand SaveCommand => saveCommand ??= new RelayCommand(Save);
@ -624,15 +549,15 @@ namespace CtrEditor
}
public class SimulationData
{
public ObservableCollection<osBase> ObjetosSimulables { get; set; }
public UnitConverter UnitConverter { get; set; }
public PLCViewModel PLC_ConnectionData { get; set; }
public ObservableCollection<osBase>? ObjetosSimulables { get; set; }
public UnitConverter? UnitConverter { get; set; }
public PLCViewModel? PLC_ConnectionData { get; set; }
}
public class TipoSimulable
{
public string Nombre { get; set; }
public Type Tipo { get; set; }
public string? Nombre { get; set; }
public Type? Tipo { get; set; }
}
public class TickSimulacionEventArgs : EventArgs

View File

@ -15,6 +15,7 @@
<Window.Resources>
<convert:FloatToFormattedStringConverter x:Key="floatFormatter"/>
<convert:DoubleToFormattedStringConverter x:Key="doubleFormatter"/>
<convert:BrushToColorNameConverter x:Key="BrushToColorNameConverter"/>
<!-- Style for Start/Stop Button -->
@ -65,7 +66,7 @@
<RowDefinition Height="2*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox x:Name="ListaImagenes" Grid.Row="0" Margin="5" ItemsSource="{Binding listaImagenes}" SelectedItem="{Binding SelectedImage}" />
<ListBox x:Name="ListaImagenes" Grid.Row="0" Margin="5" ItemsSource="{Binding ListaImagenes}" SelectedItem="{Binding SelectedImage}" />
<ListBox x:Name="ListaFunciones" Grid.Row="1" Margin="5" ItemsSource="{Binding ListaOsBase}" DisplayMemberPath="Nombre" SelectedItem="{Binding SelectedItem}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">

View File

@ -28,25 +28,39 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
public float offsetLeftSalida;
private float offsetLeftSalida;
[ObservableProperty]
public float offsetTopSalida;
private float offsetTopSalida;
[ObservableProperty]
public bool consenso;
private bool consenso;
[ObservableProperty]
public float botellas_hora;
private float botellas_hora;
partial void OnBotellas_horaChanged(float value)
{
Botellas_segundo = value / 3600;
}
[ObservableProperty]
public float velocidad_actual_percentual;
private float botellas_segundo;
partial void OnBotellas_segundoChanged(float value)
{
Botellas_hora = value * 3600;
}
[ObservableProperty]
public float diametro_botella;
private float velocidad_actual_percentual;
[ObservableProperty]
public string tag_consenso;
private float diametro_botella;
[ObservableProperty]
public float ancho;
private string tag_consenso;
[ObservableProperty]
public float alto;
private float ancho;
[ObservableProperty]
public float angulo;
private float alto;
[ObservableProperty]
private float angulo;
public osFiller()
{
@ -70,7 +84,7 @@ namespace CtrEditor.ObjetosSim
TiempoRestante -= elapsedMilliseconds / 1000.0f;
if (TiempoRestante <= 0)
{
TiempoRestante = 3600 / (Botellas_hora * (Velocidad_actual_percentual / 100.0f));
TiempoRestante += 3600 / (Botellas_hora * (Velocidad_actual_percentual / 100.0f));
var X = Left + OffsetLeftSalida;
var Y = Top + OffsetTopSalida;

View File

@ -20,7 +20,6 @@ namespace CtrEditor.ObjetosSim
private float _velocidadActual;
private osBase _osMotor = null;
private string _motor;
private simCurve Simulation_TransporteCurva;
@ -101,7 +100,7 @@ namespace CtrEditor.ObjetosSim
VelocidadActual = motor.Velocidad;
}
else
_osMotor = ObtenerLink(_motor, typeof(osVMmotorSim));
_osMotor = ObtenerLink(Motor, typeof(osVMmotorSim));
}
public override void ucLoaded()

View File

@ -30,21 +30,14 @@ namespace CtrEditor.ObjetosSim
set => SetProperty(ref nombre, value);
}
[ObservableProperty]
private float velocidadActual;
public float VelocidadActual
partial void OnVelocidadActualChanged(float value)
{
get => velocidadActual;
set
{
if (value != velocidadActual)
{
velocidadActual = value;
SimGeometria?.SetSpeed(value);
SetProperty(ref velocidadActual, value);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
}
}
[ObservableProperty]
public string motor;
@ -58,6 +51,12 @@ namespace CtrEditor.ObjetosSim
public float ancho;
[ObservableProperty]
public float alto;
partial void OnAltoChanged(float value)
{
ActualizarGeometrias();
}
[ObservableProperty]
public float angulo;
[ObservableProperty]
@ -81,6 +80,7 @@ namespace CtrEditor.ObjetosSim
UpdateOrCreateLine(Guia_Superior, uc.GuiaSuperior);
UpdateOrCreateLine(Guia_Inferior, uc.GuiaInferior) ;
SimGeometria.DistanceGuide2Guide = Alto;
SimGeometria.Speed = VelocidadActual;
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
@ -126,6 +126,8 @@ namespace CtrEditor.ObjetosSim
if (_visualRepresentation is ucTransporteGuias uc)
{
SimGeometria = AddRectangle(simulationManager, uc.Transporte, Alto, Ancho, Angulo);
SimGeometria.TransportWithGuides = true;
SimGeometria.DistanceGuide2Guide = Alto;
Guia_Superior = AddLine(simulationManager, uc.GuiaSuperior);
Guia_Inferior = AddLine(simulationManager, uc.GuiaInferior);

View File

@ -0,0 +1,46 @@
<UserControl x:Class="CtrEditor.ObjetosSim.ucGearEncoder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
xmlns:convert="clr-namespace:CtrEditor.Convertidores">
<UserControl.Resources>
<convert:MeterToPixelConverter x:Key="MeterToPixelConverter"/>
</UserControl.Resources>
<UserControl.DataContext>
<vm:osGearEncoder Dientes="9"/>
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1}"/>
<ColumnDefinition Width="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=0.02}"/>
<!-- Espacio entre el Rectangle y el Canvas -->
<ColumnDefinition Width="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1}"/>
</Grid.ColumnDefinitions>
<!-- StackPanel to contain the Rectangle -->
<Canvas Grid.Column="0" HorizontalAlignment="Right">
<Rectangle Canvas.Top="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=-0.12}"
Grid.Column="0" Width="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1}"
Height="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=0.25}"
Fill="{Binding Color_oculto}"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Canvas>
<Canvas Grid.Column="0" HorizontalAlignment="Left">
<Canvas.RenderTransform>
<RotateTransform Angle="{Binding Angulo}" CenterX="0" CenterY="0"/>
</Canvas.RenderTransform>
<local:GearControl ToothWidthRatio="{Binding Ancho_Dientes}" TeethCount="{Binding Dientes}"
InnerRadius="{Binding Radio_Interno, Converter={StaticResource MeterToPixelConverter}}"
OuterRadius="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Canvas>
</Grid>
</UserControl>

View File

@ -5,8 +5,9 @@ using System.Windows.Controls;
using System.Windows.Media;
using Newtonsoft.Json;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Diagnostics;
namespace CtrEditor.ObjetosSim.UserControls
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucGearEncoder.xaml
@ -14,6 +15,8 @@ namespace CtrEditor.ObjetosSim.UserControls
public partial class osGearEncoder : osBase, IosBase
{
private osBase _osMotor = null;
private Stopwatch Stopwatch = new Stopwatch();
private double stopwatch_last = 0;
// Otros datos y métodos relevantes para la simulación
@ -21,6 +24,7 @@ namespace CtrEditor.ObjetosSim.UserControls
{
return "Ruota Fonica";
}
private string nombre = NombreClase();
public override string Nombre
{
@ -32,10 +36,56 @@ namespace CtrEditor.ObjetosSim.UserControls
public string tag;
[ObservableProperty]
public bool pulso;
partial void OnPulsoChanged(bool value)
{
if (value)
{
var dTime = Stopwatch.ElapsedMilliseconds - stopwatch_last;
stopwatch_last = Stopwatch.ElapsedMilliseconds;
Tiempo_Pulso = (float)dTime;
}
EscribirBitTag(Tag, Pulso);
if (value)
Color_oculto = Brushes.LightGreen;
else
Color_oculto = Brushes.Gray;
}
[ObservableProperty]
private Brush color_oculto;
[ObservableProperty]
public float velocidadActual;
[ObservableProperty]
public float angulo;
public double angulo;
partial void OnAnguloChanged(double value)
{
// Generar pulsos cuadrados en función del ángulo
Pulso = DetectarDiente();
}
[ObservableProperty]
public float tiempo_Pulso;
[ObservableProperty]
public float pulsos_Por_Segundo;
partial void OnPulsos_Por_SegundoChanged(float value)
{
if (VelocidadActual > 0)
Giros_segundo_a_100 = (float)((pulsos_Por_Segundo / Dientes) * 100 / VelocidadActual);
}
[ObservableProperty]
private bool homing;
partial void OnHomingChanged(bool value)
{
homing = false;
Angulo = 0;
}
[ObservableProperty]
public float dientes;
[ObservableProperty]
@ -45,7 +95,7 @@ namespace CtrEditor.ObjetosSim.UserControls
[ObservableProperty]
public float ancho_Dientes;
[ObservableProperty]
public float giros_segundo_a_50hz;
public float giros_segundo_a_100;
[ObservableProperty]
public string motor;
@ -54,13 +104,14 @@ namespace CtrEditor.ObjetosSim.UserControls
_osMotor = ObtenerLink(Motor, typeof(osVMmotorSim));
}
public osGearEncoder()
{
Ancho_Dientes = 0.5f;
Dientes = 10;
Radio_Interno = 0.5f;
Radio_Externo = 0.6f;
Color_oculto = Brushes.Gray;
Stopwatch.Start();
}
public override void UpdateGeometryStart()
@ -77,7 +128,7 @@ namespace CtrEditor.ObjetosSim.UserControls
VelocidadActual = motor.Velocidad;
// Calcular la cantidad de giros por segundo
double girosPorSegundo = (VelocidadActual / 50.0) * Giros_segundo_a_50hz;
double girosPorSegundo = (VelocidadActual / 100.0) * Giros_segundo_a_100;
// Calcular la fracción del segundo que ha pasado
double segundosTranscurridos = elapsedMilliseconds / 1000.0;
@ -86,20 +137,48 @@ namespace CtrEditor.ObjetosSim.UserControls
double incrementoAngulo = (girosPorSegundo * 360.0) * segundosTranscurridos;
// Actualizar el ángulo
Angulo = (float)(Angulo + incrementoAngulo) % 360;
// Calcular la duración de un pulso
double duracionPulso = (360.0 / Dientes) / 2;
// Generar pulsos cuadrados en función del ángulo
Pulso = ((Angulo % (360.0 / Dientes)) < duracionPulso) ? true : false;
EscribirBitTag(Tag,Pulso);
Angulo = (Angulo + incrementoAngulo) % 360;
}
} else if (Motor.Length>0)
_osMotor = ObtenerLink(Motor, typeof(osVMmotorSim));
}
public bool DetectarDiente()
{
double angleStep = 360.0 / Dientes;
double halfToothWidthAngle = (angleStep * Ancho_Dientes) / 2;
// Normalize the Angulo to be within 0-360 degrees
double normalizedAngle = Angulo % 360;
if (normalizedAngle < 0) normalizedAngle += 360;
// Calculate the position of the first tooth's center at angle 0
double firstToothCenterAngle = 0;
// Calculate the angular distance from the current angle to the first tooth's center
double angularDistance = Math.Abs(firstToothCenterAngle - normalizedAngle);
if (angularDistance > 180) angularDistance = 360 - angularDistance;
// Check if the normalized angle falls within the segment of the first tooth
if (angularDistance <= halfToothWidthAngle)
{
return true;
}
// Calculate the number of steps to reach the nearest tooth's center
int steps = (int)Math.Round(normalizedAngle / angleStep);
// Calculate the angular position of the nearest tooth's center
double nearestToothCenterAngle = steps * angleStep;
// Calculate the angular distance from the current angle to the nearest tooth's center
angularDistance = Math.Abs(nearestToothCenterAngle - normalizedAngle);
if (angularDistance > 180) angularDistance = 360 - angularDistance;
// Check if the normalized angle falls within the segment of the nearest tooth
return angularDistance <= halfToothWidthAngle;
}
public override void UpdateControl(int elapsedMilliseconds)
{

View File

@ -1,11 +1,11 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.ucPhotocell"
<UserControl x:Class="CtrEditor.ObjetosSim.ucPhotocell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
xmlns:convert="clr-namespace:CtrEditor.Convertidores">
<UserControl.Resources>

View File

@ -7,7 +7,7 @@ using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
namespace CtrEditor.ObjetosSim.UserControls
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucPhotocell.xaml

View File

@ -1,4 +1,4 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.ucAnalogTag"
<UserControl x:Class="CtrEditor.ObjetosSim.ucAnalogTag"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
@ -6,7 +6,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:convert="clr-namespace:CtrEditor.Convertidores"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
mc:Ignorable="d">
<UserControl.Resources>

View File

@ -6,7 +6,7 @@ using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json.Linq;
namespace CtrEditor.ObjetosSim.UserControls
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucAnalogTag.xaml
@ -32,17 +32,23 @@ namespace CtrEditor.ObjetosSim.UserControls
[ObservableProperty]
public float tamano;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
public string tag;
[ObservableProperty]
public string descripcion;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
public float min_IN_Scaled;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
public float max_IN_Scaled;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
public float min_OUT_Scaled;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
public float max_OUT_Scaled;
[ObservableProperty]
public float value;

View File

@ -1,4 +1,4 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.ucBoolTag"
<UserControl x:Class="CtrEditor.ObjetosSim.ucBoolTag"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
@ -6,7 +6,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:convert="clr-namespace:CtrEditor.Convertidores"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
mc:Ignorable="d">
<UserControl.Resources>

View File

@ -4,8 +4,9 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json.Linq;
namespace CtrEditor.ObjetosSim.UserControls
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucBoolTag.xaml
@ -31,8 +32,12 @@ namespace CtrEditor.ObjetosSim.UserControls
[ObservableProperty]
private Brush color_oculto;
[ObservableProperty]
public bool estado;
partial void OnEstadoChanged(bool value)
{
EscribirBitTag(Tag, value);
if (value)
Color_oculto = Brushes.LightGreen;
else
@ -42,12 +47,11 @@ namespace CtrEditor.ObjetosSim.UserControls
[ObservableProperty]
public float tamano;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Estado))]
public string tag;
[ObservableProperty]
public string descripcion;
[ObservableProperty]
public bool estado;
public osBoolTag()
{
@ -56,22 +60,6 @@ namespace CtrEditor.ObjetosSim.UserControls
Descripcion = "Nombre del Tag";
}
public override void UpdateGeometryStart()
{
// Se llama antes de la simulacion
}
public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds)
{
plc.EscribirTagBool(Tag, Estado);
}
public override void UpdateControl(int elapsedMilliseconds)
{
// Calculamos la velocidad
}
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para

View File

@ -1,10 +1,10 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.ucConsensGeneric"
<UserControl x:Class="CtrEditor.ObjetosSim.ucConsensGeneric"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
xmlns:convert="clr-namespace:CtrEditor.Convertidores"
Background="LightGray">

View File

@ -5,7 +5,7 @@ using System.Windows;
using System.Windows.Controls;
namespace CtrEditor.ObjetosSim.UserControls
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucConsensGeneric.xaml

View File

@ -102,7 +102,7 @@ namespace CtrEditor.ObjetosSim
Grid.SetColumn(label, 0);
grid.Children.Add(label);
if (property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
{
var textBox = new TextBox
{
@ -123,6 +123,11 @@ namespace CtrEditor.ObjetosSim
if (Resources != null)
binding.Converter = (FloatToFormattedStringConverter)Resources["floatFormatter"];
}
if (property.PropertyType == typeof(double))
{
if (Resources != null)
binding.Converter = (DoubleToFormattedStringConverter)Resources["doubleFormatter"];
}
textBox.SetBinding(TextBox.TextProperty, binding);
@ -226,7 +231,7 @@ namespace CtrEditor.ObjetosSim
Grid.SetColumn(label, 0);
grid.Children.Add(label);
if (property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
{
var textBox = new TextBox
{
@ -247,6 +252,11 @@ namespace CtrEditor.ObjetosSim
if (Resources != null)
binding.Converter = (FloatToFormattedStringConverter)Resources["floatFormatter"];
}
if (property.PropertyType == typeof(double))
{
if (Resources != null)
binding.Converter = (DoubleToFormattedStringConverter)Resources["doubleFormatter"];
}
textBox.SetBinding(TextBox.TextProperty, binding);

View File

@ -1,16 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CtrEditor.ObjetosSim.UserControls
@ -94,8 +84,25 @@ namespace CtrEditor.ObjetosSim.UserControls
Canvas.SetTop(innerCircle, centerY - InnerRadius);
GearCanvas.Children.Add(innerCircle);
// Draw the zero angle marker
double zeroAngle = 0;
double radianZero = zeroAngle * Math.PI / 180;
double markerLength = InnerRadius * 1.2; // Length of the marker line extending outside the inner circle
Line zeroAngleMarker = new Line
{
X1 = centerX,
Y1 = centerY,
X2 = centerX + markerLength * Math.Cos(radianZero),
Y2 = centerY - markerLength * Math.Sin(radianZero),
Stroke = Brushes.Red,
StrokeThickness = 2
};
GearCanvas.Children.Add(zeroAngleMarker);
for (int i = 0; i < TeethCount; i++)
{
// Offset the angle to center the first tooth on the 0 angle
double angle = i * angleStep;
double radianStart = (angle - toothWidthAngle / 2) * Math.PI / 180;
double radianEnd = (angle + toothWidthAngle / 2) * Math.PI / 180;
@ -107,14 +114,16 @@ namespace CtrEditor.ObjetosSim.UserControls
Polygon tooth = new Polygon
{
Stroke = Brushes.Black,
StrokeThickness = 2,
Fill = Brushes.LightGray,
Fill = Brushes.Black,
Points = new PointCollection { p1, p2, p3, p4 }
};
GearCanvas.Children.Add(tooth);
}
}
}
}

View File

@ -1,29 +0,0 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.ucGearEncoder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:convert="clr-namespace:CtrEditor.Convertidores">
<UserControl.Resources>
<convert:MeterToPixelConverter x:Key="MeterToPixelConverter"/>
</UserControl.Resources>
<UserControl.DataContext>
<vm:osGearEncoder/>
</UserControl.DataContext>
<Canvas>
<Canvas.RenderTransform>
<RotateTransform Angle="{Binding Angulo}" CenterX="0" CenterY="0"/>
</Canvas.RenderTransform>
<local:GearControl ToothWidthRatio="{Binding Ancho_Dientes}" TeethCount="{Binding Dientes}"
InnerRadius="{Binding Radio_Interno, Converter={StaticResource MeterToPixelConverter}}"
OuterRadius="{Binding Radio_Externo, Converter={StaticResource MeterToPixelConverter}}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Canvas>
</UserControl>

View File

@ -423,14 +423,6 @@ namespace CtrEditor.ObjetosSim
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
[AttributeUsage(AttributeTargets.Property)]

View File

@ -42,7 +42,7 @@ namespace CtrEditor.Siemens
{
IsConnected = false;
PLCInterface = new PLCModel();
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1) };
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(30) };
_timer.Tick += (s, e) => Refresh();
ConnectCommand = new RelayCommand(Connect, () => true);

View File

@ -15,6 +15,7 @@ using System.Diagnostics;
using FarseerPhysics.Dynamics.Joints;
using CtrEditor.ObjetosSim;
using System.Windows.Documents;
namespace CtrEditor.Simulacion
{
@ -169,6 +170,8 @@ namespace CtrEditor.Simulacion
public class simTransporte : simBase
{
public float Speed { get; set; } // Velocidad para efectos de cinta transportadora
public float DistanceGuide2Guide { get; set; }
public bool TransportWithGuides = false;
public simTransporte(World world, float width, float height, Vector2 position, float angle = 0)
{
@ -318,7 +321,7 @@ namespace CtrEditor.Simulacion
private void Create(Vector2 position)
{
RemoverBody();
Body = BodyFactory.CreateCircle(_world, _radius, 1f, position);
Body = BodyFactory.CreateCircle(_world, _radius, 0.2f, position);
Body.BodyType = BodyType.Dynamic;
// Restablecer manejador de eventos de colisión
@ -328,13 +331,13 @@ namespace CtrEditor.Simulacion
Body.UserData = this; // Importante para la identificación durante la colisión
// Configurar la fricción
Body.Friction = 0.5f; // Ajustar según sea necesario para tu simulación
Body.Friction = 0.3f; // Ajustar según sea necesario para tu simulación
// Configurar amortiguamiento
Body.LinearDamping = 0f; // Ajustar para controlar la reducción de la velocidad lineal
Body.AngularDamping = 0f; // Ajustar para controlar la reducción de la velocidad angular
Body.LinearDamping = 0.4f; // Ajustar para controlar la reducción de la velocidad lineal
Body.AngularDamping = 0.4f; // Ajustar para controlar la reducción de la velocidad angular
Body.Restitution = 0.2f; // Baja restitución para menos rebote
Body.IsBullet = true;
// Body.IsBullet = true;
}
public void SetDiameter(float diameter)
@ -394,7 +397,11 @@ namespace CtrEditor.Simulacion
float porcentajeCompartido = InterseccionCirculoRectangulo.CalcularSuperficieCompartida(vertices, centroCirculo, radio);
// Aplicar el efecto del transportador usando el porcentaje calculado
if (conveyor.TransportWithGuides)
if (conveyor.DistanceGuide2Guide <= radio * 2)
CenterFixtureOnConveyor(fixtureA, conveyor);
ApplyConveyorEffect(conveyor, fixtureA, porcentajeCompartido);
}
return true; // No aplicar respuestas físicas
}
@ -407,6 +414,41 @@ namespace CtrEditor.Simulacion
Vector2 desiredVelocity = new Vector2((float)Math.Cos(conveyor.Body.Rotation), (float)Math.Sin(conveyor.Body.Rotation)) * speedMetersPerSecond;
circleFixture.Body.LinearVelocity += desiredVelocity * porcentajeCompartido;
}
private void CenterFixtureOnConveyor(Fixture fixtureA, simTransporte conveyor)
{
// Obtener el centro del conveyor
Vector2 conveyorCenter = conveyor.Body.Position;
// Calcular el vector de la línea horizontal centrada de conveyor
float halfDistance = conveyor.DistanceGuide2Guide / 2;
float cos = (float)Math.Cos(conveyor.Body.Rotation);
float sin = (float)Math.Sin(conveyor.Body.Rotation);
Vector2 offset = new Vector2(halfDistance * cos, halfDistance * sin);
// Línea horizontal centrada de conveyor en el espacio del mundo
Vector2 lineStart = conveyorCenter - offset;
Vector2 lineEnd = conveyorCenter + offset;
// Proyectar el centro de fixtureA sobre la línea horizontal
Vector2 fixtureCenter = fixtureA.Body.Position;
Vector2 closestPoint = ProjectPointOntoLine(fixtureCenter, lineStart, lineEnd);
// Mover fixtureA al punto más cercano en la línea horizontal
fixtureA.Body.Position = closestPoint;
}
private Vector2 ProjectPointOntoLine(Vector2 point, Vector2 lineStart, Vector2 lineEnd)
{
Vector2 lineDirection = lineEnd - lineStart;
lineDirection.Normalize();
Vector2 pointToLineStart = point - lineStart;
float projectionLength = Vector2.Dot(pointToLineStart, lineDirection);
return lineStart + projectionLength * lineDirection;
}
}
public class SimulationManagerFP
@ -415,7 +457,8 @@ namespace CtrEditor.Simulacion
private Canvas simulationCanvas;
public List<simBase> Cuerpos;
public Stopwatch stopwatch;
private Stopwatch stopwatch;
private double stopwatch_last;
public Canvas DebugCanvas { get => simulationCanvas; set => simulationCanvas = value; }
@ -424,6 +467,7 @@ namespace CtrEditor.Simulacion
world = new World(new Vector2(0, 0)); // Vector2.Zero
Cuerpos = new List<simBase>();
stopwatch = new Stopwatch();
stopwatch.Start();
}
public void Clear()
@ -437,11 +481,8 @@ namespace CtrEditor.Simulacion
public void Step()
{
// Detener el cronómetro y obtener el tiempo transcurrido en milisegundos
stopwatch.Stop();
float elapsedMilliseconds = (float)stopwatch.Elapsed.TotalMilliseconds;
// Reiniciar el cronómetro para la próxima medición
stopwatch.Restart();
float elapsedMilliseconds = (float) (stopwatch.Elapsed.TotalMilliseconds - stopwatch_last);
stopwatch_last = stopwatch.Elapsed.TotalMilliseconds;
// Pasar el tiempo transcurrido al método Step
world.Step(elapsedMilliseconds / 1000.0f);