Primera revision. trabajando en la aplicacion de velocidad sobre los transportes.

This commit is contained in:
Miguel 2024-05-14 08:15:54 +02:00
parent 2bfd83ef3b
commit 56a2e994a2
13 changed files with 781 additions and 184 deletions

View File

@ -8,11 +8,27 @@
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
<Compile Remove="Simulacion\GeometrySimulator.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="motor2.png" /> <None Remove="motor2.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Remove="ObjetosSim\ucTransporteCurva.xaml" />
</ItemGroup>
<ItemGroup>
<None Include="ObjetosSim\ucTransporteCurva.xaml" />
<None Include="ObjetosSim\ucTransporteCurva.xaml.cs" />
<None Include="Simulacion\GeometrySimulator.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FarseerPhysics" Version="3.5.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />

View File

@ -24,6 +24,7 @@ using System.Windows.Data;
using System.Windows; using System.Windows;
using static System.Resources.ResXFileRef; using static System.Resources.ResXFileRef;
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Simulacion;
namespace CtrEditor namespace CtrEditor
{ {
@ -36,7 +37,7 @@ namespace CtrEditor
private ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>(); private ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
public PLCViewModel _plcViewModelData; public PLCViewModel _plcViewModelData;
private SimulationManager simulationManager = new SimulationManager(); public SimulationManagerFP simulationManager = new SimulationManagerFP();
private readonly DispatcherTimer _timerSimulacion; private readonly DispatcherTimer _timerSimulacion;
@ -63,7 +64,7 @@ namespace CtrEditor
ItemDoubleClickCommand = new ParameterizedRelayCommand(ExecuteDoubleClick); ItemDoubleClickCommand = new ParameterizedRelayCommand(ExecuteDoubleClick);
_timerSimulacion = new DispatcherTimer(); _timerSimulacion = new DispatcherTimer();
_timerSimulacion.Interval = TimeSpan.FromMilliseconds(20); // ajusta el intervalo según sea necesario _timerSimulacion.Interval = TimeSpan.FromMilliseconds(16); // ajusta el intervalo según sea necesario
_timerSimulacion.Tick += OnTickSimulacion; _timerSimulacion.Tick += OnTickSimulacion;
StartSimulationCommand = new RelayCommand(StartSimulation); StartSimulationCommand = new RelayCommand(StartSimulation);
@ -123,6 +124,11 @@ namespace CtrEditor
private void StartSimulation() private void StartSimulation()
{ {
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.UpdateGeometryStart();
simulationManager.Debug_DrawInitialBodies();
_timerSimulacion.Start(); _timerSimulacion.Start();
} }
@ -138,7 +144,7 @@ namespace CtrEditor
{ {
if (_plcViewModelData.IsConnected) if (_plcViewModelData.IsConnected)
objetoSimulable.UpdatePLC(_plcViewModelData.PLCInterface); objetoSimulable.UpdatePLC(_plcViewModelData.PLCInterface);
objetoSimulable.UpdateGeometry(); objetoSimulable.UpdateGeometryStep();
} }
simulationManager.Step((float)_timerSimulacion.Interval.TotalMilliseconds); simulationManager.Step((float)_timerSimulacion.Interval.TotalMilliseconds);
@ -259,6 +265,7 @@ namespace CtrEditor
foreach (var obj in ObjetosSimulables) foreach (var obj in ObjetosSimulables)
{ {
obj.VisualRepresentation = null; obj.VisualRepresentation = null;
obj.simulationManager = null;
} }
// Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter // Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter
var dataToSerialize = new SimulationData var dataToSerialize = new SimulationData
@ -328,7 +335,8 @@ namespace CtrEditor
// Asignar los datos al UserControl // Asignar los datos al UserControl
UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager); UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager);
OnUserControlSelected?.Invoke(userControl); OnUserControlSelected?.Invoke(userControl);
return true; return true;
} }
return false; return false;

View File

@ -19,6 +19,7 @@ using Label = System.Windows.Controls.Label;
using MouseEventArgs = System.Windows.Input.MouseEventArgs; using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using TextBox = System.Windows.Controls.TextBox; using TextBox = System.Windows.Controls.TextBox;
using UserControl = System.Windows.Controls.UserControl; using UserControl = System.Windows.Controls.UserControl;
//using OpenCvSharp;
namespace CtrEditor namespace CtrEditor
@ -62,6 +63,7 @@ namespace CtrEditor
//viewModel.TickSimulacion += MainViewModel_TickSimulacion; //viewModel.TickSimulacion += MainViewModel_TickSimulacion;
viewModel.OnUserControlSelected += AgregarUserControl; viewModel.OnUserControlSelected += AgregarUserControl;
viewModel?.LoadInitialData(); // Carga la primera imagen por defecto una vez cargada la ventana principal viewModel?.LoadInitialData(); // Carga la primera imagen por defecto una vez cargada la ventana principal
viewModel.simulationManager.DebugCanvas = ImagenEnTrabajoCanvas;
} }
} }
@ -72,6 +74,7 @@ namespace CtrEditor
var NuevoOS = dataContainer.Datos; var NuevoOS = dataContainer.Datos;
if (!NuevoOS.Inicializado) // Aun no fue inicializado if (!NuevoOS.Inicializado) // Aun no fue inicializado
{ {
Random rnd = new Random();
// Obtiene el factor de escala // Obtiene el factor de escala
var scaleTransform = ImagenEnTrabajoCanvas.LayoutTransform as ScaleTransform; var scaleTransform = ImagenEnTrabajoCanvas.LayoutTransform as ScaleTransform;
double scaleX = scaleTransform?.ScaleX ?? 1.0; double scaleX = scaleTransform?.ScaleX ?? 1.0;
@ -94,8 +97,8 @@ namespace CtrEditor
double topPixels = centerY - (userControl.ActualHeight / 2); double topPixels = centerY - (userControl.ActualHeight / 2);
// Establece la posición del UserControl // Establece la posición del UserControl
NuevoOS.Left = PixelToMeter.Instance.calc.PixelsToMeters((float)leftPixels); NuevoOS.Left = PixelToMeter.Instance.calc.PixelsToMeters((float)leftPixels + (float)(rnd.NextDouble() - 0.5) );
NuevoOS.Top = PixelToMeter.Instance.calc.PixelsToMeters((float)topPixels); NuevoOS.Top = PixelToMeter.Instance.calc.PixelsToMeters((float)topPixels + (float)(rnd.NextDouble() - 0.5) );
NuevoOS.Inicializado = true; NuevoOS.Inicializado = true;
} }
@ -117,7 +120,7 @@ namespace CtrEditor
// Añade el UserControl al Canvas // Añade el UserControl al Canvas
Canvas.SetZIndex(userControl, dataContainer.ZIndex()); Canvas.SetZIndex(userControl, dataContainer.ZIndex());
ImagenEnTrabajoCanvas.Children.Add(userControl); ImagenEnTrabajoCanvas.Children.Add(userControl);
} }
} }
@ -423,7 +426,7 @@ namespace CtrEditor
Source = selectedObject, Source = selectedObject,
Mode = BindingMode.TwoWay, Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus, // Actualizar solo al perder el foco UpdateSourceTrigger = UpdateSourceTrigger.LostFocus, // Actualizar solo al perder el foco
Converter = (FloatToFormattedStringConverter)Resources["floatFormatter"] // Usar el convertidor //Converter = (FloatToFormattedStringConverter)Resources["floatFormatter"] // Usar el convertidor
}; };
// Aplicar el convertidor solo a propiedades float // Aplicar el convertidor solo a propiedades float

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Controls; using System.Windows.Controls;
using CtrEditor.Simulacion;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -20,8 +21,8 @@ namespace CtrEditor.ObjetosSim
return new ucGuia(); return new ucGuia();
if (tipoObjeto == typeof(osTransporteGuias)) if (tipoObjeto == typeof(osTransporteGuias))
return new ucTransporteGuias(); return new ucTransporteGuias();
if (tipoObjeto == typeof(osTransporteCurva)) //if (tipoObjeto == typeof(osTransporteCurva))
return new ucTransporteCurva(); // return new ucTransporteCurva();
if (tipoObjeto == typeof(osVMmotorSim )) if (tipoObjeto == typeof(osVMmotorSim ))
return new ucVMmotorSim(); return new ucVMmotorSim();
@ -40,8 +41,8 @@ namespace CtrEditor.ObjetosSim
return new osGuia(); return new osGuia();
if (tipoObjeto == typeof(osTransporteGuias)) if (tipoObjeto == typeof(osTransporteGuias))
return new osTransporteGuias(); return new osTransporteGuias();
if (tipoObjeto == typeof(osTransporteCurva)) //if (tipoObjeto == typeof(osTransporteCurva))
return new osTransporteCurva(); // return new osTransporteCurva();
if (tipoObjeto == typeof(osVMmotorSim)) if (tipoObjeto == typeof(osVMmotorSim))
return new osVMmotorSim(); return new osVMmotorSim();
@ -62,14 +63,14 @@ namespace CtrEditor.ObjetosSim
return instance; return instance;
} }
public static void AssignDatos(UserControl userControl, osBase datos, SimulationManager simulationManager) public static void AssignDatos(UserControl userControl, osBase datos, SimulationManagerFP simulationManager)
{ {
if (userControl is IDataContainer dataContainer) if (userControl is IDataContainer dataContainer)
{ {
dataContainer.Datos = datos; dataContainer.Datos = datos;
userControl.DataContext = datos; userControl.DataContext = datos;
datos.VisualRepresentation = userControl; datos.VisualRepresentation = userControl;
datos.ConnectSimManager(simulationManager); datos.simulationManager = simulationManager;
} }
} }
} }

View File

@ -13,6 +13,10 @@ using System.Windows.Data;
using static System.Runtime.InteropServices.JavaScript.JSType; using static System.Runtime.InteropServices.JavaScript.JSType;
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Siemens; using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using System.Windows.Media;
using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -23,7 +27,6 @@ namespace CtrEditor.ObjetosSim
{ {
string Nombre { get; } string Nombre { get; }
void ConnectSimManager(SimulationManager simulationManager);
void UpdateControl(); void UpdateControl();
} }
@ -48,10 +51,11 @@ namespace CtrEditor.ObjetosSim
public abstract string Nombre { get; set; } public abstract string Nombre { get; set; }
public abstract void ConnectSimManager(SimulationManager simulationManager);
public abstract void UpdateControl(); public abstract void UpdateControl();
public abstract void UpdateGeometry(); public abstract void UpdateGeometryStart();
public abstract void UpdateGeometryStep();
public abstract void UpdatePLC(PLCModel plc); public abstract void UpdatePLC(PLCModel plc);
public abstract void ucLoaded();
[JsonIgnore] [JsonIgnore]
public UserControl? VisualRepresentation public UserControl? VisualRepresentation
@ -59,6 +63,9 @@ namespace CtrEditor.ObjetosSim
get => _visualRepresentation; get => _visualRepresentation;
set => _visualRepresentation = value; set => _visualRepresentation = value;
} }
[JsonIgnore]
public SimulationManagerFP simulationManager;
public void CanvasSetLeftinMeter(float left) public void CanvasSetLeftinMeter(float left)
{ {
@ -84,6 +91,91 @@ namespace CtrEditor.ObjetosSim
else return 0f; 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(simRectangle simRect, System.Windows.Shapes.Rectangle wpfRect, float Alto, float Ancho, float Angulo)
{
if (simRect != null)
simRect.Create(Ancho, Alto, GetRectangleCenter(wpfRect), Angulo);
}
public simRectangle AddRectangle(SimulationManagerFP simulationManager, System.Windows.Shapes.Rectangle wpfRect, float Alto, float Ancho, float Angulo)
{
return simulationManager.AddRectangle(Ancho, Alto, GetRectangleCenter(wpfRect), Angulo);
}
public void UpdateOrCreateLine(simLine 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 simLine AddLine(SimulationManagerFP simulationManager, System.Windows.Shapes.Rectangle wpfRect)
{
var coords = GetCenterLineVectors(wpfRect);
return simulationManager.AddLine(coords.Start, coords.End);
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
@ -93,7 +185,4 @@ namespace CtrEditor.ObjetosSim
} }
} }
} }

