Funcionando la simulacion pero con problemas con el calculo de overlap
This commit is contained in:
parent
3ba10b81c3
commit
ef7d3e2618
|
@ -21,6 +21,7 @@ using System.Text.Json;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using static System.Resources.ResXFileRef;
|
||||||
|
|
||||||
namespace CtrEditor
|
namespace CtrEditor
|
||||||
{
|
{
|
||||||
|
@ -56,7 +57,7 @@ namespace CtrEditor
|
||||||
ItemDoubleClickCommand = new ParameterizedRelayCommand(ExecuteDoubleClick);
|
ItemDoubleClickCommand = new ParameterizedRelayCommand(ExecuteDoubleClick);
|
||||||
|
|
||||||
_timerSimulacion = new DispatcherTimer();
|
_timerSimulacion = new DispatcherTimer();
|
||||||
_timerSimulacion.Interval = TimeSpan.FromMilliseconds(100); // ajusta el intervalo según sea necesario
|
_timerSimulacion.Interval = TimeSpan.FromMilliseconds(20); // ajusta el intervalo según sea necesario
|
||||||
_timerSimulacion.Tick += OnTickSimulacion;
|
_timerSimulacion.Tick += OnTickSimulacion;
|
||||||
|
|
||||||
StartSimulationCommand = new RelayCommand(StartSimulation);
|
StartSimulationCommand = new RelayCommand(StartSimulation);
|
||||||
|
@ -168,6 +169,7 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (_selectedImage != value && value != null)
|
if (_selectedImage != value && value != null)
|
||||||
{
|
{
|
||||||
|
StopSimulation();
|
||||||
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
|
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
|
||||||
_selectedImage = value;
|
_selectedImage = value;
|
||||||
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
|
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
|
||||||
|
@ -235,7 +237,14 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
obj.VisualRepresentation = null;
|
obj.VisualRepresentation = null;
|
||||||
}
|
}
|
||||||
var serializedData = JsonConvert.SerializeObject(ObjetosSimulables, settings);
|
// Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter
|
||||||
|
var dataToSerialize = new SimulationData
|
||||||
|
{
|
||||||
|
ObjetosSimulables = ObjetosSimulables,
|
||||||
|
UnitConverter = PixelToMeter.Instance.calc
|
||||||
|
};
|
||||||
|
|
||||||
|
var serializedData = JsonConvert.SerializeObject(dataToSerialize, settings);
|
||||||
File.WriteAllText(datosDeTrabajo.ObtenerPathImagenConExtension(_selectedImage, ".json"), serializedData);
|
File.WriteAllText(datosDeTrabajo.ObtenerPathImagenConExtension(_selectedImage, ".json"), serializedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,11 +267,16 @@ namespace CtrEditor
|
||||||
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
|
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
|
||||||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
||||||
};
|
};
|
||||||
if (jsonString != null)
|
|
||||||
{
|
|
||||||
ObjetosSimulables = JsonConvert.DeserializeObject<ObservableCollection<osBase>>(jsonString, settings);
|
|
||||||
|
|
||||||
// Ahora recorres la colección de objetos simulables
|
var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
|
||||||
|
if (simulationData != null)
|
||||||
|
{
|
||||||
|
ObjetosSimulables = simulationData.ObjetosSimulables;
|
||||||
|
|
||||||
|
// Restaura el UnitConverter si es necesario en otra parte de tu código
|
||||||
|
PixelToMeter.Instance.calc = simulationData.UnitConverter;
|
||||||
|
|
||||||
|
// Recorrer la colección de objetos simulables
|
||||||
foreach (var objetoSimulable in ObjetosSimulables)
|
foreach (var objetoSimulable in ObjetosSimulables)
|
||||||
CrearUsercontrol(objetoSimulable);
|
CrearUsercontrol(objetoSimulable);
|
||||||
}
|
}
|
||||||
|
@ -272,6 +286,7 @@ namespace CtrEditor
|
||||||
catch { /* Consider logging the error or handling it appropriately */ }
|
catch { /* Consider logging the error or handling it appropriately */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool CrearUsercontrol(osBase osObjeto)
|
private bool CrearUsercontrol(osBase osObjeto)
|
||||||
{
|
{
|
||||||
Type tipoObjeto = osObjeto.GetType();
|
Type tipoObjeto = osObjeto.GetType();
|
||||||
|
@ -303,6 +318,11 @@ namespace CtrEditor
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public class SimulationData
|
||||||
|
{
|
||||||
|
public ObservableCollection<osBase> ObjetosSimulables { get; set; }
|
||||||
|
public UnitConverter UnitConverter { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class TipoSimulable
|
public class TipoSimulable
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace CtrEditor
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for MainWindow.xaml
|
/// Interaction logic for MainWindow.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
///
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
// Para el Canvas
|
// Para el Canvas
|
||||||
|
@ -85,19 +86,21 @@ namespace CtrEditor
|
||||||
double centerY = offsetY + (visibleHeight / scaleY) / 2;
|
double centerY = offsetY + (visibleHeight / scaleY) / 2;
|
||||||
|
|
||||||
// Ajusta la posición del UserControl para que esté centrado en el área visible
|
// Ajusta la posición del UserControl para que esté centrado en el área visible
|
||||||
double left = centerX - (userControl.ActualWidth / 2);
|
double leftPixels = centerX - (userControl.ActualWidth / 2);
|
||||||
double top = centerY - (userControl.ActualHeight / 2);
|
double topPixels = centerY - (userControl.ActualHeight / 2);
|
||||||
|
|
||||||
// Establece la posición del UserControl
|
// Establece la posición del UserControl
|
||||||
NuevoOS.Left = (float)left;
|
NuevoOS.LeftPixels = (float)leftPixels;
|
||||||
NuevoOS.Top = (float)top;
|
NuevoOS.TopPixels = (float)topPixels;
|
||||||
|
|
||||||
NuevoOS.Inicializado = true;
|
NuevoOS.Inicializado = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Establece la posición del UserControl
|
{
|
||||||
Canvas.SetLeft(userControl, NuevoOS.Left);
|
// Fuerza a Establecer la posición del UserControl
|
||||||
Canvas.SetTop(userControl, NuevoOS.Top);
|
NuevoOS.LeftPixels = NuevoOS.LeftPixels;
|
||||||
|
NuevoOS.TopPixels = NuevoOS.TopPixels;
|
||||||
|
}
|
||||||
|
|
||||||
// Suscribirse a eventos de mouse para marcar el Control
|
// Suscribirse a eventos de mouse para marcar el Control
|
||||||
userControl.MouseEnter += UserControl_MouseEnter;
|
userControl.MouseEnter += UserControl_MouseEnter;
|
||||||
|
@ -109,6 +112,7 @@ namespace CtrEditor
|
||||||
userControl.MouseMove += UserControl_MouseMove;
|
userControl.MouseMove += UserControl_MouseMove;
|
||||||
|
|
||||||
// Añade el UserControl al Canvas
|
// Añade el UserControl al Canvas
|
||||||
|
Canvas.SetZIndex(userControl, dataContainer.ZIndex());
|
||||||
ImagenEnTrabajoCanvas.Children.Add(userControl);
|
ImagenEnTrabajoCanvas.Children.Add(userControl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,13 @@ namespace CtrEditor.ObjetosSim
|
||||||
void Move(float Left, float Top);
|
void Move(float Left, float Top);
|
||||||
void Rotate(float Angle);
|
void Rotate(float Angle);
|
||||||
void Highlight(bool State);
|
void Highlight(bool State);
|
||||||
|
int ZIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class osBase : INotifyPropertyChanged, IosBase
|
public abstract class osBase : INotifyPropertyChanged, IosBase
|
||||||
{
|
{
|
||||||
private string _nombre = "Base";
|
public abstract float LeftPixels { get; set; }
|
||||||
|
public abstract float TopPixels { get; set; }
|
||||||
public abstract float Left { get; set; }
|
public abstract float Left { get; set; }
|
||||||
public abstract float Top { get; set; }
|
public abstract float Top { get; set; }
|
||||||
|
|
||||||
|
@ -38,29 +40,18 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
protected UserControl? _visualRepresentation = null;
|
protected UserControl? _visualRepresentation = null;
|
||||||
|
|
||||||
public string Nombre
|
public abstract string Nombre { get; set; }
|
||||||
{
|
|
||||||
get => _nombre;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_nombre != value)
|
|
||||||
{
|
|
||||||
_nombre = value;
|
|
||||||
OnPropertyChanged(nameof(Nombre));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void ConnectSimManager(SimulationManager simulationManager);
|
public abstract void ConnectSimManager(SimulationManager simulationManager);
|
||||||
public abstract void UpdateControl();
|
public abstract void UpdateControl();
|
||||||
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public UserControl? VisualRepresentation
|
public UserControl? VisualRepresentation
|
||||||
{
|
{
|
||||||
get => _visualRepresentation;
|
get => _visualRepresentation;
|
||||||
set => _visualRepresentation = value;
|
set => _visualRepresentation = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
protected virtual void OnPropertyChanged(string propertyName)
|
protected virtual void OnPropertyChanged(string propertyName)
|
||||||
|
@ -68,4 +59,62 @@ namespace CtrEditor.ObjetosSim
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PixelToMeter
|
||||||
|
{
|
||||||
|
// Instancia privada estática, parte del patrón Singleton
|
||||||
|
private static PixelToMeter? _instance;
|
||||||
|
public UnitConverter calc = new UnitConverter(0.01f);
|
||||||
|
|
||||||
|
// Propiedad pública estática para acceder a la instancia
|
||||||
|
public static PixelToMeter Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
_instance = new PixelToMeter();
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UnitConverter
|
||||||
|
{
|
||||||
|
// La escala representa cuántos metros hay en un píxel
|
||||||
|
public float Scale { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
public UnitConverter(float scale)
|
||||||
|
{
|
||||||
|
if (scale <= 0)
|
||||||
|
throw new ArgumentException("Scale must be greater than zero.");
|
||||||
|
|
||||||
|
Scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convierte una distancia en metros a píxeles
|
||||||
|
public float MetersToPixels(float meters)
|
||||||
|
{
|
||||||
|
return meters / Scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convierte una distancia en píxeles a metros
|
||||||
|
public float PixelsToMeters(float pixels)
|
||||||
|
{
|
||||||
|
return pixels * Scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurar o ajustar la escala
|
||||||
|
public void SetScale(float newScale)
|
||||||
|
{
|
||||||
|
if (newScale <= 0)
|
||||||
|
throw new ArgumentException("Scale must be greater than zero.");
|
||||||
|
|
||||||
|
Scale = newScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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">
|
||||||
<Ellipse Height="{Binding Diametro}" Stroke="red" Fill="Gray" Width="{Binding Diametro}"/>
|
<Ellipse Height="{Binding DiametroPixels}" Stroke="red" Fill="Gray" Width="{Binding DiametroPixels}"/>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
|
@ -35,8 +35,20 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
Data.Diameter = value;
|
Data.Diameter = value;
|
||||||
OnPropertyChanged(nameof(Diametro));
|
OnPropertyChanged(nameof(Diametro));
|
||||||
|
OnPropertyChanged(nameof(DiametroPixels));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public float DiametroPixels
|
||||||
|
{
|
||||||
|
get => PixelToMeter.Instance.calc.MetersToPixels(Data.Diameter);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Diameter = PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
|
OnPropertyChanged(nameof(Diametro));
|
||||||
|
OnPropertyChanged(nameof(DiametroPixels));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public float Mass {
|
public float Mass {
|
||||||
get => Data.Mass;
|
get => Data.Mass;
|
||||||
set
|
set
|
||||||
|
@ -46,28 +58,73 @@ namespace CtrEditor.ObjetosSim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float Left
|
public override float LeftPixels
|
||||||
{
|
{
|
||||||
get => Data.Center.X;
|
get => PixelToMeter.Instance.calc.MetersToPixels(Data.Left);
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Data.Center = new Vector2(value,Top);
|
Data.Left = PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
if (_visualRepresentation != null)
|
if (_visualRepresentation != null)
|
||||||
Canvas.SetLeft(_visualRepresentation, value);
|
Canvas.SetLeft(_visualRepresentation, value);
|
||||||
|
OnPropertyChanged(nameof(LeftPixels));
|
||||||
|
OnPropertyChanged(nameof(Left));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float TopPixels
|
||||||
|
{
|
||||||
|
get => PixelToMeter.Instance.calc.MetersToPixels(Data.Top);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Top = PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetTop(_visualRepresentation,value);
|
||||||
|
OnPropertyChanged(nameof(TopPixels));
|
||||||
|
OnPropertyChanged(nameof(Top));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float Left
|
||||||
|
{
|
||||||
|
get => Data.Left;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Left = value;
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value));
|
||||||
|
OnPropertyChanged(nameof(LeftPixels));
|
||||||
OnPropertyChanged(nameof(Left));
|
OnPropertyChanged(nameof(Left));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override float Top
|
public override float Top
|
||||||
{
|
{
|
||||||
get => Data.Center.Y;
|
get => Data.Top;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Data.Center = new Vector2(Left, value);
|
Data.Top = value;
|
||||||
if (_visualRepresentation != null)
|
if (_visualRepresentation != null)
|
||||||
Canvas.SetTop(_visualRepresentation, value);
|
Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value));
|
||||||
|
OnPropertyChanged(nameof(TopPixels));
|
||||||
OnPropertyChanged(nameof(Top));
|
OnPropertyChanged(nameof(Top));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string Nombre
|
||||||
|
{
|
||||||
|
get => _nombre;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_nombre != value)
|
||||||
|
{
|
||||||
|
_nombre = value;
|
||||||
|
OnPropertyChanged(nameof(Nombre));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public osBotella()
|
||||||
|
{
|
||||||
|
DiametroPixels = 10;
|
||||||
|
}
|
||||||
|
|
||||||
public override void ConnectSimManager(SimulationManager simulationManager)
|
public override void ConnectSimManager(SimulationManager simulationManager)
|
||||||
{
|
{
|
||||||
simulationManager.circles.Add(Data);
|
simulationManager.circles.Add(Data);
|
||||||
|
@ -75,10 +132,9 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
public override void UpdateControl()
|
public override void UpdateControl()
|
||||||
{
|
{
|
||||||
Top = Data.Center.Y;
|
Top = Data.Top;
|
||||||
Left = Data.Center.X;
|
Left = Data.Left;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ucBotella : UserControl, IDataContainer
|
public partial class ucBotella : UserControl, IDataContainer
|
||||||
|
@ -90,16 +146,19 @@ namespace CtrEditor.ObjetosSim
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
public void Resize(float width, float height) { }
|
public void Resize(float width, float height) { }
|
||||||
public void Move(float Left, float Top)
|
public void Move(float LeftPixels, float TopPixels)
|
||||||
{
|
{
|
||||||
if (Datos != null)
|
if (Datos != null)
|
||||||
{
|
{
|
||||||
Datos.Left = Left;
|
Datos.LeftPixels = LeftPixels;
|
||||||
Datos.Top = Top;
|
Datos.TopPixels = TopPixels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Rotate(float Angle) { }
|
public void Rotate(float Angle) { }
|
||||||
public void Highlight(bool State) { }
|
public void Highlight(bool State) { }
|
||||||
|
public int ZIndex()
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
xmlns:local="clr-namespace:CtrEditor"
|
xmlns:local="clr-namespace:CtrEditor"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Canvas>
|
<Canvas>
|
||||||
<Rectangle Width="{Binding Ancho}" Height="{Binding Alto}" Fill="Gray">
|
<Rectangle Width="{Binding AnchoPixels}" Height="{Binding AltoPixels}" Fill="Gray">
|
||||||
<Rectangle.RenderTransform>
|
<Rectangle.RenderTransform>
|
||||||
<RotateTransform Angle="{Binding Angulo}"/>
|
<RotateTransform Angle="{Binding Angulo}"/>
|
||||||
</Rectangle.RenderTransform>
|
</Rectangle.RenderTransform>
|
||||||
|
|
|
@ -34,6 +34,30 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
private Rectangle Data = new Rectangle();
|
private Rectangle Data = new Rectangle();
|
||||||
|
|
||||||
|
public override float LeftPixels
|
||||||
|
{
|
||||||
|
get => PixelToMeter.Instance.calc.MetersToPixels(Data.Left);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Left = PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
|
if (_visualRepresentation != null )
|
||||||
|
Canvas.SetLeft(_visualRepresentation,value);
|
||||||
|
OnPropertyChanged(nameof(LeftPixels));
|
||||||
|
OnPropertyChanged(nameof(Left));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float TopPixels
|
||||||
|
{
|
||||||
|
get => PixelToMeter.Instance.calc.MetersToPixels(Data.Top);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Top = PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
|
if (_visualRepresentation != null)
|
||||||
|
Canvas.SetTop(_visualRepresentation, value);
|
||||||
|
OnPropertyChanged(nameof(TopPixels));
|
||||||
|
OnPropertyChanged(nameof(Top));
|
||||||
|
}
|
||||||
|
}
|
||||||
public override float Left
|
public override float Left
|
||||||
{
|
{
|
||||||
get => Data.Left;
|
get => Data.Left;
|
||||||
|
@ -41,7 +65,8 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
Data.Left = value;
|
Data.Left = value;
|
||||||
if (_visualRepresentation != null)
|
if (_visualRepresentation != null)
|
||||||
Canvas.SetLeft(_visualRepresentation, value);
|
Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value));
|
||||||
|
OnPropertyChanged(nameof(LeftPixels));
|
||||||
OnPropertyChanged(nameof(Left));
|
OnPropertyChanged(nameof(Left));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,27 +77,48 @@ namespace CtrEditor.ObjetosSim
|
||||||
{
|
{
|
||||||
Data.Top = value;
|
Data.Top = value;
|
||||||
if (_visualRepresentation != null)
|
if (_visualRepresentation != null)
|
||||||
Canvas.SetTop(_visualRepresentation, value);
|
Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value));
|
||||||
|
OnPropertyChanged(nameof(TopPixels));
|
||||||
OnPropertyChanged(nameof(Top));
|
OnPropertyChanged(nameof(Top));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public float Ancho {
|
public float Ancho {
|
||||||
get => Data.Width;
|
get => Data.Length;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Data.Width = value;
|
Data.Length = value;
|
||||||
OnPropertyChanged(nameof(Ancho));
|
OnPropertyChanged(nameof(Ancho));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public float Alto {
|
public float Alto {
|
||||||
get => Data.Height;
|
get => Data.Width;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Data.Height = value;
|
Data.Width = value;
|
||||||
OnPropertyChanged(nameof(Alto));
|
OnPropertyChanged(nameof(Alto));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public float AnchoPixels
|
||||||
|
{
|
||||||
|
get => (float)PixelToMeter.Instance.calc.MetersToPixels(Data.Length);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Length = (float)PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
|
OnPropertyChanged(nameof(Ancho));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public float AltoPixels
|
||||||
|
{
|
||||||
|
get => (float)PixelToMeter.Instance.calc.MetersToPixels(Data.Width);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Data.Width = (float)PixelToMeter.Instance.calc.PixelsToMeters(value);
|
||||||
|
OnPropertyChanged(nameof(Alto));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public float Angulo
|
public float Angulo
|
||||||
{
|
{
|
||||||
get => Data.Angle;
|
get => Data.Angle;
|
||||||
|
@ -91,6 +137,19 @@ namespace CtrEditor.ObjetosSim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string Nombre
|
||||||
|
{
|
||||||
|
get => _nombre;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_nombre != value)
|
||||||
|
{
|
||||||
|
_nombre = value;
|
||||||
|
OnPropertyChanged(nameof(Nombre));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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; }
|
||||||
|
@ -98,8 +157,8 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
public osTransporteTTop()
|
public osTransporteTTop()
|
||||||
{
|
{
|
||||||
Ancho = 100;
|
AnchoPixels = 100;
|
||||||
Alto = 10;
|
AltoPixels = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ConnectSimManager(SimulationManager simulationManager)
|
public override void ConnectSimManager(SimulationManager simulationManager)
|
||||||
|
@ -125,12 +184,12 @@ namespace CtrEditor.ObjetosSim
|
||||||
if (Datos is osTransporteTTop datos)
|
if (Datos is osTransporteTTop datos)
|
||||||
datos.Ancho = width;
|
datos.Ancho = width;
|
||||||
}
|
}
|
||||||
public void Move(float Left, float Top)
|
public void Move(float LeftPixels, float TopPixels)
|
||||||
{
|
{
|
||||||
if (Datos != null)
|
if (Datos != null)
|
||||||
{
|
{
|
||||||
Datos.Left = Left;
|
Datos.LeftPixels = LeftPixels;
|
||||||
Datos.Top = Top;
|
Datos.TopPixels = TopPixels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Rotate(float Angle) {
|
public void Rotate(float Angle) {
|
||||||
|
@ -139,6 +198,11 @@ namespace CtrEditor.ObjetosSim
|
||||||
datos.Angulo = Angle;
|
datos.Angulo = Angle;
|
||||||
}
|
}
|
||||||
public void Highlight(bool State) { }
|
public void Highlight(bool State) { }
|
||||||
|
public int ZIndex()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,179 +1,328 @@
|
||||||
using Newtonsoft.Json;
|
using CtrEditor.ObjetosSim;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Eventing.Reader;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
// Definición de la clase Circle
|
public class Circle
|
||||||
public class Circle : ObjetoGeometrico
|
|
||||||
{
|
{
|
||||||
public Vector2 Center { get; set; }
|
private Vector2 position;
|
||||||
|
public float Left
|
||||||
|
{
|
||||||
|
get { return position.X; }
|
||||||
|
set { position.X = value; }
|
||||||
|
}
|
||||||
|
public float Top
|
||||||
|
{
|
||||||
|
get { return position.Y; }
|
||||||
|
set { position.Y = value; }
|
||||||
|
}
|
||||||
public float Diameter { get; set; }
|
public float Diameter { get; set; }
|
||||||
public float Mass { get; set; }
|
public float Mass { get; set; }
|
||||||
[JsonIgnore]
|
public float Angle { get; set; } // En grados
|
||||||
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 float Speed { get; set; }
|
||||||
|
|
||||||
public Rectangle(Vector2 anchorPoint, float width, float height, float angle)
|
public Circle(float left = 0, float top = 0, float diameter = 10, float mass = 1, float angle = 0, float speed = 0)
|
||||||
{
|
{
|
||||||
AnchorPoint = anchorPoint;
|
position = new Vector2(left, top);
|
||||||
Width = width;
|
Diameter = diameter;
|
||||||
Height = height;
|
Mass = mass;
|
||||||
Angle = angle;
|
Angle = angle;
|
||||||
|
Speed = speed;
|
||||||
}
|
}
|
||||||
public Rectangle()
|
|
||||||
|
public void Move(float timeStep_ms, List<Circle> circles, List<Rectangle> rectangles, List<Line> lines)
|
||||||
{
|
{
|
||||||
AnchorPoint = new Vector2(0,0);
|
// Convertir timeStep de milisegundos a segundos para la simulación
|
||||||
Width = 1;
|
float timeStepInSeconds = timeStep_ms / 1000.0f;
|
||||||
Height = 1;
|
bool isTracted = false; // Indicador para verificar si el círculo está siendo traccionado
|
||||||
Angle = 0;
|
|
||||||
|
// Aplicar fuerza desde el rectángulo si está sobre uno
|
||||||
|
foreach (var rectangle in rectangles)
|
||||||
|
{
|
||||||
|
float overlap = CalculateOverlapPercentage(this, rectangle);
|
||||||
|
if (overlap > 0)
|
||||||
|
{
|
||||||
|
isTracted = true; // El círculo está siendo traccionado por un rectángulo
|
||||||
|
// Convertir la velocidad del rectángulo de metros por minuto a metros por segundo
|
||||||
|
float rectangleSpeedInMetersPerSecond = rectangle.Speed / 60.0f;
|
||||||
|
|
||||||
|
if (rectangleSpeedInMetersPerSecond < Speed)
|
||||||
|
{
|
||||||
|
// Aplicar una fuerza de frenado si la velocidad del rectángulo es menor que la velocidad del círculo
|
||||||
|
float brakingForce = (Speed - rectangleSpeedInMetersPerSecond) * (overlap / 100.0f);
|
||||||
|
Speed -= brakingForce * timeStepInSeconds;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Alinear gradualmente la velocidad del círculo con la del rectángulo si es mayor
|
||||||
|
Speed += (rectangleSpeedInMetersPerSecond - Speed) * (overlap / 100.0f) * timeStepInSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
Angle = rectangle.Angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si el círculo no está siendo traccionado, aplicar desaceleración
|
||||||
|
if (!isTracted)
|
||||||
|
{
|
||||||
|
float deceleration = (1.0f / Mass) * 10.0f; // Coeficiente de desaceleración inversamente proporcional a la masa
|
||||||
|
Speed -= deceleration * timeStepInSeconds;
|
||||||
|
if (Speed < 0) Speed = 0; // Evitar que la velocidad sea negativa
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Interacción por impacto con otros círculos
|
||||||
|
//foreach (var other in circles)
|
||||||
|
//{
|
||||||
|
// if (this != other && IsColliding(this, other))
|
||||||
|
// {
|
||||||
|
// Vector2 impactDirection = other.position - this.position;
|
||||||
|
// Angle = (float)Math.Atan2(impactDirection.Y, impactDirection.X) * (180 / (float)Math.PI);
|
||||||
|
// Speed = other.Speed; // Asumimos que el círculo receptor adopta la velocidad del impacto
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Ajustar por superposición con otros círculos
|
||||||
|
foreach (var other in circles)
|
||||||
|
{
|
||||||
|
if (this != other && IsColliding(this, other))
|
||||||
|
{
|
||||||
|
AdjustForOverlap(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambiar dirección al contacto con líneas
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
if (IsCollidingWithLine(this, line))
|
||||||
|
{
|
||||||
|
float impactAngle = CalculateImpactAngle(this, line);
|
||||||
|
if (impactAngle < 85)
|
||||||
|
{
|
||||||
|
Angle = line.Angle;
|
||||||
|
}
|
||||||
|
else if (impactAngle > 95)
|
||||||
|
{
|
||||||
|
Angle = line.Angle + 180; // Movimiento contrario
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Speed = 0; // Cancelación de movimiento
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcular nueva posición
|
||||||
|
Vector2 direction = new Vector2((float)Math.Cos(Angle * Math.PI / 180), (float)Math.Sin(Angle * Math.PI / 180));
|
||||||
|
Vector2 velocity = direction * Speed * timeStepInSeconds;
|
||||||
|
position += velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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
|
private void AdjustForOverlap(Circle other)
|
||||||
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
|
if (this == other) return; // No auto-interacción
|
||||||
float distanceFromCenter = circlePositionRelative.Length();
|
|
||||||
float forceMagnitude = Math.Max(0, (Width - distanceFromCenter) / Width); // Simplificación de la magnitud de la fuerza
|
float distance = Vector2.Distance(this.position, other.position);
|
||||||
Vector2 forceDirection = Vector2.Transform(new Vector2(1, 0), Matrix3x2.CreateRotation(Angle)); // Fuerza en la dirección del rectángulo
|
float radiusSum = (this.Diameter / 2) + (other.Diameter / 2);
|
||||||
return forceDirection * forceMagnitude;
|
|
||||||
|
if (distance < radiusSum) // Los círculos están solapando
|
||||||
|
{
|
||||||
|
Vector2 directionToOther = Vector2.Normalize(other.position - this.position);
|
||||||
|
float overlapDistance = radiusSum - distance;
|
||||||
|
|
||||||
|
// Decidir qué círculo mover basado en sus velocidades
|
||||||
|
if (this.Speed == 0 && other.Speed > 0)
|
||||||
|
{
|
||||||
|
// Mover este círculo si su velocidad es cero y el otro se está moviendo
|
||||||
|
this.position -= directionToOther * overlapDistance;
|
||||||
|
}
|
||||||
|
else if (other.Speed == 0 && this.Speed > 0)
|
||||||
|
{
|
||||||
|
// Mover el otro círculo si su velocidad es cero y este se está moviendo
|
||||||
|
other.position += directionToOther * overlapDistance;
|
||||||
|
}
|
||||||
|
else if (this.Speed == 0 && other.Speed == 0)
|
||||||
|
{
|
||||||
|
// Si ambos tienen velocidad cero, mover ambos a la mitad del solapamiento
|
||||||
|
this.position -= directionToOther * (overlapDistance / 2);
|
||||||
|
other.position += directionToOther * (overlapDistance / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Vector2.Zero;
|
|
||||||
|
private bool IsColliding(Circle circle1, Circle circle2)
|
||||||
|
{
|
||||||
|
float distance = Vector2.Distance(circle1.position, circle2.position);
|
||||||
|
float radiusSum = (circle1.Diameter / 2) + (circle2.Diameter / 2);
|
||||||
|
return distance <= radiusSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsCollidingWithLine(Circle circle, Line line)
|
||||||
|
{
|
||||||
|
Vector2 nearestPoint = NearestPointOnLine(circle.position, line.start, line.end);
|
||||||
|
float distanceToLine = Vector2.Distance(circle.position, nearestPoint);
|
||||||
|
return distanceToLine <= (circle.Diameter / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definición de la clase Line
|
private Vector2 NearestPointOnLine(Vector2 point, Vector2 lineStart, Vector2 lineEnd)
|
||||||
public class Line : ObjetoGeometrico
|
|
||||||
{
|
{
|
||||||
public Vector2 StartPoint { get; set; }
|
Vector2 lineVector = lineEnd - lineStart;
|
||||||
public Vector2 EndPoint { get; set; }
|
Vector2 pointVector = point - lineStart;
|
||||||
|
float lineLength = lineVector.Length();
|
||||||
public Line(Vector2 startPoint, Vector2 endPoint)
|
float projectedLength = Vector2.Dot(pointVector, lineVector) / lineLength;
|
||||||
{
|
projectedLength = Math.Max(0, Math.Min(lineLength, projectedLength)); // Clamping to the line segment
|
||||||
StartPoint = startPoint;
|
return lineStart + lineVector * (projectedLength / lineLength);
|
||||||
EndPoint = endPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HandleCollision(Circle circle)
|
private float CalculateImpactAngle(Circle circle, Line line)
|
||||||
{
|
{
|
||||||
Vector2 closestPoint = ClosestPoint(circle.Center);
|
Vector2 movementDirection = new Vector2((float)Math.Cos(circle.Angle * Math.PI / 180), (float)Math.Sin(circle.Angle * Math.PI / 180));
|
||||||
|
Vector2 lineDirection = line.end - line.start;
|
||||||
|
Vector2 lineNormal = new Vector2(-lineDirection.Y, lineDirection.X); // Rotar 90 grados para obtener normal
|
||||||
|
lineNormal = Vector2.Normalize(lineNormal);
|
||||||
|
|
||||||
|
// Calcular ángulo entre el movimiento y la normal de la línea
|
||||||
|
float dotProduct = Vector2.Dot(movementDirection, lineNormal);
|
||||||
|
float angle = (float)Math.Acos(dotProduct) * (180 / (float)Math.PI); // Convertir de radianes a grados
|
||||||
|
|
||||||
|
// Ajustar para obtener el ángulo relativo correcto
|
||||||
|
return angle < 90 ? 90 - angle : angle - 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float CalculateOverlapPercentage(Circle circle, Rectangle rectangle)
|
||||||
|
{
|
||||||
|
// Convertir ángulo del rectángulo de grados a radianes
|
||||||
|
float angleRadians = (float)(rectangle.Angle * Math.PI / 180);
|
||||||
|
|
||||||
|
// Centro del círculo
|
||||||
|
Vector2 circleCenter = new Vector2(circle.Left + circle.Diameter / 2, circle.Top + circle.Diameter / 2);
|
||||||
float radius = circle.Diameter / 2;
|
float radius = circle.Diameter / 2;
|
||||||
if (Vector2.Distance(circle.Center, closestPoint) < radius)
|
|
||||||
|
// Pivot del rectángulo es el Top Left
|
||||||
|
Vector2 rectPivot = new Vector2(rectangle.Left, rectangle.Top);
|
||||||
|
|
||||||
|
// Rotar el centro del círculo respecto al pivote del rectángulo
|
||||||
|
Vector2 rotatedCircleCenter = RotatePoint(circleCenter, rectPivot, -angleRadians);
|
||||||
|
|
||||||
|
// Comprobar si el círculo rotado intersecta con el rectángulo alineado
|
||||||
|
// Rectángulo "alineado" asume que después de rotar el círculo, el rectángulo se comporta como si estuviera alineado con los ejes
|
||||||
|
if (IsCircleRectangleIntersecting(rotatedCircleCenter, radius, rectPivot, rectangle.Length, rectangle.Width))
|
||||||
{
|
{
|
||||||
Vector2 lineDirection = Vector2.Normalize(EndPoint - StartPoint);
|
float overlapArea = EstimateOverlapArea(rotatedCircleCenter, radius, rectPivot, rectangle.Length, rectangle.Width);
|
||||||
Vector2 normal = new Vector2(-lineDirection.Y, lineDirection.X); // Normal perpendicular a la dirección de la línea
|
float circleArea = (float)(Math.PI * radius * radius);
|
||||||
circle.Velocity = Vector2.Reflect(circle.Velocity, normal);
|
return (overlapArea / circleArea) * 100;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Vector2 ClosestPoint(Vector2 point)
|
private bool IsCircleRectangleIntersecting(Vector2 circleCenter, float radius, Vector2 rectTopLeft, float length, float width)
|
||||||
{
|
{
|
||||||
Vector2 AP = point - StartPoint;
|
float closestX = Math.Max(rectTopLeft.X, Math.Min(circleCenter.X, rectTopLeft.X + length));
|
||||||
Vector2 AB = EndPoint - StartPoint;
|
float closestY = Math.Max(rectTopLeft.Y, Math.Min(circleCenter.Y, rectTopLeft.Y + width));
|
||||||
float magnitudeAB = AB.LengthSquared();
|
|
||||||
float ABAPproduct = Vector2.Dot(AP, AB);
|
float distanceX = circleCenter.X - closestX;
|
||||||
float distance = ABAPproduct / magnitudeAB;
|
float distanceY = circleCenter.Y - closestY;
|
||||||
return StartPoint + AB * Math.Clamp(distance, 0, 1);
|
|
||||||
}
|
return (distanceX * distanceX + distanceY * distanceY) < (radius * radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ObjetoGeometrico
|
|
||||||
{ }
|
|
||||||
|
private float EstimateOverlapArea(Vector2 circleCenter, float radius, Vector2 rectCenter, float length, float width)
|
||||||
|
{
|
||||||
|
// Esto es un placeholder: el cálculo real requiere un algoritmo geométrico complejo
|
||||||
|
// Puedes retornar una estimación basada en proporciones o usar una librería geométrica
|
||||||
|
return (float) (radius * radius * Math.PI * 0.25f); // Asumiendo un solapamiento del 25% como placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Vector2 RotatePoint(Vector2 point, Vector2 pivot, float angle)
|
||||||
|
{
|
||||||
|
float cosTheta = (float)Math.Cos(angle);
|
||||||
|
float sinTheta = (float)Math.Sin(angle);
|
||||||
|
// Ajustar punto por pivot antes de aplicar rotación
|
||||||
|
Vector2 translatedPoint = new Vector2(point.X - pivot.X, point.Y - pivot.Y);
|
||||||
|
// Rotar el punto
|
||||||
|
Vector2 rotatedPoint = new Vector2(
|
||||||
|
translatedPoint.X * cosTheta - translatedPoint.Y * sinTheta,
|
||||||
|
translatedPoint.X * sinTheta + translatedPoint.Y * cosTheta
|
||||||
|
);
|
||||||
|
// Traducir el punto de vuelta
|
||||||
|
return new Vector2(rotatedPoint.X + pivot.X, rotatedPoint.Y + pivot.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Rectangle
|
||||||
|
{
|
||||||
|
private Vector2 position;
|
||||||
|
public float Left
|
||||||
|
{
|
||||||
|
get { return position.X; }
|
||||||
|
set { position = new Vector2(value, position.Y); }
|
||||||
|
}
|
||||||
|
public float Top
|
||||||
|
{
|
||||||
|
get { return position.Y; }
|
||||||
|
set { position = new Vector2(position.X, value); }
|
||||||
|
}
|
||||||
|
public float Length { get; set; }
|
||||||
|
public float Width { get; set; }
|
||||||
|
public float Angle { get; set; } // En grados
|
||||||
|
public float Speed { get; set; } // Velocidad del rectángulo
|
||||||
|
|
||||||
|
public Rectangle(float left = 0, float top = 0, float length = 10, float width = 10, float angle = 0, float speed = 0)
|
||||||
|
{
|
||||||
|
position = new Vector2(left, top);
|
||||||
|
Length = length;
|
||||||
|
Width = width;
|
||||||
|
Angle = angle;
|
||||||
|
Speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Line
|
||||||
|
{
|
||||||
|
public Vector2 start;
|
||||||
|
public Vector2 end;
|
||||||
|
|
||||||
|
public float Left
|
||||||
|
{
|
||||||
|
get { return start.X; }
|
||||||
|
set { start = new Vector2(value, start.Y); UpdateEnd(); }
|
||||||
|
}
|
||||||
|
public float Top
|
||||||
|
{
|
||||||
|
get { return start.Y; }
|
||||||
|
set { start = new Vector2(start.X, value); UpdateEnd(); }
|
||||||
|
}
|
||||||
|
public float Length { get; set; }
|
||||||
|
public float Width { get; set; }
|
||||||
|
public float Angle { get; set; } // En grados
|
||||||
|
|
||||||
|
public Line(float left, float top, float length, float width, float angle)
|
||||||
|
{
|
||||||
|
start = new Vector2(left, top);
|
||||||
|
Length = length;
|
||||||
|
Width = width;
|
||||||
|
Angle = angle;
|
||||||
|
UpdateEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateEnd()
|
||||||
|
{
|
||||||
|
// Asumiendo que la línea se extiende en el ángulo desde el punto de inicio
|
||||||
|
end = new Vector2(start.X + Length * (float)Math.Cos(Angle * Math.PI / 180),
|
||||||
|
start.Y + Length * (float)Math.Sin(Angle * Math.PI / 180));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Clase principal que gestiona la simulación
|
// Clase principal que gestiona la simulación
|
||||||
|
@ -183,6 +332,7 @@ public class SimulationManager
|
||||||
public List<Rectangle> rectangles;
|
public List<Rectangle> rectangles;
|
||||||
public List<Line> lines;
|
public List<Line> lines;
|
||||||
|
|
||||||
|
|
||||||
public SimulationManager()
|
public SimulationManager()
|
||||||
{
|
{
|
||||||
circles = new List<Circle>();
|
circles = new List<Circle>();
|
||||||
|
@ -198,5 +348,3 @@ public class SimulationManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue