using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using static System.Runtime.InteropServices.JavaScript.JSType; using CtrEditor.Convertidores; using CtrEditor.Siemens; using CtrEditor.Simulacion; using System.Windows.Media; using Microsoft.Xna.Framework; using FarseerPhysics.Dynamics; using Siemens.Simatic.Simulation.Runtime; using System.Windows.Media.Imaging; namespace CtrEditor.ObjetosSim { public interface IosBase { static abstract string NombreClase(); } public interface IDataContainer { [JsonIgnore] osBase? Datos { get; set; } void Resize(float width, float height); void Move(float Left, float Top); void Rotate(float Angle); void Highlight(bool State); int ZIndex(); } public abstract class osBase : INotifyPropertyChanged { public virtual string Nombre { get; set; } = "osBase"; public abstract float Left { get; set; } public abstract float Top { get; set; } public bool Inicializado = false; public bool AutoCreated = false; public bool RemoverDesdeSimulacion = false; // La simulacion indica que se debe remover [JsonIgnore] protected UserControl? _visualRepresentation = null; public abstract void UpdateControl(int elapsedMilliseconds); public abstract void UpdateGeometryStart(); public abstract void UpdateGeometryStep(); public abstract void UpdatePLC(PLCModel plc, int elapsedMilliseconds); public abstract void ucLoaded(); public abstract void ucUnLoaded(); [JsonIgnore] public MainViewModel _mainViewModel; [JsonIgnore] public UserControl? VisualRepresentation { get => _visualRepresentation; set => _visualRepresentation = value; } [JsonIgnore] public SimulationManagerFP simulationManager; protected osBase ObtenerLink(string NameLink, Type tipoOsBase) { if (!string.IsNullOrEmpty(NameLink) && _mainViewModel != null) { foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables) { if (tipoOsBase.IsInstanceOfType(objetoSimulable) && objetoSimulable.Nombre == NameLink) { return objetoSimulable; } } } return null; } public void ActualizarLeftTop() { Left = Left; Top = Top; } public bool LeerBitTag(PLCModel plc, string Tag) { if (!string.IsNullOrEmpty(Tag)) { if (Tag == "1") return true; else if (Tag == "0") return false; if (plc != null) return plc.LeerTagBool(Tag); } return false; } public void EscribirBitTag(PLCModel plc, string Tag, bool Value) { if (!string.IsNullOrEmpty(Tag)) if (plc != null) plc.EscribirTagBool(Tag, Value); } public void EscribirWordTagScaled(PLCModel plc, string Tag, float Value, float IN_scale_Min, float IN_scale_Max, float OUT_scale_Min, float OUT_scale_Max) { if (plc != null) if (!string.IsNullOrEmpty(Tag)) { SDataValue plcData = new SDataValue(); plcData.UInt16 = (ushort)((Value - IN_scale_Min) / (IN_scale_Max - IN_scale_Min) * (OUT_scale_Max - OUT_scale_Min) + OUT_scale_Min); plc.EscribirTag(Tag, plcData); } } public float LeerWordTagScaled(PLCModel plc, string Tag, float IN_scale_Min, float IN_scale_Max, float OUT_scale_Min, float OUT_scale_Max) { if (!string.IsNullOrEmpty(Tag)) { if (float.TryParse(Tag, out float v)) return v; if (plc != null) { SDataValue plcData = plc.LeerTag(Tag); float Value = plcData.UInt16; // WORD return (Value - OUT_scale_Min) / (OUT_scale_Max - OUT_scale_Min) * (IN_scale_Max - IN_scale_Min) + IN_scale_Min; } } return 0; } public void CanvasSetLeftinMeter(float left) { if (_visualRepresentation != null) Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(left)); } public float CanvasGetLeftinMeter() { if (_visualRepresentation != null) return PixelToMeter.Instance.calc.PixelsToMeters((float)Canvas.GetLeft(_visualRepresentation)); else return 0f; } public void CanvasSetTopinMeter(float top) { if (_visualRepresentation != null) Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(top)); } public float CanvasGetTopinMeter() { if (_visualRepresentation != null) return PixelToMeter.Instance.calc.PixelsToMeters((float)Canvas.GetTop(_visualRepresentation)); else return 0f; } public (Vector2 TopLeft, Vector2 BottomRight) GetRectangleCoordinatesInMeter(System.Windows.Shapes.Rectangle rect) { if (rect != null) { var _canvasLeft = CanvasGetLeftinMeter(); var _canvasTop = CanvasGetTopinMeter(); // Obtiene la transformada del objeto visual GeneralTransform transform = rect.TransformToAncestor(_visualRepresentation); // Obtiene la posición absoluta Point topLeft = transform.Transform(new Point(0, 0)); Point bottomRight = transform.Transform(new Point(rect.ActualWidth, rect.ActualHeight)); return (new Vector2(PixelToMeter.Instance.calc.PixelsToMeters((float)topLeft.X) + _canvasLeft, PixelToMeter.Instance.calc.PixelsToMeters((float)topLeft.Y) + _canvasTop), new Vector2(PixelToMeter.Instance.calc.PixelsToMeters((float)bottomRight.X) + _canvasLeft, PixelToMeter.Instance.calc.PixelsToMeters((float)bottomRight.Y) + _canvasTop)); } else return (new Vector2(0, 0), new Vector2(0, 0)); } public (Vector2 Start, Vector2 End) GetCenterLineVectors(System.Windows.Shapes.Rectangle rect) { if (rect == null) return (new Vector2(0, 0), new Vector2(0, 0)); var _canvasLeft = CanvasGetLeftinMeter(); var _canvasTop = CanvasGetTopinMeter(); var transform = rect.TransformToAncestor(_visualRepresentation); // Puntos en coordenadas locales del rectángulo no rotado Point startLocal = new Point(0, rect.ActualHeight / 2); Point endLocal = new Point(rect.ActualWidth, rect.ActualHeight / 2); // Transformar estos puntos al sistema de coordenadas del ancestro Point transformedStart = transform.Transform(startLocal); Point transformedEnd = transform.Transform(endLocal); // Convierte a unidades de Farseer (metros en este caso) Vector2 start = new Vector2(PixelToMeter.Instance.calc.PixelsToMeters((float)transformedStart.X) + _canvasLeft, PixelToMeter.Instance.calc.PixelsToMeters((float)transformedStart.Y) + _canvasTop); Vector2 end = new Vector2(PixelToMeter.Instance.calc.PixelsToMeters((float)transformedEnd.X) + _canvasLeft, PixelToMeter.Instance.calc.PixelsToMeters((float)transformedEnd.Y) + _canvasTop); return (start, end); } public Vector2 GetRectangleCenter(System.Windows.Shapes.Rectangle wpfRect) { var coords = GetRectangleCoordinatesInMeter(wpfRect); Vector2 topLeft = coords.TopLeft; Vector2 bottomRight = coords.BottomRight; // Calcular el centro, ancho y alto en metros return new Vector2((topLeft.X + bottomRight.X) / 2, (topLeft.Y + bottomRight.Y) / 2); } public void UpdateRectangle(simTransporte simRect, System.Windows.Shapes.Rectangle wpfRect, float Alto, float Ancho, float Angulo) { if (simRect != null) simRect.Create(Ancho, Alto, GetRectangleCenter(wpfRect), Angulo); } public void UpdateRectangle(simBarrera simRect, System.Windows.Shapes.Rectangle wpfRect, float Alto, float Ancho, float Angulo) { if (simRect != null) simRect.Create(Ancho, Alto, GetRectangleCenter(wpfRect), Angulo); } public simTransporte AddRectangle(SimulationManagerFP simulationManager, System.Windows.Shapes.Rectangle wpfRect, float Alto, float Ancho, float Angulo) { return simulationManager.AddRectangle(Ancho, Alto, GetRectangleCenter(wpfRect), Angulo); } public simBarrera AddBarrera(SimulationManagerFP simulationManager, System.Windows.Shapes.Rectangle wpfRect, float Alto, float Ancho, float Angulo) { return simulationManager.AddBarrera(Ancho, Alto, GetRectangleCenter(wpfRect), Angulo); } public void UpdateOrCreateLine(simGuia simGuia, System.Windows.Shapes.Rectangle wpfRect) { if (simGuia != null) { var coords = GetCenterLineVectors(wpfRect); // Crear o actualizar simRectangle simGuia.Create(coords.Start, coords.End); // asumiendo que el ángulo inicial es 0 } } public simGuia AddLine(SimulationManagerFP simulationManager, System.Windows.Shapes.Rectangle wpfRect) { var coords = GetCenterLineVectors(wpfRect); return simulationManager.AddLine(coords.Start, coords.End); } public ImageSource ImageFromPath(string value) { if (value is string stringValue) { return new BitmapImage(new Uri(stringValue, UriKind.RelativeOrAbsolute)); } return null; } static protected T GetLastElement(List list) where T : class { if (list.Count > 0) { return list[list.Count - 1]; } else { return null; } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } [AttributeUsage(AttributeTargets.Property)] public class HiddenAttribute : Attribute { } }