Con ucGuias

This commit is contained in:
Miguel 2024-05-08 13:41:26 +02:00
parent 643287583a
commit e23e07b2c2
12 changed files with 396 additions and 235 deletions

View File

@ -90,16 +90,16 @@ 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.LeftPixels = (float)leftPixels; NuevoOS.Left = PixelToMeter.Instance.calc.PixelsToMeters((float)leftPixels);
NuevoOS.TopPixels = (float)topPixels; NuevoOS.Top = PixelToMeter.Instance.calc.PixelsToMeters((float)topPixels);
NuevoOS.Inicializado = true; NuevoOS.Inicializado = true;
} }
else else
{ {
// Fuerza a Establecer la posición del UserControl // Fuerza a Establecer la posición del UserControl
NuevoOS.LeftPixels = NuevoOS.LeftPixels; NuevoOS.Left = NuevoOS.Left;
NuevoOS.TopPixels = NuevoOS.TopPixels; NuevoOS.Top = NuevoOS.Top;
} }
// Suscribirse a eventos de mouse para marcar el Control // Suscribirse a eventos de mouse para marcar el Control

View File

@ -16,6 +16,8 @@ namespace CtrEditor.ObjetosSim
return new ucBotella(); return new ucBotella();
if (tipoObjeto == typeof(osTransporteTTop)) if (tipoObjeto == typeof(osTransporteTTop))
return new ucTransporteTTop(); return new ucTransporteTTop();
if (tipoObjeto == typeof(osGuia))
return new ucGuia();
// Puedes añadir más condiciones para otros tipos // Puedes añadir más condiciones para otros tipos
@ -28,6 +30,8 @@ namespace CtrEditor.ObjetosSim
return new osBotella(); return new osBotella();
if (tipoObjeto == typeof(osTransporteTTop)) if (tipoObjeto == typeof(osTransporteTTop))
return new osTransporteTTop(); return new osTransporteTTop();
if (tipoObjeto == typeof(osGuia))
return new osGuia();
// Puedes añadir más condiciones para otros tipos // Puedes añadir más condiciones para otros tipos

View File

