Primera logica de simulacion
This commit is contained in:
parent
dd2b656c69
commit
3ba10b81c3
|
@ -32,6 +32,8 @@ namespace CtrEditor
|
||||||
public ObservableCollection<TipoSimulable> ListaOsBase { get; } = new ObservableCollection<TipoSimulable>();
|
public ObservableCollection<TipoSimulable> ListaOsBase { get; } = new ObservableCollection<TipoSimulable>();
|
||||||
private ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
|
private ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
|
||||||
|
|
||||||
|
private SimulationManager simulationManager = new SimulationManager();
|
||||||
|
|
||||||
private readonly DispatcherTimer _timerSimulacion;
|
private readonly DispatcherTimer _timerSimulacion;
|
||||||
|
|
||||||
public ICommand StartSimulationCommand { get; }
|
public ICommand StartSimulationCommand { get; }
|
||||||
|
@ -125,14 +127,18 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void OnTickSimulacion(object sender, EventArgs e)
|
private void OnTickSimulacion(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var args = new TickSimulacionEventArgs();
|
|
||||||
OnTickSimulacion(args);
|
simulationManager.Step((float)_timerSimulacion.Interval.TotalMilliseconds);
|
||||||
|
|
||||||
|
foreach (var objetoSimulable in ObjetosSimulables)
|
||||||
|
objetoSimulable.UpdateControl();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnTickSimulacion(TickSimulacionEventArgs e)
|
//protected virtual void OnTickSimulacion(TickSimulacionEventArgs e)
|
||||||
{
|
//{
|
||||||
TickSimulacion?.Invoke(this, e);
|
// TickSimulacion?.Invoke(this, e);
|
||||||
}
|
//}
|
||||||
|
|
||||||
public string directorioTrabajo
|
public string directorioTrabajo
|
||||||
{
|
{
|
||||||
|
@ -276,7 +282,7 @@ namespace CtrEditor
|
||||||
if (userControl != null)
|
if (userControl != null)
|
||||||
{
|
{
|
||||||
// Asignar los datos al UserControl
|
// Asignar los datos al UserControl
|
||||||
UserControlFactory.AssignDatos(userControl, osObjeto);
|
UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager);
|
||||||
|
|
||||||
OnUserControlSelected?.Invoke(userControl);
|
OnUserControlSelected?.Invoke(userControl);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace CtrEditor
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (DataContext is MainViewModel viewModel)
|
||||||
{
|
{
|
||||||
viewModel.ImageSelected += ViewModel_ImageSelected;
|
viewModel.ImageSelected += ViewModel_ImageSelected;
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,8 @@ namespace CtrEditor
|
||||||
double top = centerY - (userControl.ActualHeight / 2);
|
double top = centerY - (userControl.ActualHeight / 2);
|
||||||
|
|
||||||
// Establece la posición del UserControl
|
// Establece la posición del UserControl
|
||||||
NuevoOS.Left = left;
|
NuevoOS.Left = (float)left;
|
||||||
NuevoOS.Top = top;
|
NuevoOS.Top = (float)top;
|
||||||
|
|
||||||
NuevoOS.Inicializado = true;
|
NuevoOS.Inicializado = true;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ namespace CtrEditor
|
||||||
var newY = Canvas.GetTop(_currentDraggingControl) + dy;
|
var newY = Canvas.GetTop(_currentDraggingControl) + dy;
|
||||||
|
|
||||||
if (_currentDraggingControl is IDataContainer dataContainer)
|
if (_currentDraggingControl is IDataContainer dataContainer)
|
||||||
dataContainer.Move(newX, newY);
|
dataContainer.Move((float)newX,(float) newY);
|
||||||
|
|
||||||
_startPointUserControl = currentPosition; // Actualiza el punto inicial para el siguiente movimiento
|
_startPointUserControl = currentPosition; // Actualiza el punto inicial para el siguiente movimiento
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ namespace CtrEditor
|
||||||
//rotateTransform.Angle = angle; // - _initialAngleUserControl; // Asegúrate de ajustar esta parte según cómo calcules el ángulo inicial
|
//rotateTransform.Angle = angle; // - _initialAngleUserControl; // Asegúrate de ajustar esta parte según cómo calcules el ángulo inicial
|
||||||
|
|
||||||
if (control is IDataContainer dataContainer)
|
if (control is IDataContainer dataContainer)
|
||||||
dataContainer.Rotate(angle);
|
dataContainer.Rotate((float)angle);
|
||||||
|
|
||||||
// Actualizar el ángulo mostrado
|
// Actualizar el ángulo mostrado
|
||||||
_angleDisplayTextBlock.Text = $"Ángulo: {angle:F2}°";
|
_angleDisplayTextBlock.Text = $"Ángulo: {angle:F2}°";
|
||||||
|
@ -267,7 +267,7 @@ namespace CtrEditor
|
||||||
control.Width = newWidth; // Asegurar que no sea menor que el mínimo
|
control.Width = newWidth; // Asegurar que no sea menor que el mínimo
|
||||||
|
|
||||||
if (control is IDataContainer dataContainer)
|
if (control is IDataContainer dataContainer)
|
||||||
dataContainer.Resize(newWidth, 0);
|
dataContainer.Resize((float)newWidth, 0);
|
||||||
|
|
||||||
// Actualizar el punto de inicio para el próximo evento de movimiento
|
// Actualizar el punto de inicio para el próximo evento de movimiento
|
||||||
_startPointUserControl = currentPosition;
|
_startPointUserControl = currentPosition;
|
||||||
|
@ -423,20 +423,6 @@ namespace CtrEditor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainViewModel_TickSimulacion(object sender, TickSimulacionEventArgs e)
|
|
||||||
{
|
|
||||||
// aquí puedes agregar la lógica para actualizar tus UserControl
|
|
||||||
// en el ImagenEnTrabajoCanvas
|
|
||||||
foreach (var child in ImagenEnTrabajoCanvas.Children)
|
|
||||||
{
|
|
||||||
if (child is osBase uc)
|
|
||||||
{
|
|
||||||
// llama al método Update de cada UserControl
|
|
||||||
uc.Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MainWindow_Closed(object sender, EventArgs e)
|
private void MainWindow_Closed(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (DataContext is MainViewModel viewModel)
|
||||||
|
|
|
@ -45,13 +45,14 @@ namespace CtrEditor.ObjetosSim
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AssignDatos(UserControl userControl, osBase datos)
|
public static void AssignDatos(UserControl userControl, osBase datos, SimulationManager 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,52 +14,29 @@ namespace CtrEditor.ObjetosSim
|
||||||
public interface IosBase
|
public interface IosBase
|
||||||
{
|
{
|
||||||
string Nombre { get; }
|
string Nombre { get; }
|
||||||
void Update();
|
|
||||||
|
void ConnectSimManager(SimulationManager simulationManager);
|
||||||
|
void UpdateControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDataContainer
|
public interface IDataContainer
|
||||||
{
|
{
|
||||||
osBase? Datos { get; set; }
|
osBase? Datos { get; set; }
|
||||||
void Resize(double width, double height);
|
void Resize(float width, float height);
|
||||||
void Move(double Left, double Top);
|
void Move(float Left, float Top);
|
||||||
void Rotate(double Angle);
|
void Rotate(float Angle);
|
||||||
void Highlight(bool State);
|
void Highlight(bool State);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class osBase : INotifyPropertyChanged, IosBase
|
public abstract class osBase : INotifyPropertyChanged, IosBase
|
||||||
{
|
{
|
||||||
private string _nombre = "Base";
|
private string _nombre = "Base";
|
||||||
public double _left;
|
public abstract float Left { get; set; }
|
||||||
public double _top;
|
public abstract float Top { get; set; }
|
||||||
|
|
||||||
public bool Inicializado = false;
|
public bool Inicializado = false;
|
||||||
public double Left
|
|
||||||
{
|
|
||||||
get => _left;
|
|
||||||
|
|
||||||
set
|
protected UserControl? _visualRepresentation = null;
|
||||||
{
|
|
||||||
_left = value;
|
|
||||||
if (_visualRepresentation != null)
|
|
||||||
Canvas.SetLeft(_visualRepresentation, _left);
|
|
||||||
OnPropertyChanged(nameof(Left));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public double Top
|
|
||||||
{
|
|
||||||
get => _top;
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_top = value;
|
|
||||||
if (_visualRepresentation != null)
|
|
||||||
Canvas.SetTop(_visualRepresentation, _top);
|
|
||||||
|
|
||||||
OnPropertyChanged(nameof(Top));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserControl? _visualRepresentation = null;
|
|
||||||
|
|
||||||
public string Nombre
|
public string Nombre
|
||||||
{
|
{
|
||||||
|
@ -74,7 +51,8 @@ namespace CtrEditor.ObjetosSim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Update();
|
public abstract void ConnectSimManager(SimulationManager simulationManager);
|
||||||
|
public abstract void UpdateControl();
|
||||||
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<UserControl x:Class="CtrEditor.ObjetosSim.ucBotella"
|
<UserControl x:Class="CtrEditor.ObjetosSim.ucBotella"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
DataContext="{Binding RelativeSource={RelativeSource Self}}">
|
<Ellipse Height="{Binding Diametro}" Stroke="red" Fill="Gray" Width="{Binding Diametro}"/>
|
||||||
<Border Background="Brown" CornerRadius="10" Height="10" Width="10"/>
|
|
||||||
</UserControl>
|
</UserControl>
|
|
@ -12,6 +12,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 System.Numerics;
|
||||||
|
|
||||||
namespace CtrEditor.ObjetosSim
|
namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
|
@ -22,14 +23,62 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
public class osBotella : osBase
|
public class osBotella : osBase
|
||||||
{
|
{
|
||||||
public double diametro { get; set; }
|
private Circle Data = new Circle();
|
||||||
|
|
||||||
// Otros datos y métodos relevantes para la simulación
|
// Otros datos y métodos relevantes para la simulación
|
||||||
|
|
||||||
private string _nombre = "Botella";
|
private string _nombre = "Botella";
|
||||||
public override void Update()
|
|
||||||
{
|
public float Diametro {
|
||||||
// implementation of Update method
|
get => Data.Diameter;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Diameter = value;
|
||||||
|
OnPropertyChanged(nameof(Diametro));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
public float Mass {
|
||||||
|
get => Data.Mass;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Mass = value;
|
||||||
|
OnPropertyChanged(nameof(Mass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float Left
|
||||||
|
{
|
||||||
|
get => Data.Center.X;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Center = new Vector2(value,Top);
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetLeft(_visualRepresentation, value);
|
||||||
|
OnPropertyChanged(nameof(Left));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float Top
|
||||||
|
{
|
||||||
|
get => Data.Center.Y;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Center = new Vector2(Left, value);
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetTop(_visualRepresentation, value);
|
||||||
|
OnPropertyChanged(nameof(Top));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void ConnectSimManager(SimulationManager simulationManager)
|
||||||
|
{
|
||||||
|
simulationManager.circles.Add(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateControl()
|
||||||
|
{
|
||||||
|
Top = Data.Center.Y;
|
||||||
|
Left = Data.Center.X;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ucBotella : UserControl, IDataContainer
|
public partial class ucBotella : UserControl, IDataContainer
|
||||||
|
@ -40,8 +89,8 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
public void Resize(double width, double height) { }
|
public void Resize(float width, float height) { }
|
||||||
public void Move(double Left, double Top)
|
public void Move(float Left, float Top)
|
||||||
{
|
{
|
||||||
if (Datos != null)
|
if (Datos != null)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +98,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
Datos.Top = Top;
|
Datos.Top = Top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Rotate(double Angle) { }
|
public void Rotate(float Angle) { }
|
||||||
public void Highlight(bool State) { }
|
public void Highlight(bool State) { }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Windows.Markup;
|
||||||
|
|
||||||
namespace CtrEditor.ObjetosSim
|
namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
|
@ -25,36 +27,74 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
private string _nombre = "Transporte TTOP";
|
private string _nombre = "Transporte TTOP";
|
||||||
|
|
||||||
private double _Ancho;
|
private float frictionCoefficient;
|
||||||
private double _Alto;
|
private float velMax50hz; // en metros por minuto
|
||||||
private double _Angulo;
|
private float tiempoRampa;
|
||||||
|
private bool esMarcha;
|
||||||
|
|
||||||
public double diametro { get; set; }
|
private Rectangle Data = new Rectangle();
|
||||||
public double Ancho {
|
|
||||||
get { return _Ancho; }
|
public override float Left
|
||||||
|
{
|
||||||
|
get => Data.Left;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_Ancho = value;
|
Data.Left = value;
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetLeft(_visualRepresentation, value);
|
||||||
|
OnPropertyChanged(nameof(Left));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float Top
|
||||||
|
{
|
||||||
|
get => Data.Top;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Top = value;
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetTop(_visualRepresentation, value);
|
||||||
|
OnPropertyChanged(nameof(Top));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Ancho {
|
||||||
|
get => Data.Width;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Width = value;
|
||||||
OnPropertyChanged(nameof(Ancho));
|
OnPropertyChanged(nameof(Ancho));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public double Alto {
|
public float Alto {
|
||||||
get { return _Alto; }
|
get => Data.Height;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_Alto = value;
|
Data.Height = value;
|
||||||
OnPropertyChanged(nameof(Alto));
|
OnPropertyChanged(nameof(Alto));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public double Angulo
|
public float Angulo
|
||||||
{
|
{
|
||||||
get { return _Angulo; }
|
get => Data.Angle;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_Angulo = value;
|
Data.Angle = value;
|
||||||
OnPropertyChanged(nameof(Angulo));
|
OnPropertyChanged(nameof(Angulo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public float VelocidadActual
|
||||||
|
{
|
||||||
|
get => Data.Speed;
|
||||||
|
set {
|
||||||
|
Data.Speed = value;
|
||||||
|
OnPropertyChanged(nameof(VelocidadActual));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float FrictionCoefficient { get => frictionCoefficient; set => frictionCoefficient = value; }
|
||||||
|
public float VelMax50hz { get => velMax50hz; set => velMax50hz = value; }
|
||||||
|
public float TiempoRampa { get => tiempoRampa; set => tiempoRampa = value; }
|
||||||
|
public bool EsMarcha { get => esMarcha; set => esMarcha = value; }
|
||||||
|
|
||||||
public osTransporteTTop()
|
public osTransporteTTop()
|
||||||
{
|
{
|
||||||
|
@ -62,10 +102,14 @@ namespace CtrEditor.ObjetosSim
|
||||||
Alto = 10;
|
Alto = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void ConnectSimManager(SimulationManager simulationManager)
|
||||||
{
|
{
|
||||||
// implementation of Update method
|
simulationManager.rectangles.Add(Data);
|
||||||
}
|
}
|
||||||
|
public override void UpdateControl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ucTransporteTTop : UserControl, IDataContainer
|
public partial class ucTransporteTTop : UserControl, IDataContainer
|
||||||
|
@ -76,12 +120,12 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
public void Resize(double width, double height)
|
public void Resize(float width, float height)
|
||||||
{
|
{
|
||||||
if (Datos is osTransporteTTop datos)
|
if (Datos is osTransporteTTop datos)
|
||||||
datos.Ancho = width;
|
datos.Ancho = width;
|
||||||
}
|
}
|
||||||
public void Move(double Left, double Top)
|
public void Move(float Left, float Top)
|
||||||
{
|
{
|
||||||
if (Datos != null)
|
if (Datos != null)
|
||||||
{
|
{
|
||||||
|
@ -89,7 +133,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
Datos.Top = Top;
|
Datos.Top = Top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Rotate(double Angle) {
|
public void Rotate(float Angle) {
|
||||||
if (Datos != null)
|
if (Datos != null)
|
||||||
if (Datos is osTransporteTTop datos)
|
if (Datos is osTransporteTTop datos)
|
||||||
datos.Angulo = Angle;
|
datos.Angulo = Angle;
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
// Definición de la clase Circle
|
||||||
|
public class Circle : ObjetoGeometrico
|
||||||
|
{
|
||||||
|
public Vector2 Center { get; set; }
|
||||||
|
public float Diameter { get; set; }
|
||||||
|
public float Mass { get; set; }
|
||||||
|
[JsonIgnore]
|
||||||
|
public Vector2 Velocity { get; set; }
|
||||||
|
|
||||||
|
public Circle(Vector2 center, float diameter, float mass, Vector2 velocity)
|
||||||
|
{
|
||||||
|
Center = center;
|
||||||
|
Diameter = diameter;
|
||||||
|
Mass = mass;
|
||||||
|
Velocity = velocity;
|
||||||
|
}
|
||||||
|
public Circle() {
|
||||||
|
Center = new Vector2(0,0);
|
||||||
|
Center.X = 0;
|
||||||
|
Diameter = 10;
|
||||||
|
Mass = 1;
|
||||||
|
Velocity = new Vector2(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método para calcular la nueva posición del círculo en función del tiempo
|
||||||
|
public void Move(float timeStep, List<Circle> circles, List<Rectangle> rectangles, List<Line> lines)
|
||||||
|
{
|
||||||
|
Vector2 totalForce = new Vector2(0, 0);
|
||||||
|
|
||||||
|
// Aplicar fuerza de los rectángulos
|
||||||
|
foreach (var rectangle in rectangles)
|
||||||
|
{
|
||||||
|
totalForce += rectangle.ApplyForce(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplicar fuerza a otros círculos
|
||||||
|
foreach (var otherCircle in circles)
|
||||||
|
{
|
||||||
|
if (otherCircle != this)
|
||||||
|
{
|
||||||
|
totalForce += ApplyForceToOtherCircle(otherCircle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplicar fuerza debido a la inercia (ejemplo simple)
|
||||||
|
Vector2 inertiaForce = -0.1f * Velocity; // coeficiente de inercia
|
||||||
|
totalForce += inertiaForce;
|
||||||
|
|
||||||
|
// Calcular la aceleración
|
||||||
|
if (Mass <= 0)
|
||||||
|
Mass = 1;
|
||||||
|
Vector2 acceleration = totalForce / Mass;
|
||||||
|
|
||||||
|
// Actualizar la velocidad y la posición
|
||||||
|
Velocity += acceleration * timeStep / 1000;
|
||||||
|
Center += Velocity * timeStep;
|
||||||
|
|
||||||
|
// Controlar la colisión con las líneas
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
line.HandleCollision(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 ApplyForceToOtherCircle(Circle other)
|
||||||
|
{
|
||||||
|
Vector2 direction = other.Center - this.Center;
|
||||||
|
float distance = direction.Length();
|
||||||
|
float overlap = this.Diameter / 2 + other.Diameter / 2 - distance;
|
||||||
|
|
||||||
|
if (overlap > 0)
|
||||||
|
{
|
||||||
|
Vector2 forceDirection = Vector2.Normalize(direction);
|
||||||
|
float transferVelocity = 0.5f * this.Velocity.Length(); // Ejemplo de transferencia de parte de la velocidad
|
||||||
|
if (transferVelocity == 0)
|
||||||
|
transferVelocity = 0.01f;
|
||||||
|
other.Velocity += forceDirection * transferVelocity; // Asumiendo una simplificación del impacto
|
||||||
|
return -forceDirection * transferVelocity; // Retorno de fuerza opuesta aplicada a este círculo
|
||||||
|
}
|
||||||
|
return Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Definición de la clase Rectangle
|
||||||
|
public class Rectangle : ObjetoGeometrico
|
||||||
|
{
|
||||||
|
public Vector2 AnchorPoint { get; set; }
|
||||||
|
public float Left { get; set; }
|
||||||
|
public float Top { get; set; }
|
||||||
|
public float Width { get; set; }
|
||||||
|
public float Height { get; set; }
|
||||||
|
public float Angle { get; set; }
|
||||||
|
public float Speed { get; set; }
|
||||||
|
|
||||||
|
public Rectangle(Vector2 anchorPoint, float width, float height, float angle)
|
||||||
|
{
|
||||||
|
AnchorPoint = anchorPoint;
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
Angle = angle;
|
||||||
|
}
|
||||||
|
public Rectangle()
|
||||||
|
{
|
||||||
|
AnchorPoint = new Vector2(0,0);
|
||||||
|
Width = 1;
|
||||||
|
Height = 1;
|
||||||
|
Angle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Vector2 ApplyForce(Circle circle)
|
||||||
|
{
|
||||||
|
// Transformar el centro del círculo al sistema de coordenadas del rectángulo
|
||||||
|
Vector2 circlePositionRelative = Vector2.Transform(circle.Center - AnchorPoint, Matrix3x2.CreateRotation(-Angle));
|
||||||
|
|
||||||
|
// Verificar si el círculo está dentro del rectángulo
|
||||||
|
float halfWidth = Width / 2;
|
||||||
|
float halfHeight = Height / 2;
|
||||||
|
if (Math.Abs(circlePositionRelative.X) <= halfWidth && Math.Abs(circlePositionRelative.Y) <= halfHeight)
|
||||||
|
{
|
||||||
|
// Calcular fuerza basada en la proximidad al centro del rectángulo
|
||||||
|
float distanceFromCenter = circlePositionRelative.Length();
|
||||||
|
float forceMagnitude = Math.Max(0, (Width - distanceFromCenter) / Width); // Simplificación de la magnitud de la fuerza
|
||||||
|
Vector2 forceDirection = Vector2.Transform(new Vector2(1, 0), Matrix3x2.CreateRotation(Angle)); // Fuerza en la dirección del rectángulo
|
||||||
|
return forceDirection * forceMagnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Definición de la clase Line
|
||||||
|
public class Line : ObjetoGeometrico
|
||||||
|
{
|
||||||
|
public Vector2 StartPoint { get; set; }
|
||||||
|
public Vector2 EndPoint { get; set; }
|
||||||
|
|
||||||
|
public Line(Vector2 startPoint, Vector2 endPoint)
|
||||||
|
{
|
||||||
|
StartPoint = startPoint;
|
||||||
|
EndPoint = endPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleCollision(Circle circle)
|
||||||
|
{
|
||||||
|
Vector2 closestPoint = ClosestPoint(circle.Center);
|
||||||
|
float radius = circle.Diameter / 2;
|
||||||
|
if (Vector2.Distance(circle.Center, closestPoint) < radius)
|
||||||
|
{
|
||||||
|
Vector2 lineDirection = Vector2.Normalize(EndPoint - StartPoint);
|
||||||
|
Vector2 normal = new Vector2(-lineDirection.Y, lineDirection.X); // Normal perpendicular a la dirección de la línea
|
||||||
|
circle.Velocity = Vector2.Reflect(circle.Velocity, normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Vector2 ClosestPoint(Vector2 point)
|
||||||
|
{
|
||||||
|
Vector2 AP = point - StartPoint;
|
||||||
|
Vector2 AB = EndPoint - StartPoint;
|
||||||
|
float magnitudeAB = AB.LengthSquared();
|
||||||
|
float ABAPproduct = Vector2.Dot(AP, AB);
|
||||||
|
float distance = ABAPproduct / magnitudeAB;
|
||||||
|
return StartPoint + AB * Math.Clamp(distance, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ObjetoGeometrico
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
// Clase principal que gestiona la simulación
|
||||||
|
public class SimulationManager
|
||||||
|
{
|
||||||
|
public List<Circle> circles;
|
||||||
|
public List<Rectangle> rectangles;
|
||||||
|
public List<Line> lines;
|
||||||
|
|
||||||
|
public SimulationManager()
|
||||||
|
{
|
||||||
|
circles = new List<Circle>();
|
||||||
|
rectangles = new List<Rectangle>();
|
||||||
|
lines = new List<Line>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Step(float timeStep)
|
||||||
|
{
|
||||||
|
foreach (var circle in circles)
|
||||||
|
{
|
||||||
|
circle.Move(timeStep, circles, rectangles, lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue