using CtrEditor.Convertidores; using CtrEditor.Siemens; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using Newtonsoft.Json; using CommunityToolkit.Mvvm.ComponentModel; using System.Diagnostics; namespace CtrEditor.ObjetosSim { /// /// Interaction logic for ucGearEncoder.xaml /// 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 public static string NombreClase() { return "Ruota Fonica"; } private string nombre = NombreClase(); public override string Nombre { get => nombre; set => SetProperty(ref nombre, value); } [ObservableProperty] 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 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] public float radio_Interno; [ObservableProperty] public float radio_Externo; [ObservableProperty] public float ancho_Dientes; [ObservableProperty] public float giros_segundo_a_100; [ObservableProperty] public string motor; partial void OnMotorChanged(string value) { _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() { // Se llama antes de la simulacion } public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds) { if (_osMotor != null) { if (_osMotor is osVMmotorSim motor) { VelocidadActual = motor.Velocidad; // Calcular la cantidad de giros por segundo double girosPorSegundo = (VelocidadActual / 100.0) * Giros_segundo_a_100; // Calcular la fracción del segundo que ha pasado double segundosTranscurridos = elapsedMilliseconds / 1000.0; // Calcular el incremento de ángulo double incrementoAngulo = (girosPorSegundo * 360.0) * segundosTranscurridos; // Actualizar el ángulo 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) { // Calculamos la velocidad } public override void ucLoaded() { // El UserControl ya se ha cargado y podemos obtener las coordenadas para // crear el objeto de simulacion ActualizarLeftTop(); } } public partial class ucGearEncoder : UserControl, IDataContainer { public osBase? Datos { get; set; } public ucGearEncoder() { InitializeComponent(); this.Loaded += OnLoaded; this.Unloaded += OnUnloaded; } private void OnLoaded(object sender, RoutedEventArgs e) { Datos?.ucLoaded(); } private void OnUnloaded(object sender, RoutedEventArgs e) { Datos?.ucUnLoaded(); } public void Resize(float width, float height) { } public void Move(float LeftPixels, float TopPixels) { if (Datos != null) { Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels); Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels); } } public void Rotate(float Angle) { } public void Highlight(bool State) { } public int ZIndex() { return 10; } } }