View File

@ -12,9 +12,11 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using System.Numerics; using Microsoft.Xna.Framework;
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Siemens; using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using Newtonsoft.Json.Linq;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -25,61 +27,88 @@ namespace CtrEditor.ObjetosSim
public class osBotella : osBase public class osBotella : osBase
{ {
private Circle Geometria = new Circle(); private float _diametro;
private float _mass;
private Vector2 _centro = new Vector2(); // Centro
private string _nombre = "Botella";
private simCircle Simulacion_Botella;
// Otros datos y métodos relevantes para la simulación // Otros datos y métodos relevantes para la simulación
private string _nombre = "Botella";
public float Diametro { public float Diametro {
get => Geometria.Diameter; get => _diametro;
set set
{ {
Geometria.Diameter = value; _diametro = value;
Simulacion_Botella?.SetDiameter(Diametro);
OnPropertyChanged(nameof(Diametro)); OnPropertyChanged(nameof(Diametro));
} }
} }
public float Mass { public float Mass {
get => Geometria.Mass; get => _mass;
set set
{ {
Geometria.Mass = value; _mass = value;
Simulacion_Botella?.SetMass(value);
OnPropertyChanged(nameof(Mass)); OnPropertyChanged(nameof(Mass));
} }
} }
public float Overlap
{
get => Geometria.Overlap;
set
{
Geometria.Overlap = value;
OnPropertyChanged(nameof(Overlap));
}
}
public override float Left public override float Left
{ {
get => Geometria.Left; get => _centro.X-Diametro/2;
set set
{ {
Geometria.Left = value; _centro.X = value+Diametro/2;
CanvasSetLeftinMeter(value); CanvasSetLeftinMeter(value);
OnPropertyChanged(nameof(Left)); OnPropertyChanged(nameof(Left));
} }
} }
public override float Top public override float Top
{ {
get => Geometria.Top; get => _centro.Y - Diametro / 2;
set set
{ {
Geometria.Top = value; _centro.Y = value + Diametro / 2;
CanvasSetTopinMeter(value); CanvasSetTopinMeter(value);
OnPropertyChanged(nameof(Top)); OnPropertyChanged(nameof(Top));
} }
} }
public float CenterX
{
get => _centro.X;
set
{
_centro.X = value;
CanvasSetLeftinMeter(Left);
OnPropertyChanged(nameof(CenterX));
OnPropertyChanged(nameof(Left));
}
}
public float CenterY
{
get => _centro.Y;
set
{
_centro.Y = value;
CanvasSetTopinMeter(Top);
OnPropertyChanged(nameof(CenterY));
OnPropertyChanged(nameof(Top));
}
}
private void ActualizarGeometrias()
{
if (Simulacion_Botella != null)
{
Simulacion_Botella.SetDiameter(Diametro);
Simulacion_Botella.SetPosition(CenterX, CenterY);
}
}
public override string Nombre public override string Nombre
{ {
get => _nombre; get => _nombre;
@ -96,25 +125,34 @@ namespace CtrEditor.ObjetosSim
public osBotella() public osBotella()
{ {
Diametro = 0.10f; Diametro = 0.10f;
Mass = 1;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void UpdateGeometryStart()
{
simulationManager.circles.Add(Geometria);
}
public override void UpdateGeometry()
{ {
// Se llama antes de la simulacion // Se llama antes de la simulacion
ActualizarGeometrias();
} }
public override void UpdateGeometryStep()
{
// Se llama antes de la simulacion
ActualizarGeometrias();
}
public override void UpdatePLC(PLCModel plc) { } public override void UpdatePLC(PLCModel plc) { }
public override void UpdateControl() public override void UpdateControl()
{ {
Top = Geometria.Top; CenterX = Simulacion_Botella.CenterX;
Left = Geometria.Left; CenterY = Simulacion_Botella.CenterY;
Overlap = Geometria.Overlap;
} }
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
Simulacion_Botella = simulationManager.AddCircle(Diametro, _centro, Mass);
}
} }
public partial class ucBotella : UserControl, IDataContainer public partial class ucBotella : UserControl, IDataContainer
@ -124,6 +162,11 @@ namespace CtrEditor.ObjetosSim
public ucBotella() public ucBotella()
{ {
InitializeComponent(); InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
} }
public void Resize(float width, float height) { } public void Resize(float width, float height) { }
public void Move(float LeftPixels, float TopPixels) public void Move(float LeftPixels, float TopPixels)

View File

@ -11,7 +11,7 @@
</UserControl.Resources> </UserControl.Resources>
<Canvas> <Canvas>
<Rectangle Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding AltoGuia, Converter={StaticResource MeterToPixelConverter}}" Fill="Blue"> <Rectangle x:Name="Guia" Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding AltoGuia, Converter={StaticResource MeterToPixelConverter}}" Fill="Blue">
<Rectangle.RenderTransform> <Rectangle.RenderTransform>
<RotateTransform Angle="{Binding Angulo}"/> <RotateTransform Angle="{Binding Angulo}"/>
</Rectangle.RenderTransform> </Rectangle.RenderTransform>

View File

@ -14,6 +14,10 @@ using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Siemens; using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -22,26 +26,31 @@ namespace CtrEditor.ObjetosSim
/// </summary> /// </summary>
public class osGuia : osBase public class osGuia : osBase
{ {
private float _ancho;
private float _altoGuia;
private float _left;
private float _top;
private float _angulo;
private string _nombre = "Guia"; private string _nombre = "Guia";
private Line Geometria = new Line(); private simLine Simulation_Guia;
public override float Left public override float Left
{ {
get => Geometria.Left; get => _left;
set set
{ {
Geometria.Left = value; _left = value;
CanvasSetLeftinMeter(value); CanvasSetLeftinMeter(value);
OnPropertyChanged(nameof(Left)); OnPropertyChanged(nameof(Left));
} }
} }
public override float Top public override float Top
{ {
get => Geometria.Top; get => _top;
set set
{ {
Geometria.Top = value; _top = value;
CanvasSetTopinMeter(value); CanvasSetTopinMeter(value);
OnPropertyChanged(nameof(Top)); OnPropertyChanged(nameof(Top));
} }
@ -49,29 +58,29 @@ namespace CtrEditor.ObjetosSim
public float Ancho public float Ancho
{ {
get => Geometria.Length; get => _ancho;
set set
{ {
Geometria.Length = value; _ancho = value;
OnPropertyChanged(nameof(Ancho)); OnPropertyChanged(nameof(Ancho));
} }
} }
public float AltoGuia public float AltoGuia
{ {
get => Geometria.Width; get => _altoGuia;
set set
{ {
Geometria.Width = value; _altoGuia = value;
OnPropertyChanged(nameof(AltoGuia)); OnPropertyChanged(nameof(AltoGuia));
} }
} }
public float Angulo public float Angulo
{ {
get => Geometria.Angle; get => _angulo;
set set
{ {
Geometria.Angle = value; _angulo = value;
OnPropertyChanged(nameof(Angulo)); OnPropertyChanged(nameof(Angulo));
} }
} }
@ -89,25 +98,37 @@ namespace CtrEditor.ObjetosSim
} }
} }
private void ActualizarGeometrias()
{
if (_visualRepresentation is ucGuia uc)
UpdateOrCreateLine(Simulation_Guia, uc.Guia);
}
public osGuia() public osGuia()
{ {
Ancho = 1; Ancho = 1;
AltoGuia = 0.03f; AltoGuia = 0.03f;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void UpdateGeometryStart()
{
simulationManager.lines.Add(Geometria);
}
public override void UpdateGeometry()
{ {
// Se llama antes de la simulacion // Se llama antes de la simulacion
ActualizarGeometrias();
} }
public override void UpdateControl() public override void UpdateControl()
{ {
} }
public override void UpdateGeometryStep()
{
}
public override void UpdatePLC(PLCModel plc) { } public override void UpdatePLC(PLCModel plc) { }
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
if (_visualRepresentation is ucGuia uc)
Simulation_Guia = AddLine(simulationManager, uc.Guia);
}
} }
@ -119,6 +140,11 @@ namespace CtrEditor.ObjetosSim
public ucGuia() public ucGuia()
{ {
InitializeComponent(); InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
} }
public void Resize(float width, float height) public void Resize(float width, float height)
{ {

View File

@ -14,6 +14,7 @@ using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Siemens; using CtrEditor.Siemens;
using CtrEditor.Simulacion;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -24,36 +25,42 @@ namespace CtrEditor.ObjetosSim
{ {
private string _nombre = "Transporte Guias"; private string _nombre = "Transporte Guias";
private float _distance;
private float _altoGuia;
private float frictionCoefficient; private float frictionCoefficient;
private float velMax50hz; // en metros por minuto private float velMax50hz; // en metros por minuto
private float tiempoRampa; private float tiempoRampa;
private bool esMarcha; private bool esMarcha;
private double _distance;
private float altoGuia;
private float left; private float _ancho;
private float top; private float _alto;
private float _left;
private float _top;
private float _angulo;
private float _velocidadActual;
private simRectangle? TransporteCentral;
private simLine? Guia_Superior;
private simLine? Guia_Inferior;
private Rectangle TransporteCentral = new Rectangle();
private Line Guia_Superior = new Line();
private Line Guia_Inferior = new Line();
public override float Left public override float Left
{ {
get => left; get => _left;
set set
{ {
left = value; _left = value;
CanvasSetLeftinMeter(value); CanvasSetLeftinMeter(value);
OnPropertyChanged(nameof(Left)); OnPropertyChanged(nameof(Left));
} }
} }
public override float Top public override float Top
{ {
get => top; get => _top;
set set
{ {
top = value; _top = value;
CanvasSetTopinMeter(value); CanvasSetTopinMeter(value);
OnPropertyChanged(nameof(Top)); OnPropertyChanged(nameof(Top));
} }
@ -61,53 +68,45 @@ namespace CtrEditor.ObjetosSim
public float Ancho public float Ancho
{ {
get => TransporteCentral.Length; get => _ancho;
set set
{ {
TransporteCentral.Length = value; _ancho = value;
OnPropertyChanged(nameof(Ancho)); OnPropertyChanged(nameof(Ancho));
} }
} }
public float AltoGuia
{
get => altoGuia;
set
{
altoGuia = value;
OnPropertyChanged(nameof(AltoGuia));
}
}
public float Alto public float Alto
{ {
get => TransporteCentral.Width; get => _alto;
set set
{ {
TransporteCentral.Width = value; _alto = value;
OnPropertyChanged(nameof(Alto)); OnPropertyChanged(nameof(Alto));
} }
} }
public float Angulo public float Angulo
{ {
get => TransporteCentral.Angle; get => _angulo;
set set
{ {
TransporteCentral.Angle = value; _angulo = value;
OnPropertyChanged(nameof(Angulo)); OnPropertyChanged(nameof(Angulo));
} }
} }
public float VelocidadActual public float VelocidadActual
{ {
get => TransporteCentral.Speed; get => _velocidadActual;
set set
{ {
TransporteCentral.Speed = value; _velocidadActual = value;
TransporteCentral?.SetSpeed(value);
OnPropertyChanged(nameof(VelocidadActual)); OnPropertyChanged(nameof(VelocidadActual));
} }
} }
public double Distance public float Distance
{ {
get { return _distance; } get { return _distance; }
set set
@ -115,11 +114,21 @@ namespace CtrEditor.ObjetosSim
if (_distance != value) if (_distance != value)
{ {
_distance = value; _distance = value;
OnPropertyChanged("Distance"); OnPropertyChanged(nameof(Distance));
} }
} }
} }
public float AltoGuia
{
get => _altoGuia;
set
{
_altoGuia = value;
OnPropertyChanged(nameof(AltoGuia));
}
}
public override string Nombre public override string Nombre
{ {
get => _nombre; get => _nombre;
@ -135,50 +144,21 @@ namespace CtrEditor.ObjetosSim
private void ActualizarGeometrias() private void ActualizarGeometrias()
{ {
ucTransporteGuias ucTG = (ucTransporteGuias)_visualRepresentation; if (_visualRepresentation is ucTransporteGuias uc)
if (ucTG != null)
{ {
var _canvasLeft = CanvasGetLeftinMeter(); UpdateRectangle(TransporteCentral, uc.Transporte, Alto, Ancho, Angulo);
var _canvasTop = CanvasGetTopinMeter(); UpdateOrCreateLine(Guia_Superior, uc.GuiaSuperior);
UpdateOrCreateLine(Guia_Inferior, uc.GuiaInferior) ;
var coordenadas = GetRectangleCoordinatesInMeter(ucTG.Transporte, ucTG); TransporteCentral.Speed = VelocidadActual;
TransporteCentral.Left = coordenadas.Left + _canvasLeft;
TransporteCentral.Top = coordenadas.Top + _canvasTop;
coordenadas = GetRectangleCoordinatesInMeter(ucTG.GuiaSuperior, ucTG);
Guia_Superior.Left = coordenadas.Left + _canvasLeft;
Guia_Superior.Top = coordenadas.Top + _canvasTop; ;
coordenadas = GetRectangleCoordinatesInMeter(ucTG.GuiaInferior, ucTG);
Guia_Inferior.Left = coordenadas.Left + _canvasLeft;
Guia_Inferior.Top = coordenadas.Top + _canvasTop; ;
TransporteCentral.Angle = Guia_Superior.Angle = Guia_Inferior.Angle = Angulo;
Guia_Superior.Length = Guia_Inferior.Length = Ancho;
} }
} }
private (float Left, float Top) GetRectangleCoordinatesInMeter(System.Windows.Shapes.Rectangle rect, ucTransporteGuias ucTG)
{
if (rect != null)
{
// Obtiene la transformada del objeto visual
GeneralTransform transform = rect.TransformToAncestor(ucTG);
// Obtiene la posición absoluta
Point topLeft = transform.Transform(new Point(0, 0));
//Point bottomRight = transform.Transform(new Point(rect.ActualWidth, rect.ActualHeight));
return (PixelToMeter.Instance.calc.PixelsToMeters((float)topLeft.X), PixelToMeter.Instance.calc.PixelsToMeters((float)topLeft.Y));
}
else return (0,0);
}
public float FrictionCoefficient { get => frictionCoefficient; set => frictionCoefficient = value; } public float FrictionCoefficient { get => frictionCoefficient; set => frictionCoefficient = value; }
public float VelMax50hz { get => velMax50hz; set => velMax50hz = value; } public float VelMax50hz { get => velMax50hz; set => velMax50hz = value; }
public float TiempoRampa { get => tiempoRampa; set => tiempoRampa = value; } public float TiempoRampa { get => tiempoRampa; set => tiempoRampa = value; }
public bool EsMarcha { get => esMarcha; set => esMarcha = value; } public bool EsMarcha { get => esMarcha; set => esMarcha = value; }
public osTransporteGuias() public osTransporteGuias()
{ {
@ -188,22 +168,35 @@ namespace CtrEditor.ObjetosSim
Distance = 0.01f; Distance = 0.01f;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void UpdateGeometryStart()
{
simulationManager.rectangles.Add(TransporteCentral);
simulationManager.lines.Add(Guia_Superior);
simulationManager.lines.Add(Guia_Inferior);
}
public override void UpdateGeometry()
{ {
// Se llama antes de la simulacion // Se llama antes de la simulacion
ActualizarGeometrias(); ActualizarGeometrias();
} }
public override void UpdateGeometryStep()
{
}
public override void UpdateControl() public override void UpdateControl()
{ {
} }
public override void UpdatePLC(PLCModel plc) { } public override void UpdatePLC(PLCModel plc) { }
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
simulationManager.rectangles.Add(TransporteCentral);
simulationManager.lines.Add(Guia_Superior);
simulationManager.lines.Add(Guia_Inferior);
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
if (_visualRepresentation is ucTransporteGuias uc)
{
TransporteCentral = AddRectangle(simulationManager, uc.Transporte, Alto, Ancho, Angulo);
Guia_Superior = AddLine(simulationManager, uc.GuiaSuperior);
Guia_Inferior = AddLine(simulationManager, uc.GuiaInferior);
}
}
} }
@ -215,6 +208,11 @@ namespace CtrEditor.ObjetosSim
public ucTransporteGuias() public ucTransporteGuias()
{ {
InitializeComponent(); InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
} }
public void Resize(float width, float height) public void Resize(float width, float height)
{ {

View File

@ -11,7 +11,7 @@
</UserControl.Resources> </UserControl.Resources>
<Canvas> <Canvas>
<Rectangle Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Fill="Gray"> <Rectangle x:Name="Transporte" Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Fill="Gray">
<Rectangle.RenderTransform> <Rectangle.RenderTransform>
<RotateTransform Angle="{Binding Angulo}"/> <RotateTransform Angle="{Binding Angulo}"/>
</Rectangle.RenderTransform> </Rectangle.RenderTransform>

View File

@ -1,22 +1,9 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; 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 static System.Runtime.InteropServices.JavaScript.JSType;
using System.Numerics;
using System.Windows.Markup;
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Siemens; using CtrEditor.Siemens;
using CtrEditor.Simulacion;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -34,60 +21,72 @@ namespace CtrEditor.ObjetosSim
private float tiempoRampa; private float tiempoRampa;
private bool esMarcha; private bool esMarcha;
private Rectangle Geometria = new Rectangle(); private float _ancho;
private float _alto;
private float _left;
private float _top;
private float _angulo;
private float _velocidadActual;
private simRectangle Simulation_Transporte;
public override float Left public override float Left
{ {
get => Geometria.Left; get => _left;
set set
{ {
Geometria.Left = value; _left = value;
CanvasSetLeftinMeter(value); CanvasSetLeftinMeter(value);
OnPropertyChanged(nameof(Left)); OnPropertyChanged(nameof(Left));
} }
} }
public override float Top public override float Top
{ {
get => Geometria.Top; get => _top;
set set
{ {
Geometria.Top = value; _top = value;
CanvasSetTopinMeter(value); CanvasSetTopinMeter(value);
OnPropertyChanged(nameof(Top)); OnPropertyChanged(nameof(Top));
} }
} }
public float Ancho { public float Ancho
get => Geometria.Length; {
get => _ancho;
set set
{ {
Geometria.Length = value; _ancho = value;
OnPropertyChanged(nameof(Ancho)); OnPropertyChanged(nameof(Ancho));
} }
} }
public float Alto { public float Alto
get => Geometria.Width; {
get => _alto;
set set
{ {
Geometria.Width = value; _alto = value;
OnPropertyChanged(nameof(Alto)); OnPropertyChanged(nameof(Alto));
} }
} }
public float Angulo public float Angulo
{ {
get => Geometria.Angle; get => _angulo;
set set
{ {
Geometria.Angle = value; _angulo = value;
OnPropertyChanged(nameof(Angulo)); OnPropertyChanged(nameof(Angulo));
} }
} }
public float VelocidadActual public float VelocidadActual
{ {
get => Geometria.Speed; get => _velocidadActual;
set { set {
Geometria.Speed = value; _velocidadActual = value;
Simulation_Transporte?.SetSpeed(value);
OnPropertyChanged(nameof(VelocidadActual)); OnPropertyChanged(nameof(VelocidadActual));
} }
} }
@ -105,6 +104,15 @@ namespace CtrEditor.ObjetosSim
} }
} }
private void ActualizarGeometrias()
{
if (_visualRepresentation is ucTransporteTTop uc)
{
UpdateRectangle(Simulation_Transporte, uc.Transporte,Alto,Ancho,Angulo);
Simulation_Transporte.Speed = VelocidadActual;
}
}
public float FrictionCoefficient { get => frictionCoefficient; set => frictionCoefficient = value; } public float FrictionCoefficient { get => frictionCoefficient; set => frictionCoefficient = value; }
public float VelMax50hz { get => velMax50hz; set => velMax50hz = value; } public float VelMax50hz { get => velMax50hz; set => velMax50hz = value; }
public float TiempoRampa { get => tiempoRampa; set => tiempoRampa = value; } public float TiempoRampa { get => tiempoRampa; set => tiempoRampa = value; }
@ -116,14 +124,13 @@ namespace CtrEditor.ObjetosSim
Alto = 0.10f; Alto = 0.10f;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void UpdateGeometryStart()
{
simulationManager.rectangles.Add(Geometria);
}
public override void UpdateGeometry()
{ {
// Se llama antes de la simulacion // Se llama antes de la simulacion
ActualizarGeometrias();
}
public override void UpdateGeometryStep()
{
} }
public override void UpdatePLC(PLCModel plc) { } public override void UpdatePLC(PLCModel plc) { }
@ -131,6 +138,13 @@ namespace CtrEditor.ObjetosSim
public override void UpdateControl() public override void UpdateControl()
{ {
} }
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
if (_visualRepresentation is ucTransporteTTop uc)
Simulation_Transporte = AddRectangle(simulationManager, uc.Transporte, Alto, Ancho, Angulo);
}
} }
@ -141,6 +155,11 @@ namespace CtrEditor.ObjetosSim
public ucTransporteTTop() public ucTransporteTTop()
{ {
InitializeComponent(); InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
} }
public void Resize(float width, float height) public void Resize(float width, float height)
{ {

View File

@ -14,6 +14,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using CtrEditor.Simulacion;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -93,13 +94,13 @@ namespace CtrEditor.ObjetosSim
PLC_NumeroMotor = 31; PLC_NumeroMotor = 31;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void UpdateGeometryStart()
{
}
public override void UpdateGeometry()
{ {
// Se llama antes de la simulacion // Se llama antes de la simulacion
}
public override void UpdateGeometryStep()
{
} }
public override void UpdatePLC(PLCModel plc) { } public override void UpdatePLC(PLCModel plc) { }
@ -107,6 +108,12 @@ namespace CtrEditor.ObjetosSim
{ {
} }
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
}
} }
public partial class ucVMmotorSim : UserControl, IDataContainer public partial class ucVMmotorSim : UserControl, IDataContainer