@ -1,4 +1,5 @@
using System; using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
@ -13,6 +14,8 @@ using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
public interface IosBase public interface IosBase
{ {
string Nombre { get; } string Nombre { get; }
@ -33,8 +36,6 @@ namespace CtrEditor.ObjetosSim
public abstract class osBase : INotifyPropertyChanged, IosBase public abstract class osBase : INotifyPropertyChanged, IosBase
{ {
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; }
@ -54,6 +55,18 @@ namespace CtrEditor.ObjetosSim
set => _visualRepresentation = value; set => _visualRepresentation = value;
} }
public void CanvasSetLeftinMeter(float left)
{
if (_visualRepresentation != null)
Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(left));
}
public void CanvasSetTopinMeter(float top)
{
if (_visualRepresentation != null)
Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(top));
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) protected virtual void OnPropertyChanged(string propertyName)
@ -97,6 +110,22 @@ namespace CtrEditor.ObjetosSim
} }
} }
public class MeterToPixelConverterDbl : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double meters = (double)value;
return (double)PixelToMeter.Instance.calc.MetersToPixels((float)meters);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
double pixels = (double)value;
return PixelToMeter.Instance.calc.PixelsToMeters((float)pixels);
}
}
public class UnitConverter public class UnitConverter
{ {
// La escala representa cuántos metros hay en un píxel // La escala representa cuántos metros hay en un píxel

View File

@ -1,6 +1,12 @@
<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 DiametroPixels}" Stroke="red" Fill="Gray" Width="{Binding DiametroPixels}"/> xmlns:local="clr-namespace:CtrEditor.ObjetosSim">
<UserControl.Resources>
<local:MeterToPixelConverter x:Key="MeterToPixelConverter"/>
</UserControl.Resources>
<Ellipse Height="{Binding Diametro, Converter={StaticResource MeterToPixelConverter}}"
Stroke="red" Fill="Gray"
Width="{Binding Diametro, Converter={StaticResource MeterToPixelConverter}}"/>
</UserControl> </UserControl>

View File

@ -23,97 +23,57 @@ namespace CtrEditor.ObjetosSim
public class osBotella : osBase public class osBotella : osBase
{ {
private Circle Data = new Circle(); private Circle Geometria = 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 float Diametro { public float Diametro {
get => Data.Diameter; get => Geometria.Diameter;
set set
{ {
Data.Diameter = value; Geometria.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 => Geometria.Mass;
set set
{ {
Data.Mass = value; Geometria.Mass = value;
OnPropertyChanged(nameof(Mass)); OnPropertyChanged(nameof(Mass));
} }
} }
public float Overlap public float Overlap
{ {
get => Data.Overlap; get => Geometria.Overlap;
set set
{ {
Data.Overlap = value; Geometria.Overlap = value;
OnPropertyChanged(nameof(Overlap)); OnPropertyChanged(nameof(Overlap));
} }
} }
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 => Geometria.Left;
set set
{ {
Data.Left = value; Geometria.Left = value;
if (_visualRepresentation != null) CanvasSetLeftinMeter(value);
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.Top; get => Geometria.Top;
set set
{ {
Data.Top = value; Geometria.Top = value;
if (_visualRepresentation != null) CanvasSetTopinMeter(value);
Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value));
OnPropertyChanged(nameof(TopPixels));
OnPropertyChanged(nameof(Top)); OnPropertyChanged(nameof(Top));
} }
} }
@ -133,19 +93,19 @@ namespace CtrEditor.ObjetosSim
public osBotella() public osBotella()
{ {
DiametroPixels = 10; Diametro = 0.10f;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void ConnectSimManager(SimulationManager simulationManager)
{ {
simulationManager.circles.Add(Data); simulationManager.circles.Add(Geometria);
} }
public override void UpdateControl() public override void UpdateControl()
{ {
Top = Data.Top; Top = Geometria.Top;
Left = Data.Left; Left = Geometria.Left;
Overlap = Data.Overlap; Overlap = Geometria.Overlap;
} }
} }
@ -162,8 +122,8 @@ namespace CtrEditor.ObjetosSim
{ {
if (Datos != null) if (Datos != null)
{ {
Datos.LeftPixels = LeftPixels; Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
Datos.TopPixels = TopPixels; Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
} }
} }
public void Rotate(float Angle) { } public void Rotate(float Angle) { }

21
ObjetosSim/ucGuia.xaml Normal file
View File

@ -0,0 +1,21 @@
<UserControl x:Class="CtrEditor.ObjetosSim.ucGuia"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim">
<UserControl.Resources>
<local:MeterToPixelConverter x:Key="MeterToPixelConverter"/>
</UserControl.Resources>
<Canvas>
<Rectangle Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Fill="Blue">
<Rectangle.RenderTransform>
<RotateTransform Angle="{Binding Angulo}"/>
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</UserControl>

140
ObjetosSim/ucGuia.xaml.cs Normal file
View File

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucGuia.xaml
/// </summary>
public class osGuia : osBase
{
private string _nombre = "Guia";
private Line Geometria = new Line();
public override float Left
{
get => Geometria.Left;
set
{
Geometria.Left = value;
CanvasSetLeftinMeter(value);
OnPropertyChanged(nameof(Left));
}
}
public override float Top
{
get => Geometria.Top;
set
{
Geometria.Top = value;
CanvasSetTopinMeter(value);
OnPropertyChanged(nameof(Top));
}
}
public float Ancho
{
get => Geometria.Length;
set
{
Geometria.Length = value;
OnPropertyChanged(nameof(Ancho));
}
}
public float Alto
{
get => Geometria.Width;
set
{
Geometria.Width = value;
OnPropertyChanged(nameof(Alto));
}
}
public float Angulo
{
get => Geometria.Angle;
set
{
Geometria.Angle = value;
OnPropertyChanged(nameof(Angulo));
}
}
public override string Nombre
{
get => _nombre;
set
{
if (_nombre != value)
{
_nombre = value;
OnPropertyChanged(nameof(Nombre));
}
}
}
public osGuia()
{
Ancho = 1;
Alto = 0.10f;
}
public override void ConnectSimManager(SimulationManager simulationManager)
{
simulationManager.lines.Add(Geometria);
}
public override void UpdateControl()
{
}
}
public partial class ucGuia : UserControl, IDataContainer
{
public osBase? Datos { get; set; }
public ucGuia()
{
InitializeComponent();
}
public void Resize(float width, float height)
{
if (Datos is osGuia datos)
datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width);
}
public void Move(float LeftPixels, float TopPixels)
{
if (Datos != null)
{
Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
}
}
public void Rotate(float Angle)
{
if (Datos != null)
if (Datos is osGuia datos)
datos.Angulo = Angle;
}
public void Highlight(bool State) { }
public int ZIndex()
{
return 1;
}
}
}

View File

@ -0,0 +1,13 @@
<UserControl x:Class="CtrEditor.ObjetosSim.ucTransporteGuias"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucTransporteGuias.xaml
/// </summary>
public partial class ucTransporteGuias : UserControl
{
public ucTransporteGuias()
{
InitializeComponent();
}
}
}

