diff --git a/CtrEditor.csproj b/CtrEditor.csproj index acafe06..84e6647 100644 --- a/CtrEditor.csproj +++ b/CtrEditor.csproj @@ -12,13 +12,22 @@ - + + + + + + + + + + @@ -36,18 +45,16 @@ - - - + @@ -62,8 +69,15 @@ + + + + + + + diff --git a/CtrEditorE.png b/CtrEditorE.png new file mode 100644 index 0000000..59934f0 Binary files /dev/null and b/CtrEditorE.png differ diff --git a/Icons/CtrEditorA.png b/Icons/CtrEditorA.png new file mode 100644 index 0000000..95ae8e1 Binary files /dev/null and b/Icons/CtrEditorA.png differ diff --git a/Icons/CtrEditorC.png b/Icons/CtrEditorC.png new file mode 100644 index 0000000..1f8c253 Binary files /dev/null and b/Icons/CtrEditorC.png differ diff --git a/Icons/CtrEditorE.png b/Icons/CtrEditorE.png new file mode 100644 index 0000000..ad31475 Binary files /dev/null and b/Icons/CtrEditorE.png differ diff --git a/Icons/app.png b/Icons/app.png new file mode 100644 index 0000000..b1ff3c6 Binary files /dev/null and b/Icons/app.png differ diff --git a/Icons/app2.png b/Icons/app2.png new file mode 100644 index 0000000..63aa6e1 Binary files /dev/null and b/Icons/app2.png differ diff --git a/MainViewModel.cs b/MainViewModel.cs index 8b898b6..df0ca61 100644 --- a/MainViewModel.cs +++ b/MainViewModel.cs @@ -348,6 +348,8 @@ namespace CtrEditor if (NuevoObjetoDuplicado != null) { NuevoObjetoDuplicado.Nombre += "_Duplicado"; + NuevoObjetoDuplicado.Left += 0.5f; + NuevoObjetoDuplicado.Top += 0.5f; ObjetosSimulables.Add(NuevoObjetoDuplicado); CrearUserControlDesdeObjetoSimulable(NuevoObjetoDuplicado); } diff --git a/MainWindow.xaml b/MainWindow.xaml index 1adaa0e..1013a61 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -7,7 +7,7 @@ xmlns:convert="clr-namespace:CtrEditor.Convertidores" xmlns:ObjetosSim="clr-namespace:CtrEditor.ObjetosSim" x:Class="CtrEditor.MainWindow" Height="900" Width="1600" WindowState="Maximized" - ResizeMode="CanResize" Title="{Binding directorioTrabajo}"> + ResizeMode="CanResize" Title="{Binding directorioTrabajo}" Icon="/app2.png"> diff --git a/ObjetosSim/UserControls/ucBoton.xaml.cs b/ObjetosSim/UserControls/ucBoton.xaml.cs index 666d693..2b634be 100644 --- a/ObjetosSim/UserControls/ucBoton.xaml.cs +++ b/ObjetosSim/UserControls/ucBoton.xaml.cs @@ -1,19 +1,9 @@ using CtrEditor.Convertidores; using CtrEditor.Siemens; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; 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 { diff --git a/ObjetosSim/UserControls/ucFiller.xaml.cs b/ObjetosSim/UserControls/ucFiller.xaml.cs index 7ff7e0f..1edfe4d 100644 --- a/ObjetosSim/UserControls/ucFiller.xaml.cs +++ b/ObjetosSim/UserControls/ucFiller.xaml.cs @@ -40,7 +40,7 @@ namespace CtrEditor.ObjetosSim private float TiempoRestante; private float _leftSalida; private float _topSalida; - private List Botellas = new List(); + private osBotella UltimaBotella; public static string NombreClase() { @@ -210,14 +210,16 @@ namespace CtrEditor.ObjetosSim var X = Left + OffsetLeftSalida; var Y = Top + OffsetTopSalida; - var UltimaBotella = GetLastElement(Botellas); + if (UltimaBotella != null && UltimaBotella.RemoverDesdeSimulacion) + UltimaBotella = null; + if (UltimaBotella == null) { // No hay botellas, se puede crear una nueva directamente var nuevaBotella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), X, Y); ((osBotella)nuevaBotella).Diametro = Diametro_botella; nuevaBotella.AutoCreated = true; - Botellas.Add((osBotella)nuevaBotella); + UltimaBotella = (osBotella)nuevaBotella; } else { @@ -230,7 +232,7 @@ namespace CtrEditor.ObjetosSim var nuevaBotella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), X, Y); ((osBotella)nuevaBotella).Diametro = Diametro_botella; nuevaBotella.AutoCreated = true; - Botellas.Add((osBotella)nuevaBotella); + UltimaBotella = (osBotella)nuevaBotella; } } } diff --git a/ObjetosSim/UserControls/ucPhotocell.xaml b/ObjetosSim/UserControls/ucPhotocell.xaml index 5e1854c..c6892f9 100644 --- a/ObjetosSim/UserControls/ucPhotocell.xaml +++ b/ObjetosSim/UserControls/ucPhotocell.xaml @@ -9,36 +9,42 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + \ No newline at end of file diff --git a/ObjetosSim/UserControls/ucPhotocell.xaml.cs b/ObjetosSim/UserControls/ucPhotocell.xaml.cs index d74f4b1..6dfd423 100644 --- a/ObjetosSim/UserControls/ucPhotocell.xaml.cs +++ b/ObjetosSim/UserControls/ucPhotocell.xaml.cs @@ -1,20 +1,10 @@ using CtrEditor.Convertidores; -using CtrEditor.Siemens; using CtrEditor.Simulacion; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using CtrEditor.Siemens; 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 { @@ -32,6 +22,7 @@ namespace CtrEditor.ObjetosSim.UserControls private bool _luzCortada; private string _tagPhotocellOUT; private bool _tipoNC; + private Brush _color; private simBarrera Simulation_Photocell; @@ -40,6 +31,15 @@ namespace CtrEditor.ObjetosSim.UserControls return "Photocell"; } + public Brush Color + { + get => _color; + set + { + _color = value; + OnPropertyChanged(nameof(Color)); + } + } public bool LuzCortada { get => _luzCortada; @@ -48,6 +48,10 @@ namespace CtrEditor.ObjetosSim.UserControls if (_luzCortada != value) { _luzCortada = value; + if (_luzCortada) + Color = Brushes.Blue; + else + Color = Brushes.Green; OnPropertyChanged(nameof(LuzCortada)); } } @@ -236,7 +240,7 @@ namespace CtrEditor.ObjetosSim.UserControls public void Highlight(bool State) { } public int ZIndex() { - return 1; + return 16; } } diff --git a/ObjetosSim/UserControls/ucTransporteCurva.xaml b/ObjetosSim/UserControls/ucTransporteCurva.xaml index 9f39d9d..428323b 100644 --- a/ObjetosSim/UserControls/ucTransporteCurva.xaml +++ b/ObjetosSim/UserControls/ucTransporteCurva.xaml @@ -10,7 +10,8 @@ - diff --git a/ObjetosSim/UserControls/ucTransporteCurva.xaml.cs b/ObjetosSim/UserControls/ucTransporteCurva.xaml.cs index f7bd8fb..91f9afd 100644 --- a/ObjetosSim/UserControls/ucTransporteCurva.xaml.cs +++ b/ObjetosSim/UserControls/ucTransporteCurva.xaml.cs @@ -1,106 +1,107 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Configuration; 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; +using CommunityToolkit.Mvvm.ComponentModel; using CtrEditor.Convertidores; using CtrEditor.Siemens; +using CtrEditor.Simulacion; -namespace CtrEditor.ObjetosSim.UserControls +namespace CtrEditor.ObjetosSim { /// /// Interaction logic for ucTransporteCurva.xaml /// - public class osTransporteCurva : osBase, IosBase + public partial class osTransporteCurva : osBase, IosBase { - private string _nombre = "Transporte Curva"; - private float frictionCoefficient; private float velMax50hz; // en metros por minuto private float tiempoRampa; private bool esMarcha; - private Rectangle Geometria = new Rectangle(); + private float _velocidadActual; + private osBase _osMotor = null; + private string _motor; - public override float Left - { - get => Geometria.Left; - set - { - Geometria.Left = value; - CanvasSetLeftinMeter(value); - OnPropertyChanged(nameof(Left)); - } - } - public override float Top - { - get => Geometria.Top; - set - { - Geometria.Top = value; - CanvasSetTopinMeter(value); - OnPropertyChanged(nameof(Top)); - } - } + private simTransporte Simulation_Transporte; - public float RadioExterno + public static string NombreClase() { - get => Geometria.Length; - set - { - Geometria.Length = value; - OnPropertyChanged(nameof(RadioExterno)); - } + return "Transporte Curva 90"; } - public float RadioInterno - { - get => Geometria.Width; - set - { - Geometria.Width = value; - OnPropertyChanged(nameof(RadioInterno)); - } - } - + + private float angulo; public float Angulo { - get => Geometria.Angle; + get => angulo; set { - Geometria.Angle = value; - OnPropertyChanged(nameof(Angulo)); + ActualizarGeometrias(); + SetProperty(ref angulo, value); } } - public float VelocidadActual + + [ObservableProperty] + private float radioExterno; + + [ObservableProperty] + private float radioInterno; + + [ObservableProperty] + private string motor; + + private float left; + public override float Left { - get => Geometria.Speed; + get => left; set { - Geometria.Speed = value; + CanvasSetLeftinMeter(value); + SetProperty(ref left, value); + } + } + private float top; + public override float Top + { + get => top; + set + { + CanvasSetTopinMeter(value); + SetProperty(ref top, value); + } + } + + [ObservableProperty] + public float ancho; + + [ObservableProperty] + public float alto; + + + public float VelocidadActual + { + get => _velocidadActual; + set + { + _velocidadActual = value; + Simulation_Transporte?.SetSpeed(value); OnPropertyChanged(nameof(VelocidadActual)); } } + private string nombre = "Transporte Curva 90"; public override string Nombre { - get => _nombre; - set + get => nombre; + set => SetProperty(ref nombre, value); + } + + private void ActualizarGeometrias() + { + if (_visualRepresentation is ucTransporteCurva uc) { - if (_nombre != value) - { - _nombre = value; - OnPropertyChanged(nameof(Nombre)); - } + //UpdateRectangle(Simulation_Transporte, uc.Transporte, Alto, Ancho, Angulo); + Simulation_Transporte.Speed = VelocidadActual; } } @@ -111,26 +112,49 @@ namespace CtrEditor.ObjetosSim.UserControls public osTransporteCurva() { + Ancho = 1; + Alto = 0.10f; RadioExterno = 2; RadioInterno = 1; } - public override void ConnectSimManager(SimulationManager simulationManager) - { - simulationManager.rectangles.Add(Geometria); - } - public override void UpdateGeometry() + public override void UpdateGeometryStart() { // Se llama antes de la simulacion - + ActualizarGeometrias(); } - - public override void UpdateControl() + public override void UpdateGeometryStep() { } - public override void UpdatePLC(PLCModel plc) { } + public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds) + { + if (_osMotor != null) + { + if (_osMotor is osVMmotorSim motor) + VelocidadActual = motor.Velocidad; + } + else + _osMotor = ObtenerLink(_motor, typeof(osVMmotorSim)); + } + public override void UpdateControl(int elapsedMilliseconds) + { + } + public override void ucLoaded() + { + // El UserControl ya se ha cargado y podemos obtener las coordenadas para + // crear el objeto de simulacion + ActualizarLeftTop(); + //if (_visualRepresentation is ucTransporteCurva uc) + // Simulation_Transporte = AddRectangle(simulationManager, uc.Transporte, Alto, Ancho, Angulo); + } + public override void ucUnLoaded() + { + // El UserControl se esta eliminando + // eliminar el objeto de simulacion + simulationManager.Remove(Simulation_Transporte); + } } @@ -141,11 +165,21 @@ namespace CtrEditor.ObjetosSim.UserControls public ucTransporteCurva() { 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) { if (Datos is osTransporteCurva datos) - datos.RadioExterno = PixelToMeter.Instance.calc.PixelsToMeters(width); + datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width); } public void Move(float LeftPixels, float TopPixels) { @@ -167,7 +201,6 @@ namespace CtrEditor.ObjetosSim.UserControls return 1; } - } } diff --git a/ObjetosSim/osBase.cs b/ObjetosSim/osBase.cs index b10e2cc..d90a94c 100644 --- a/ObjetosSim/osBase.cs +++ b/ObjetosSim/osBase.cs @@ -20,6 +20,7 @@ using FarseerPhysics.Dynamics; using Siemens.Simatic.Simulation.Runtime; using System.Windows.Media.Imaging; using System.Windows.Input; +using CommunityToolkit.Mvvm.ComponentModel; namespace CtrEditor.ObjetosSim { @@ -64,7 +65,7 @@ namespace CtrEditor.ObjetosSim } - public abstract class osBase : INotifyPropertyChanged + public abstract class osBase : ObservableObject { public virtual string Nombre { get; set; } = "osBase"; diff --git a/Simulacion/FPhysics.cs b/Simulacion/FPhysics.cs index e9af1a8..7d6aa7a 100644 --- a/Simulacion/FPhysics.cs +++ b/Simulacion/FPhysics.cs @@ -12,9 +12,8 @@ using CtrEditor.Convertidores; using FarseerPhysics.Common; using System.Windows; using System.Diagnostics; -using System.Windows.Documents; -using CtrEditor.ObjetosSim; -using static System.Runtime.InteropServices.JavaScript.JSType; + +using FarseerPhysics.Dynamics.Joints; namespace CtrEditor.Simulacion { @@ -37,6 +36,90 @@ namespace CtrEditor.Simulacion } + public class simCurve : simBase + { + private float _innerRadius; + private float _outerRadius; + private float _startAngle; + private float _endAngle; + + public simCurve(World world, float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 position) + { + _world = world; + _innerRadius = innerRadius; + _outerRadius = outerRadius; + _startAngle = MathHelper.ToRadians(startAngle); + _endAngle = MathHelper.ToRadians(endAngle); + Create(position); + } + + private void Create(Vector2 position) + { + if (Body != null) + { + _world.RemoveBody(Body); + } + + // Crear la geometría del sensor de curva + List segments = CreateCurveVertices(_innerRadius, _outerRadius, _startAngle, _endAngle); + Body = new Body(_world); + foreach (var segment in segments) + { + var shape = new PolygonShape(segment, 1f); + var fixture = Body.CreateFixture(shape); + fixture.IsSensor = true; + } + Body.Position = position; + Body.BodyType = BodyType.Static; + Body.UserData = this; + } + + private List CreateCurveVertices(float innerRadius, float outerRadius, float startAngle, float endAngle) + { + List verticesList = new List(); + int segments = 32; + float angleStep = (endAngle - startAngle) / segments; + + Vertices innerVertices = new Vertices(); + Vertices outerVertices = new Vertices(); + + for (int i = 0; i <= segments; i++) + { + float angle = startAngle + i * angleStep; + innerVertices.Add(new Vector2(innerRadius * (float)Math.Cos(angle), innerRadius * (float)Math.Sin(angle))); + outerVertices.Add(new Vector2(outerRadius * (float)Math.Cos(angle), outerRadius * (float)Math.Sin(angle))); + } + + outerVertices.Reverse(); + innerVertices.AddRange(outerVertices); + verticesList.Add(innerVertices); + + return verticesList; + } + + public void ApplyCurveEffect(simBotella bottle) + { + // Crear un joint para mantener la botella en la curva + RevoluteJoint joint = new RevoluteJoint(bottle.Body, Body, Body.Position, true) + { + CollideConnected = false + }; + _world.AddJoint(joint); + + bottle.CurrentJoint = joint; + } + + public void RemoveCurveEffect(simBotella bottle) + { + if (bottle.CurrentJoint != null) + { + _world.RemoveJoint(bottle.CurrentJoint); + bottle.CurrentJoint = null; + } + } + } + + public class simDescarte : simBase { private float _radius; @@ -178,6 +261,7 @@ namespace CtrEditor.Simulacion private float _radius; private float _mass; public bool Descartar = false; + public RevoluteJoint CurrentJoint { get; set; } public simBotella(World world, float diameter, Vector2 position, float mass) { @@ -255,6 +339,11 @@ namespace CtrEditor.Simulacion Sensor.LuzCortada = true; return true; } + else if (fixtureB.Body.UserData is simCurve curve) + { + curve.ApplyCurveEffect(this); + return true; // No aplicar respuestas físicas + } else if (fixtureB.Body.UserData is simDescarte) { Descartar = true; @@ -346,8 +435,11 @@ namespace CtrEditor.Simulacion public void Remove(simBase Objeto) { - Objeto.RemoverBody(); - Cuerpos.Remove(Objeto); + if (Objeto != null) + { + Objeto.RemoverBody(); + Cuerpos.Remove(Objeto); + } } public simBotella AddCircle(float diameter, Vector2 position, float mass) diff --git a/app2.png b/app2.png new file mode 100644 index 0000000..63aa6e1 Binary files /dev/null and b/app2.png differ