387
Simulacion/FPhysics.cs Normal file
View File

@ -0,0 +1,387 @@
using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Shapes;
using CtrEditor.Convertidores;
using CtrEditor.ObjetosSim;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using OpenCvSharp;
using Siemens.Simatic.Simulation.Runtime;
using static System.Windows.Forms.DataFormats;
using Point = System.Windows.Point;
namespace CtrEditor.Simulacion
{
public class simRectangle
{
public Body Body { get; private set; }
public float Speed { get; set; } // Velocidad para efectos de cinta transportadora
public World _world;
public simRectangle(World world, float width, float height, Vector2 position, float angle = 0)
{
_world = world;
Create(width, height, position, angle);
}
public float Angle
{
get { return MathHelper.ToDegrees(Body.Rotation); }
set { Body.Rotation = MathHelper.ToRadians(value); }
}
public void SetPosition(float x, float y)
{
Body.Position = new Vector2(x, y);
}
public void SetSpeed(float speed)
{
Speed = speed;
}
public void SetDimensions(float width, float height)
{
// Primero, elimina el fixture antiguo
Body.DestroyFixture(Body.FixtureList[0]);
// Crea un nuevo fixture con las nuevas dimensiones
var newShape = new PolygonShape(PolygonTools.CreateRectangle(width / 2, height / 2), 1f);
Body.CreateFixture(newShape);
}
public void Create(float width, float height, Vector2 position, float angle = 0)
{
if (Body != null) {
_world.RemoveBody(Body);
}
Body = BodyFactory.CreateRectangle(_world, width, height, 1f, position);
Body.FixtureList[0].IsSensor = true;
Body.BodyType = BodyType.Static;
Body.Rotation = MathHelper.ToRadians(angle);
Body.UserData = this; // Importante para la identificación durante la colisión
}
// Otros métodos según sea necesario, como mover, rotar, etc.
}
public class simLine
{
public Body Body { get; private set; }
public World _world;
public simLine(World world, Vector2 start, Vector2 end)
{
_world = world;
Create(start, end);
}
public void Create(Vector2 start, Vector2 end)
{
if (Body != null)
{
_world.RemoveBody(Body); // Elimina el cuerpo anterior si existe
}
Body = BodyFactory.CreateEdge(_world, start, end);
Body.BodyType = BodyType.Static;
Body.UserData = this; // Importante para la identificación durante la colisión
}
public void UpdateVertices(Vector2 newStart, Vector2 newEnd)
{
Create(newStart, newEnd); // Recrear la línea con nuevos vértices
}
}
public class simCircle
{
public Body Body { get; private set; }
public World _world;
private float _radius;
private float _mass;
public simCircle(World world, float diameter, Vector2 position, float mass)
{
_world = world;
_radius = diameter / 2;
_mass = mass;
Create(position);
}
public float CenterX
{
get { return Body.Position.X; }
set { }
}
public float CenterY
{
get { return Body.Position.Y; }
set { }
}
public Vector2 Center
{
get { return Body.Position; }
}
public float Mass
{
get {
if (_mass <= 0)
_mass = 1;
return _mass;
}
set { _mass = value; }
}
private void Create(Vector2 position)
{
if (Body != null)
{
_world.RemoveBody(Body); // Remover el cuerpo anterior si existe
}
Body = BodyFactory.CreateCircle(_world, _radius, 10f, position);
Body.BodyType = BodyType.Dynamic;
// Restablecer manejador de eventos de colisión
Body.OnCollision += HandleCollision;
Body.OnSeparation += HandleOnSeparation;
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
// Configurar amortiguamiento
Body.LinearDamping = 0.01f; // Ajustar para controlar la reducción de la velocidad lineal
Body.AngularDamping = 1f; // Ajustar para controlar la reducción de la velocidad angular
Body.Restitution = 0.2f; // Baja restitución para menos rebote
Body.IsBullet = true;
}
private void HandleOnSeparation(Fixture fixtureA, Fixture fixtureB)
{
Body.LinearDamping = 5f; // Ajustar para controlar la reducción de la velocidad lineal
}
public void SetPosition(float x, float y)
{
// Usar el ángulo actual, ya que no es relevante para un círculo en este contexto
Body.SetTransform(new Vector2(x, y), Body.Rotation);
}
public void SetDiameter(float diameter)
{
_radius = diameter / 2;
Create(Body.Position); // Recrear el círculo con el nuevo tamaño
}
public void SetMass(float mass)
{
Mass = mass;
}
private bool HandleCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
{
if (fixtureB.Body.UserData is simRectangle)
{
simRectangle conveyor = fixtureB.Body.UserData as simRectangle;
ApplyConveyorEffect(conveyor, fixtureA, contact);
return true; // No aplicar respuestas fisicas
}
return true; // No aplicar respuestas fisicas
}
private void ApplyConveyorEffect(simRectangle conveyor, Fixture circleFixture, FarseerPhysics.Dynamics.Contacts.Contact contact)
{
// Calcular la velocidad deseada en metros por segundo
float speedMetersPerSecond = conveyor.Speed / 60.0f;
Vector2 desiredVelocity = new Vector2((float)Math.Cos(conveyor.Body.Rotation), (float)Math.Sin(conveyor.Body.Rotation)) * speedMetersPerSecond;
// Calcular la fuerza necesaria para alcanzar esa velocidad
Vector2 velocityChange = desiredVelocity - circleFixture.Body.LinearVelocity;
float timeStep = 1.0f / 60.0f; // Asumiendo 60 Hz de tasa de actualización
Vector2 acceleration = velocityChange / timeStep;
Vector2 force = acceleration / Mass;
// Aplicar la fuerza al círculo
circleFixture.Body.ApplyForce(force);
}
}
public class SimulationManagerFP
{
private World world;
private Canvas simulationCanvas;
public List<simCircle> circles;
public List<simRectangle> rectangles;
public List<simLine> lines;
public Canvas DebugCanvas { get => simulationCanvas; set => simulationCanvas = value; }
public SimulationManagerFP()
{
world = new World(new Vector2(0,0)); // Vector2.Zero
circles = new List<simCircle>();
rectangles = new List<simRectangle>();
lines = new List<simLine>();
}
public simCircle AddCircle(float diameter, Vector2 position, float mass)
{
simCircle circle = new simCircle(world, diameter, position, mass);
circles.Add(circle);
return circle;
}
public simRectangle AddRectangle(float width, float height, Vector2 position, float angle)
{
simRectangle rectangle = new simRectangle(world, width, height, position, angle);
rectangles.Add(rectangle);
return rectangle;
}
public simLine AddLine(Vector2 start, Vector2 end)
{
simLine line = new simLine(world, start, end);
lines.Add(line);
return line;
}
// Otros métodos para agregar círculos y ejecutar la simulación
public void Step(float timeStep)
{
world.Step(timeStep/1000.0f);
// Actualiza y gestiona otras lógicas si es necesario
}
public void Debug_DrawInitialBodies()
{
ClearSimulationShapes();
world.Step(0.01f); // Para actualizar la BodyList
foreach (Body body in world.BodyList)
{
foreach (Fixture fixture in body.FixtureList)
{
DrawShape(fixture);
}
}
}
private void ClearSimulationShapes()
{
var simulationShapes = simulationCanvas.Children.OfType<System.Windows.Shapes.Shape>().Where(s => s.Tag as string == "Simulation").ToList();
foreach (var shape in simulationShapes)
{
simulationCanvas.Children.Remove(shape);
}
}
private void DrawShape(Fixture fixture)
{
System.Windows.Shapes.Shape shape;
switch (fixture.ShapeType)
{
case ShapeType.Circle:
shape = DrawCircle(fixture);
break;
case ShapeType.Polygon:
shape = DrawPolygon(fixture);
break;
case ShapeType.Edge:
shape = DrawEdge(fixture);
break;
default:
return;
}
shape.Tag = "Simulation"; // Marcar para simulación
Canvas.SetZIndex(shape, 20);
simulationCanvas.Children.Add(shape);
}
private float p(float x)
{
float c = PixelToMeter.Instance.calc.MetersToPixels(x);
return c;
}
private System.Windows.Shapes.Shape DrawEdge(Fixture fixture)
{
EdgeShape edge = fixture.Shape as EdgeShape;
Line line = new Line
{
X1 = p(edge.Vertex1.X + fixture.Body.Position.X ), // Aplicar escala y posición
Y1 = p(edge.Vertex1.Y + fixture.Body.Position.Y ),
X2 = p(edge.Vertex2.X + fixture.Body.Position.X ),
Y2 = p(edge.Vertex2.Y + fixture.Body.Position.Y ),
Stroke = Brushes.Black,
StrokeThickness = 2
};
return line;
}
private System.Windows.Shapes.Shape DrawCircle(Fixture fixture)
{
CircleShape circle = fixture.Shape as CircleShape;
Ellipse ellipse = new Ellipse
{
Width = p(circle.Radius * 2), // Escalado para visualización
Height = p(circle.Radius * 2), // Escalado para visualización
Stroke = Brushes.Black,
StrokeThickness = 2
};
Canvas.SetLeft(ellipse, p(fixture.Body.Position.X - circle.Radius ));
Canvas.SetTop(ellipse, p(fixture.Body.Position.Y - circle.Radius ));
return ellipse;
}
private System.Windows.Shapes.Shape DrawPolygon(Fixture fixture)
{
Polygon polygon = new Polygon { Stroke = Brushes.Black, StrokeThickness = 2 };
PolygonShape polyShape = fixture.Shape as PolygonShape;
float cos = (float)Math.Cos(fixture.Body.Rotation);
float sin = (float)Math.Sin(fixture.Body.Rotation);
foreach (Vector2 vertex in polyShape.Vertices)
{
// Aplicar la rotación alrededor del origen y luego trasladar
float rotatedX = vertex.X * cos - vertex.Y * sin + fixture.Body.Position.X;
float rotatedY = vertex.X * sin + vertex.Y * cos + fixture.Body.Position.Y;
polygon.Points.Add(new Point(p(rotatedX), p(rotatedY)));
}
return polygon;
}
}
}