diff --git a/CtrEditor.csproj b/CtrEditor.csproj index ca9b246..f3ac5a4 100644 --- a/CtrEditor.csproj +++ b/CtrEditor.csproj @@ -174,6 +174,7 @@ + diff --git a/Simulacion/Fluids/Components/ComponentesFluidos.cs b/Simulacion/Fluids/Components/ComponentesFluidos.cs index 5712119..7534106 100644 --- a/Simulacion/Fluids/Components/ComponentesFluidos.cs +++ b/Simulacion/Fluids/Components/ComponentesFluidos.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using nkast.Aether.Physics2D.Common; using tainicom.Aether.Physics2D.Fluids; +using CtrEditor.Simulacion.Fluids.Components; namespace CtrEditor.Simulacion.Fluids.Components { @@ -156,14 +157,14 @@ namespace CtrEditor.Simulacion.Fluids.Components Vector2 puntoMasCercano = PuntoMasCercanoEnLinea(pos, Inicio, Fin); // Dirección desde partícula hacia punto más cercano en el centro del tubo - Vector2 direccion = Vector2.Normalize(puntoMasCercano - pos); + Vector2 direccion = VectorUtils.NormalizeVector(puntoMasCercano - pos); // Mover la partícula al interior del tubo particula.Position.X = puntoMasCercano.X - direccion.X * Radio * 0.9f; particula.Position.Y = puntoMasCercano.Y - direccion.Y * Radio * 0.9f; // Ajustar velocidad para simular rebote - float velocidadNormal = Vector2.Dot( + float velocidadNormal = VectorUtils.DotProduct( new Vector2(particula.Velocity.X, particula.Velocity.Y), direccion); @@ -186,7 +187,7 @@ namespace CtrEditor.Simulacion.Fluids.Components float longitud = linea.Length(); if (longitud < 0.0001f) - return Vector2.Distance(punto, lineaInicio); // Es un punto, no una línea + return VectorUtils.DistanceBetween(punto, lineaInicio); // Es un punto, no una línea // Normalizar el vector de la línea Vector2 lineaNormalizada = linea / longitud; @@ -195,7 +196,7 @@ namespace CtrEditor.Simulacion.Fluids.Components Vector2 puntoDesdeInicio = punto - lineaInicio; // Proyectar puntoDesdeInicio sobre la línea - float proyeccion = Vector2.Dot(puntoDesdeInicio, lineaNormalizada); + float proyeccion = VectorUtils.DotProduct(puntoDesdeInicio, lineaNormalizada); // Limitar la proyección al segmento de línea proyeccion = Math.Max(0, Math.Min(longitud, proyeccion)); @@ -204,10 +205,9 @@ namespace CtrEditor.Simulacion.Fluids.Components Vector2 puntoMasCercano = lineaInicio + lineaNormalizada * proyeccion; // Distancia desde el punto hasta el punto más cercano - return Vector2.Distance(punto, puntoMasCercano); + return VectorUtils.DistanceBetween(punto, puntoMasCercano); } - /// /// Calcula el punto más cercano en una línea desde un punto dado /// private Vector2 PuntoMasCercanoEnLinea(Vector2 punto, Vector2 lineaInicio, Vector2 lineaFin) @@ -215,22 +215,23 @@ namespace CtrEditor.Simulacion.Fluids.Components // Vector que representa la dirección de la línea Vector2 linea = lineaFin - lineaInicio; float longitud = linea.Length(); - + if (longitud < 0.0001f) return lineaInicio; // Es un punto, no una línea - + // Normalizar el vector de la línea Vector2 lineaNormalizada = linea / longitud; - + // Vector desde el inicio de la línea hasta el punto Vector2 puntoDesdeInicio = punto - lineaInicio; - + // Proyectar puntoDesdeInicio sobre la línea - float proyeccion = Vector2.Dot(puntoDesdeInicio, lineaNormalizada); - + float proyeccion; + Vector2.Dot(ref puntoDesdeInicio, ref lineaNormalizada, out proyeccion); + // Limitar la proyección al segmento de línea proyeccion = Math.Max(0, Math.Min(longitud, proyeccion)); - + // Punto más cercano en la línea return lineaInicio + lineaNormalizada * proyeccion; } @@ -318,17 +319,17 @@ namespace CtrEditor.Simulacion.Fluids.Components float longitudCuadrada = segmento.LengthSquared(); if (longitudCuadrada < 0.0001f) - return Vector2.Distance(punto, segmentoInicio); // Es un punto, no un segmento + return VectorUtils.DistanceBetween(punto, segmentoInicio); // Es un punto, no un segmento // Calcular proyección del punto sobre el segmento - float t = Vector2.Dot(punto - segmentoInicio, segmento) / longitudCuadrada; + float t = VectorUtils.DotProduct(punto - segmentoInicio, segmento) / longitudCuadrada; t = Math.Max(0, Math.Min(1, t)); // Punto más cercano en el segmento Vector2 proyeccion = segmentoInicio + t * segmento; // Distancia desde el punto hasta la proyección - return Vector2.Distance(punto, proyeccion); + return VectorUtils.DistanceBetween(punto, proyeccion); } } @@ -377,7 +378,7 @@ namespace CtrEditor.Simulacion.Fluids.Components // Calcular distancia al centro de la válvula Vector2 posParticula = new Vector2(particula.Position.X, particula.Position.Y); - float distancia = Vector2.Distance(_posicionAjustada, posParticula); + float distancia = VectorUtils.DistanceBetween(_posicionAjustada, posParticula); float radioValvula = Diametro * 100 / 2; // Radio en unidades internas // Verificar si la partícula está dentro del radio de acción de la válvula @@ -387,7 +388,7 @@ namespace CtrEditor.Simulacion.Fluids.Components if (Apertura < 0.05f) { // Rechazar partícula - Vector2 direccion = Vector2.Normalize(posParticula - _posicionAjustada); + Vector2 direccion = VectorUtils.NormalizeVector(posParticula - _posicionAjustada); particula.Position.X = _posicionAjustada.X + direccion.X * (radioValvula * 1.2f); particula.Position.Y = _posicionAjustada.Y + direccion.Y * (radioValvula * 1.2f); diff --git a/Simulacion/Fluids/Components/VectorUtils.cs b/Simulacion/Fluids/Components/VectorUtils.cs new file mode 100644 index 0000000..660baa6 --- /dev/null +++ b/Simulacion/Fluids/Components/VectorUtils.cs @@ -0,0 +1,70 @@ +using System; +using nkast.Aether.Physics2D.Common; + +namespace CtrEditor.Simulacion.Fluids.Components +{ + /// + /// Utilidades para operaciones con Vector2 de nkast.Aether.Physics2D.Common + /// + public static class VectorUtils + { + /// + /// Calcula la distancia entre dos vectores + /// + public static float DistanceBetween(Vector2 v1, Vector2 v2) + { + float result; + Vector2 v1Ref = v1; + Vector2 v2Ref = v2; + Vector2.Distance(ref v1Ref, ref v2Ref, out result); + return result; + } + + /// + /// Calcula el producto punto entre dos vectores + /// + public static float DotProduct(Vector2 v1, Vector2 v2) + { + float result; + Vector2 v1Ref = v1; + Vector2 v2Ref = v2; + Vector2.Dot(ref v1Ref, ref v2Ref, out result); + return result; + } + + /// + /// Normaliza un vector y retorna el resultado + /// + public static Vector2 NormalizeVector(Vector2 v) + { + Vector2 result; + float length = v.Length(); + + if (length < 1e-6f) + return new Vector2(0, 0); + + Vector2.Divide(ref v, length, out result); + return result; + } + + /// + /// Calcula la reflexión de un vector respecto a una normal + /// + public static Vector2 Reflect(Vector2 vector, Vector2 normal) + { + Vector2 normalized = NormalizeVector(normal); + float dot; + Vector2 vectorRef = vector; + Vector2 normalizedRef = normalized; + Vector2.Dot(ref vectorRef, ref normalizedRef, out dot); + + Vector2 result; + Vector2.Multiply(ref normalizedRef, 2f * dot, out result); + Vector2 vectorRef2 = vector; + Vector2 resultRef = result; + Vector2.Subtract(ref vectorRef2, ref resultRef, out result); + + return result; + } + } +} diff --git a/Simulacion/Fluids/SimulacionFluidos.cs b/Simulacion/Fluids/SimulacionFluidos.cs index a642319..3cbdf4e 100644 --- a/Simulacion/Fluids/SimulacionFluidos.cs +++ b/Simulacion/Fluids/SimulacionFluidos.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using nkast.Aether.Physics2D.Common; using tainicom.Aether.Physics2D.Fluids; +using CtrEditor.Simulacion.Fluids.Components; namespace CtrEditor.Simulacion.Fluids { @@ -130,7 +131,10 @@ namespace CtrEditor.Simulacion.Fluids // Buscar partículas cercanas y sumar sus densidades foreach (var p in SistemaFluido.Particles) { - float distancia = Vector2.Distance(posAjustada, p.Position); + float distancia; +Vector2 posAjustadaRef = posAjustada; +Vector2 positionRef = p.Position; +Vector2.Distance(ref posAjustadaRef, ref positionRef, out distancia); if (distancia < FluidSystem2.InfluenceRadius) { densidadTotal += p.Density;