CtrEditor/Simulacion/InterseccionCirculoRectangu...

135 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FarseerPhysics.Collision;
using Microsoft.VisualBasic.Devices;
using nkast.Aether.Physics2D.Common;
namespace CtrEditor.Simulacion
{
internal class InterseccionCirculoRectangulo
{
// Definición de la función CalcularSuperficieCompartida
public static float CalcularSuperficieCompartida(Vector2[] vertices, Vector2 center, float r)
{
float totalCircleArea = (float)Math.PI * r * r;
// Distancia a líneas ajustado
float[] distances = new float[4];
for (int i = 0; i < 4; i++)
{
distances[i] = DistanceFromLine(center, vertices[i], vertices[(i + 1) % 4]);
}
float minDistance = float.MaxValue;
foreach (var dist in distances)
{
if (Math.Abs(dist) < Math.Abs(minDistance))
minDistance = dist;
}
float d = Math.Abs(minDistance);
float sharedArea = 0;
if (Array.TrueForAll(distances, dist => Math.Abs(dist) > r))
{
sharedArea = totalCircleArea;
}
else if (d < r)
{
float cosTheta = Math.Min(1, d / r);
float sinTheta = (float)Math.Sqrt(Math.Max(0, r * r - d * d));
if (minDistance < 0) // El centro está dentro del rectángulo
{
float areaOutside = r * r * (float)Math.Acos(cosTheta) - d * sinTheta;
sharedArea = totalCircleArea - areaOutside;
}
else // El centro está fuera del rectángulo
{
sharedArea = r * r * (float)Math.Acos(cosTheta) - d * sinTheta;
}
}
else
{
sharedArea = 0;
}
return sharedArea / totalCircleArea;
}
public static float DistanceFromLine(Vector2 point, Vector2 start, Vector2 end)
{
float A = end.Y - start.Y;
float B = start.X - end.X;
float C = end.X * start.Y - start.X * end.Y;
float distance = (A * point.X + B * point.Y + C) / (float)Math.Sqrt(A * A + B * B);
return distance;
}
}
internal class InterseccionCirculoRectanguloAether
{
// Definición de la función CalcularSuperficieCompartida
public static float CalcularSuperficieCompartida(nkast.Aether.Physics2D.Common.Vector2[] vertices, nkast.Aether.Physics2D.Common.Vector2 center, float r)
{
float totalCircleArea = (float)Math.PI * r * r;
// Distancia a líneas ajustado
float[] distances = new float[4];
for (int i = 0; i < 4; i++)
{
distances[i] = DistanceFromLine(center, vertices[i], vertices[(i + 1) % 4]);
}
float minDistance = float.MaxValue;
foreach (var dist in distances)
{
if (Math.Abs(dist) < Math.Abs(minDistance))
minDistance = dist;
}
float d = Math.Abs(minDistance);
float sharedArea = 0;
if (Array.TrueForAll(distances, dist => Math.Abs(dist) > r))
{
sharedArea = totalCircleArea;
}
else if (d < r)
{
float cosTheta = Math.Min(1, d / r);
float sinTheta = (float)Math.Sqrt(Math.Max(0, r * r - d * d));
if (minDistance < 0) // El centro está dentro del rectángulo
{
float areaOutside = r * r * (float)Math.Acos(cosTheta) - d * sinTheta;
sharedArea = totalCircleArea - areaOutside;
}
else // El centro está fuera del rectángulo
{
sharedArea = r * r * (float)Math.Acos(cosTheta) - d * sinTheta;
}
}
else
{
sharedArea = 0;
}
return sharedArea / totalCircleArea;
}
public static float DistanceFromLine(nkast.Aether.Physics2D.Common.Vector2 point, nkast.Aether.Physics2D.Common.Vector2 start, nkast.Aether.Physics2D.Common.Vector2 end)
{
float A = end.Y - start.Y;
float B = start.X - end.X;
float C = end.X * start.Y - start.X * end.Y;
float distance = (A * point.X + B * point.Y + C) / (float)Math.Sqrt(A * A + B * B);
return distance;
}
}
}