From 294be7788f201eb997dbadc31ee2941be079e7f9 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 8 May 2024 09:15:28 +0200 Subject: [PATCH] Con el agregado de Overlap a los circulos --- ObjetosSim/ucBotella.xaml.cs | 12 +++++++++++ Simulacion/GeometrySimulator.cs | 38 +++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/ObjetosSim/ucBotella.xaml.cs b/ObjetosSim/ucBotella.xaml.cs index 19a4383..f5ecb65 100644 --- a/ObjetosSim/ucBotella.xaml.cs +++ b/ObjetosSim/ucBotella.xaml.cs @@ -58,6 +58,17 @@ namespace CtrEditor.ObjetosSim } } + public float Overlap + { + get => Data.Overlap; + set + { + Data.Overlap = value; + OnPropertyChanged(nameof(Overlap)); + } + } + + public override float LeftPixels { get => PixelToMeter.Instance.calc.MetersToPixels(Data.Left); @@ -134,6 +145,7 @@ namespace CtrEditor.ObjetosSim { Top = Data.Top; Left = Data.Left; + Overlap = Data.Overlap; } } diff --git a/Simulacion/GeometrySimulator.cs b/Simulacion/GeometrySimulator.cs index 0c7d866..fe1853c 100644 --- a/Simulacion/GeometrySimulator.cs +++ b/Simulacion/GeometrySimulator.cs @@ -20,15 +20,16 @@ public class Circle } public float Diameter { get; set; } public float Mass { get; set; } - public float Angle { get; set; } // En grados + public float AngleofMovement { get; set; } // En grados public float Speed { get; set; } + public float Overlap { get; set; } public Circle(float left = 0, float top = 0, float diameter = 10, float mass = 1, float angle = 0, float speed = 0) { position = new Vector2(left, top); Diameter = diameter; Mass = mass; - Angle = angle; + AngleofMovement = angle; Speed = speed; } @@ -37,6 +38,7 @@ public class Circle // Convertir timeStep de milisegundos a segundos para la simulación float timeStepInSeconds = timeStep_ms / 1000.0f; bool isTracted = false; // Indicador para verificar si el círculo está siendo traccionado + Overlap = 0; // Aplicar fuerza desde el rectángulo si está sobre uno foreach (var rectangle in rectangles) @@ -44,6 +46,7 @@ public class Circle float overlap = CalculateOverlapPercentage(this, rectangle); if (overlap > 0) { + Overlap += overlap; 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; @@ -60,7 +63,7 @@ public class Circle Speed += (rectangleSpeedInMetersPerSecond - Speed) * (overlap / 100.0f) * timeStepInSeconds; } - Angle = rectangle.Angle; + AngleofMovement = rectangle.Angle; } } @@ -100,11 +103,11 @@ public class Circle float impactAngle = CalculateImpactAngle(this, line); if (impactAngle < 85) { - Angle = line.Angle; + AngleofMovement = line.Angle; } else if (impactAngle > 95) { - Angle = line.Angle + 180; // Movimiento contrario + AngleofMovement = line.Angle + 180; // Movimiento contrario } else { @@ -114,7 +117,7 @@ public class Circle } // Calcular nueva posición - Vector2 direction = new Vector2((float)Math.Cos(Angle * Math.PI / 180), (float)Math.Sin(Angle * 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; position += velocity; } @@ -180,7 +183,7 @@ public class Circle private float CalculateImpactAngle(Circle circle, Line line) { - Vector2 movementDirection = new Vector2((float)Math.Cos(circle.Angle * Math.PI / 180), (float)Math.Sin(circle.Angle * Math.PI / 180)); + 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); @@ -233,14 +236,27 @@ public class Circle - private float EstimateOverlapArea(Vector2 circleCenter, float radius, Vector2 rectCenter, float length, float width) + private float EstimateOverlapArea(Vector2 circleCenter, float radius, Vector2 rectTopLeft, 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 + float rectRight = rectTopLeft.X + length; + float rectBottom = rectTopLeft.Y + width; + float distToLeft = Math.Max(0, rectTopLeft.X - circleCenter.X); + float distToRight = Math.Max(0, circleCenter.X - rectRight); + float distToTop = Math.Max(0, rectTopLeft.Y - circleCenter.Y); + float distToBottom = Math.Max(0, circleCenter.Y - rectBottom); + float distToNearestEdge = Math.Min(Math.Min(distToLeft, distToRight), Math.Min(distToTop, distToBottom)); + + if (distToNearestEdge >= radius) + return 0; // No overlap + + float overlapRadius = radius - distToNearestEdge; + float overlapArea = (float)(Math.PI * overlapRadius * overlapRadius); + + return Math.Min(overlapArea, (float)(Math.PI * radius * radius)); // Cap at circle area } + private Vector2 RotatePoint(Vector2 point, Vector2 pivot, float angle) { float cosTheta = (float)Math.Cos(angle);