View File

@ -3,10 +3,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor" mc:Ignorable="d"
mc:Ignorable="d"> xmlns:local="clr-namespace:CtrEditor.ObjetosSim">
<UserControl.Resources>
<local:MeterToPixelConverter x:Key="MeterToPixelConverter"/>
</UserControl.Resources>
<Canvas> <Canvas>
<Rectangle Width="{Binding AnchoPixels}" Height="{Binding AltoPixels}" Fill="Gray"> <Rectangle 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

@ -32,111 +32,60 @@ namespace CtrEditor.ObjetosSim
private float tiempoRampa; private float tiempoRampa;
private bool esMarcha; private bool esMarcha;
private Rectangle Data = new Rectangle(); private Rectangle Geometria = 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 => Geometria.Left;
set set
{ {
Data.Left = value; Geometria.Left = value;
if (_visualRepresentation != null) CanvasSetLeftinMeter(value);
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.Top; get => Geometria.Top;
set set
{ {
Data.Top = value; Geometria.Top = value;
if (_visualRepresentation != null) CanvasSetTopinMeter(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.Length; get => Geometria.Length;
set set
{ {
Data.Length = value; Geometria.Length = value;
OnPropertyChanged(nameof(AnchoPixels));
OnPropertyChanged(nameof(Ancho)); OnPropertyChanged(nameof(Ancho));
} }
} }
public float Alto { public float Alto {
get => Data.Width; get => Geometria.Width;
set set
{ {
Data.Width = value; Geometria.Width = value;
OnPropertyChanged(nameof(AltoPixels));
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(AnchoPixels));
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(AltoPixels));
OnPropertyChanged(nameof(Alto));
}
}
public float Angulo public float Angulo
{ {
get => Data.Angle; get => Geometria.Angle;
set set
{ {
Data.Angle = value; Geometria.Angle = value;
OnPropertyChanged(nameof(Angulo)); OnPropertyChanged(nameof(Angulo));
} }
} }
public float VelocidadActual public float VelocidadActual
{ {
get => Data.Speed; get => Geometria.Speed;
set { set {
Data.Speed = value; Geometria.Speed = value;
OnPropertyChanged(nameof(VelocidadActual)); OnPropertyChanged(nameof(VelocidadActual));
} }
} }
@ -161,13 +110,13 @@ namespace CtrEditor.ObjetosSim
public osTransporteTTop() public osTransporteTTop()
{ {
AnchoPixels = 100; Ancho = 1;
AltoPixels = 10; Alto = 0.10f;
} }
public override void ConnectSimManager(SimulationManager simulationManager) public override void ConnectSimManager(SimulationManager simulationManager)
{ {
simulationManager.rectangles.Add(Data); simulationManager.rectangles.Add(Geometria);
} }
public override void UpdateControl() public override void UpdateControl()
{ {
@ -186,14 +135,14 @@ namespace CtrEditor.ObjetosSim
public void Resize(float width, float height) public void Resize(float width, float height)
{ {
if (Datos is osTransporteTTop datos) if (Datos is osTransporteTTop datos)
datos.AnchoPixels = width; datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width);
} }
public void Move(float LeftPixels, float TopPixels) public void Move(float LeftPixels, float TopPixels)
{ {
if (Datos != null) if (Datos != null)
{ {
Datos.LeftPixels = LeftPixels; Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
Datos.TopPixels = TopPixels; Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
} }
} }
public void Rotate(float Angle) { public void Rotate(float Angle) {

View File

@ -76,53 +76,99 @@ public class Circle
if (Speed < 0) Speed = 0; // Evitar que la velocidad sea negativa 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)
{
AngleofMovement = line.Angle;
}
else if (impactAngle > 95)
{
AngleofMovement = line.Angle + 180; // Movimiento contrario
}
else
{
Speed = 0; // Cancelación de movimiento
}
}
}
// Calcular nueva posición // Calcular nueva posición
Vector2 direction = new Vector2((float)Math.Cos(AngleofMovement * Math.PI / 180), (float)Math.Sin(AngleofMovement * Math.PI / 180)); Vector2 direction = new Vector2((float)Math.Cos(AngleofMovement * Math.PI / 180), (float)Math.Sin(AngleofMovement * Math.PI / 180));
Vector2 velocity = direction * Speed * timeStepInSeconds; Vector2 velocity = direction * Speed * timeStepInSeconds;
position += velocity; position += velocity;
// Ajustar por colisiones con líneas
foreach (var line in lines)
{
Vector2 movementVector = Vector2FromPolar(Speed, AngleofMovement);
Vector2 circleCenter = GetCircleCenter(this);
// Calcular la nueva posición tentativa del centro del círculo
Vector2 newPosition = circleCenter + movementVector * timeStepInSeconds;
if (LineCircleCollision(newPosition, Diameter / 2, line, out Vector2 collisionPoint))
{
// Ajustar la posición del centro del círculo y el vector de movimiento
AdjustCircleAfterCollision(ref newPosition, ref movementVector, line, collisionPoint, Diameter / 2);
}
// Actualizar la posición del círculo basada en el nuevo centro
Left = newPosition.X - Diameter / 2;
Top = newPosition.Y - Diameter / 2;
Speed = movementVector.Length();
AngleofMovement = PolarAngleFromVector(movementVector);
}
} }
Vector2 GetCircleCenter(Circle circle)
{
return new Vector2(circle.Left + circle.Diameter / 2, circle.Top + circle.Diameter / 2);
}
private bool LineCircleCollision(Vector2 circleCenter, float radius, Line line, out Vector2 collisionPoint)
{
// Transformar la línea a un vector con el ángulo rotado
float angleRadians = line.Angle * (float)Math.PI / 180;
Vector2 lineDirection = new Vector2(
(float)Math.Cos(angleRadians),
(float)Math.Sin(angleRadians)
);
// Calcular los puntos de inicio y fin de la línea
Vector2 lineStart = new Vector2(line.Left, line.Top);
Vector2 lineEnd = lineStart + lineDirection * line.Length;
// Encontrar el punto más cercano del centro del círculo a la línea
Vector2 lineToCircle = circleCenter - lineStart;
float projection = Vector2.Dot(lineToCircle, lineDirection);
projection = Math.Clamp(projection, 0, line.Length);
Vector2 closestPointOnLine = lineStart + projection * lineDirection;
// Calcular la distancia entre el círculo y el punto más cercano
float distance = Vector2.Distance(circleCenter, closestPointOnLine);
collisionPoint = closestPointOnLine;
// Verificar si hay colisión
return distance <= radius;
}
private void AdjustCircleAfterCollision(ref Vector2 circlePosition, ref Vector2 movementVector, Line line, Vector2 collisionPoint, float radius)
{
// Calcular el vector normal de la línea para reflejar la dirección de movimiento del círculo
float angleRadians = line.Angle * (float)Math.PI / 180;
Vector2 lineNormal = new Vector2(-(float)Math.Sin(angleRadians), (float)Math.Cos(angleRadians));
// Asegurar que la normal está correctamente orientada hacia fuera de la línea
if (Vector2.Dot(lineNormal, circlePosition - collisionPoint) < 0)
lineNormal = -lineNormal;
// Calcular el desplazamiento necesario para separar el círculo de la línea
Vector2 displacement = lineNormal * (radius - Vector2.Distance(circlePosition, collisionPoint));
circlePosition += displacement;
// Opcionalmente, ajustar la velocidad si el círculo debe "rebotar" de la línea
movementVector = Vector2.Reflect(movementVector, lineNormal);
}
private Vector2 Vector2FromPolar(float speed, float angleDegrees)
{
float angleRadians = angleDegrees * (float)Math.PI / 180;
return new Vector2(
speed * (float)Math.Cos(angleRadians),
speed * (float)Math.Sin(angleRadians)
);
}
private float PolarAngleFromVector(Vector2 vector)
{
return (float)Math.Atan2(vector.Y, vector.X) * 180 / (float)Math.PI;
}
private void AdjustForOverlap(Circle other) private void AdjustForOverlap(Circle other)
@ -165,38 +211,7 @@ public class Circle
return distance <= radiusSum; return distance <= radiusSum;
} }
private bool IsCollidingWithLine(Circle circle, Line line) // Circulos sobre Rectangulos
{
Vector2 nearestPoint = NearestPointOnLine(circle.position, line.start, line.end);
float distanceToLine = Vector2.Distance(circle.position, nearestPoint);
return distanceToLine <= (circle.Diameter / 2);
}
private Vector2 NearestPointOnLine(Vector2 point, Vector2 lineStart, Vector2 lineEnd)
{
Vector2 lineVector = lineEnd - lineStart;
Vector2 pointVector = point - lineStart;
float lineLength = lineVector.Length();
float projectedLength = Vector2.Dot(pointVector, lineVector) / lineLength;
projectedLength = Math.Max(0, Math.Min(lineLength, projectedLength)); // Clamping to the line segment
return lineStart + lineVector * (projectedLength / lineLength);
}
private float CalculateImpactAngle(Circle circle, Line line)
{
Vector2 movementDirection = new Vector2((float)Math.Cos(circle.AngleofMovement * Math.PI / 180), (float)Math.Sin(circle.AngleofMovement * 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 static float CalculateOverlapPercentage(Circle circle, Rectangle rectangle) public static float CalculateOverlapPercentage(Circle circle, Rectangle rectangle)
{ {
// Convertir el círculo en un cuadrado aproximado. // Convertir el círculo en un cuadrado aproximado.
@ -284,37 +299,28 @@ public class Rectangle
public class Line public class Line
{ {
public Vector2 start; private Vector2 position;
public Vector2 end;
public float Left public float Left
{ {
get { return start.X; } get { return position.X; }
set { start = new Vector2(value, start.Y); UpdateEnd(); } set { position = new Vector2(value, position.Y); }
} }
public float Top public float Top
{ {
get { return start.Y; } get { return position.Y; }
set { start = new Vector2(start.X, value); UpdateEnd(); } set { position = new Vector2(position.X, value); }
} }
public float Length { get; set; } public float Length { get; set; }
public float Width { get; set; } public float Width { get; set; }
public float Angle { get; set; } // En grados public float Angle { get; set; } // En grados
public float Grip { get; set; } // Friccion por contacto
public Line(float left, float top, float length, float width, float angle) public Line(float left = 0, float top = 0, float length = 10, float angle = 0, float grip = 0)
{ {
start = new Vector2(left, top); position = new Vector2(left, top);
Length = length; Length = length;
Width = width;
Angle = angle; Angle = angle;
UpdateEnd(); Grip = grip;
}
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));
} }
} }