From f431ede7bdb5d87aa6975277c6ea7b57fb3cfb9c Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 3 Jul 2025 23:11:48 +0200 Subject: [PATCH] =?UTF-8?q?Se=20a=C3=B1adi=C3=B3=20una=20referencia=20al?= =?UTF-8?q?=20SimulationManagerBEPU=20en=20las=20clases=20simTransporte=20?= =?UTF-8?q?y=20simCurve.=20Se=20implementaron=20nuevos=20m=C3=A9todos=20pa?= =?UTF-8?q?ra=20limpiar=20restricciones=20de=20botellas=20conectadas=20ant?= =?UTF-8?q?es=20de=20eliminar=20cuerpos=20y=20para=20obtener=20botellas=20?= =?UTF-8?q?conectadas=20a=20un=20elemento=20espec=C3=ADfico.=20Adem=C3=A1s?= =?UTF-8?q?,=20se=20simplific=C3=B3=20el=20m=C3=A9todo=20RemoverBody=20y?= =?UTF-8?q?=20se=20mejor=C3=B3=20la=20gesti=C3=B3n=20de=20restricciones=20?= =?UTF-8?q?internas,=20optimizando=20la=20l=C3=B3gica=20de=20eliminaci?= =?UTF-8?q?=C3=B3n=20y=20limpieza=20de=20datos.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Simulacion/BEPU.cs | 183 +++++++++++++++++++++++++++++++++------------ 1 file changed, 136 insertions(+), 47 deletions(-) diff --git a/Simulacion/BEPU.cs b/Simulacion/BEPU.cs index 175430d..96b817a 100644 --- a/Simulacion/BEPU.cs +++ b/Simulacion/BEPU.cs @@ -249,6 +249,7 @@ namespace CtrEditor.Simulacion public BodyHandle BodyHandle { get; protected set; } public Simulation _simulation; protected bool _bodyCreated = false; // Bandera para saber si hemos creado un cuerpo + protected SimulationManagerBEPU _simulationManager; // ✅ NUEVO: Referencia al manager // ✅ CORREGIDO: Restaurar factor de conversión correcto public const float SPEED_CONVERSION_FACTOR = 1f; // Factor de conversión de velocidad interna a m/s - Para LinearAxisMotor es 0.5f @@ -279,10 +280,10 @@ namespace CtrEditor.Simulacion _bodyCreated = false; // Marcar como no creado después de remover System.Diagnostics.Debug.WriteLine($"[simBase.RemoverBody] ✅ Body eliminado: {BodyHandle}"); } - else - { - System.Diagnostics.Debug.WriteLine($"[simBase.RemoverBody] ⚠️ Body no existe o no creado: {BodyHandle}"); - } + //else + //{ + // System.Diagnostics.Debug.WriteLine($"[simBase.RemoverBody] ⚠️ Body no existe o no creado: {BodyHandle}"); + //} } catch (Exception ex) { @@ -394,10 +395,11 @@ namespace CtrEditor.Simulacion - public simTransporte(Simulation simulation, List deferredActions, float width, float height, Vector2 topLeft, float angle = 0) + public simTransporte(Simulation simulation, List deferredActions, float width, float height, Vector2 topLeft, float angle = 0, SimulationManagerBEPU simulationManager = null) { _simulation = simulation; _deferredActions = deferredActions; + _simulationManager = simulationManager; // ✅ NUEVO: Almacenar referencia Width = width; Height = height; @@ -579,10 +581,20 @@ namespace CtrEditor.Simulacion } /// - /// ✅ SIMPLIFICADO: RemoverBody que solo elimina el body + /// ✅ SIMPLIFICADO: RemoverBody que limpia restricciones y elimina el body /// public new void RemoverBody() { + // ✅ NUEVO: Limpiar restricciones de botellas conectadas antes de eliminar el cuerpo + if (_simulationManager != null) + { + var connectedBottles = _simulationManager.GetBottlesConnectedToElement(this); + foreach (var bottle in connectedBottles) + { + bottle.CleanRestrictions(this); + } + } + base.RemoverBody(); } @@ -996,14 +1008,14 @@ namespace CtrEditor.Simulacion { // ✅ PRIMERA VEZ: Crear motor nuevo needsNewMotor = true; - System.Diagnostics.Debug.WriteLine($"[CreateOrUpdateMotor] 🆕 Creando motor nuevo para {target?.GetType().Name}"); + //System.Diagnostics.Debug.WriteLine($"[CreateOrUpdateMotor] 🆕 Creando motor nuevo para {target?.GetType().Name}"); } else if (CurrentMotorTarget != target) { // ✅ CAMBIO DE OBJETO: Eliminar motor anterior y crear uno nuevo RemoveCurrentMotor(); needsNewMotor = true; - System.Diagnostics.Debug.WriteLine($"[CreateOrUpdateMotor] 🔄 Cambiando motor de {CurrentMotorTarget?.GetType().Name} a {target?.GetType().Name}"); + //System.Diagnostics.Debug.WriteLine($"[CreateOrUpdateMotor] 🔄 Cambiando motor de {CurrentMotorTarget?.GetType().Name} a {target?.GetType().Name}"); } else { @@ -1070,41 +1082,41 @@ namespace CtrEditor.Simulacion CurrentMotorTarget = target; _hasMotor = true; // ✅ ESTABLECER BANDERA - if (target is simCurve curva) { - // Calcular el vector desde el centro de la curva hasta la botella (en el plano XY) - var curveCenter = curva.CurveCenter; - var bottlePosition = GetPosition(); + //if (target is simCurve curva) { + // // Calcular el vector desde el centro de la curva hasta la botella (en el plano XY) + // var curveCenter = curva.CurveCenter; + // var bottlePosition = GetPosition(); - var radiusVector = new Vector3(bottlePosition.X - curveCenter.X, bottlePosition.Y - curveCenter.Y, 0f); - var radius = radiusVector.Length(); + // var radiusVector = new Vector3(bottlePosition.X - curveCenter.X, bottlePosition.Y - curveCenter.Y, 0f); + // var radius = radiusVector.Length(); - if (radius > 1e-3f) - { + // if (radius > 1e-3f) + // { - // Calcular offsets locales - var localOffsetA = curveCenter; // Desde el centro de la curva hasta el punto de anclaje - var localOffsetB = Vector3.Zero; // ✅ SIMPLIFICADO: Conectar al centro de la botella + // // Calcular offsets locales + // var localOffsetA = curveCenter; // Desde el centro de la curva hasta el punto de anclaje + // var localOffsetB = Vector3.Zero; // ✅ SIMPLIFICADO: Conectar al centro de la botella - var distanceLimit = new DistanceLimit() - { - LocalOffsetA = Vector3.Zero, - LocalOffsetB = Vector3.Zero, - MinimumDistance = radius, // Distancia mínima = radio actual - MaximumDistance = radius, // Distancia máxima = radio actual (mantener distancia fija) - SpringSettings = new SpringSettings(30f, 0f) - }; + // var distanceLimit = new DistanceLimit() + // { + // LocalOffsetA = Vector3.Zero, + // LocalOffsetB = Vector3.Zero, + // MinimumDistance = radius- 4*Radius, // Distancia mínima = radio actual + // MaximumDistance = radius+ 4*Radius, // Distancia máxima = radio actual (mantener distancia fija) + // SpringSettings = new SpringSettings(30f, 0f) + // }; - CurrentDistanceLimit = _simulation.Solver.Add(target.BodyHandle, BodyHandle, distanceLimit); + // //CurrentDistanceLimit = _simulation.Solver.Add(target.BodyHandle, BodyHandle, distanceLimit); - //System.Diagnostics.Debug.WriteLine($"[CreateMotorForTarget-Curve] 📏 DistanceLimit creado:"); - //System.Diagnostics.Debug.WriteLine($" Radio actual: {radius:F3}"); - //System.Diagnostics.Debug.WriteLine($" Punto de anclaje: {anchorPoint}"); - //System.Diagnostics.Debug.WriteLine($" LocalOffsetA (curva): {localOffsetA}"); - //System.Diagnostics.Debug.WriteLine($" LocalOffsetB (botella): {localOffsetB} (centro)"); - //System.Diagnostics.Debug.WriteLine($" Distancia objetivo: {radius:F3}"); - //System.Diagnostics.Debug.WriteLine($" DistanceLimit Handle: {CurrentDistanceLimit}"); - } - } + // //System.Diagnostics.Debug.WriteLine($"[CreateMotorForTarget-Curve] 📏 DistanceLimit creado:"); + // //System.Diagnostics.Debug.WriteLine($" Radio actual: {radius:F3}"); + // //System.Diagnostics.Debug.WriteLine($" Punto de anclaje: {anchorPoint}"); + // //System.Diagnostics.Debug.WriteLine($" LocalOffsetA (curva): {localOffsetA}"); + // //System.Diagnostics.Debug.WriteLine($" LocalOffsetB (botella): {localOffsetB} (centro)"); + // //System.Diagnostics.Debug.WriteLine($" Distancia objetivo: {radius:F3}"); + // //System.Diagnostics.Debug.WriteLine($" DistanceLimit Handle: {CurrentDistanceLimit}"); + // } + //} // ✅ ACTUALIZAR PROPIEDADES INTERNAS CurrentDirection = direction; CurrentSpeed = speed; @@ -1229,6 +1241,40 @@ namespace CtrEditor.Simulacion UpdateMotorSpeed(CurrentDirection, 0f); } + /// + /// ✅ NUEVO: Limpia las restricciones asociadas a un elemento específico + /// Solo limpia los datos internos de simBotella, no elimina las restricciones de BEPU + /// + /// Elemento (simTransporte o simCurve) del cual limpiar las restricciones + public void CleanRestrictions(simBase target) + { + try + { + // ✅ VERIFICAR SI EL TARGET COINCIDE CON EL ACTUAL + if (CurrentMotorTarget == target) + { + // ✅ LIMPIAR SOLO LOS DATOS INTERNOS (no eliminar restricciones de BEPU) + CurrentMotorTarget = null; + _hasMotor = false; // ✅ CRÍTICO: Limpiar el flag del motor + CurrentDirection = Vector3.UnitX; + CurrentSpeed = 0f; + IsOnElement = false; + + // ✅ NO LIMPIAR CurrentMotor ni CurrentDistanceLimit - BEPU los maneja automáticamente + + System.Diagnostics.Debug.WriteLine($"[CleanRestrictions] ✅ Restricciones limpiadas para {target?.GetType().Name}"); + } + else + { + System.Diagnostics.Debug.WriteLine($"[CleanRestrictions] ⚠️ Target no coincide: actual={CurrentMotorTarget?.GetType().Name}, solicitado={target?.GetType().Name}"); + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[CleanRestrictions] ❌ ERROR: {ex.Message}"); + } + } + public void SetDiameter(float diameter) @@ -1369,10 +1415,11 @@ namespace CtrEditor.Simulacion // ✅ NUEVO: Propiedad para acceder al centro real de la curva public Vector3 CurveCenter => _curveCenter; - public simCurve(Simulation simulation, List deferredActions, float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 topLeft, float unused = 0) + public simCurve(Simulation simulation, List deferredActions, float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 topLeft, float unused = 0, SimulationManagerBEPU simulationManager = null) { _simulation = simulation; _deferredActions = deferredActions; + _simulationManager = simulationManager; // ✅ NUEVO: Almacenar referencia _innerRadius = innerRadius; _outerRadius = outerRadius; // ✅ SIMPLIFICADO: Usar conversión directa WPF grados → BEPU radianes @@ -1529,6 +1576,16 @@ namespace CtrEditor.Simulacion public new void RemoverBody() { + // ✅ NUEVO: Limpiar restricciones de botellas conectadas antes de eliminar el cuerpo + if (_simulationManager != null) + { + var connectedBottles = _simulationManager.GetBottlesConnectedToElement(this); + foreach (var bottle in connectedBottles) + { + bottle.CleanRestrictions(this); + } + } + // ✅ NUEVO: Limpiar triángulos almacenados _storedTriangles = null; @@ -2078,6 +2135,38 @@ namespace CtrEditor.Simulacion return simBase as simCurve; } + /// + /// ✅ NUEVO: Obtiene todas las botellas que están conectadas a un elemento específico + /// + /// Elemento (simTransporte o simCurve) del cual obtener las botellas conectadas + /// Lista de botellas conectadas al elemento + public List GetBottlesConnectedToElement(simBase element) + { + var connectedBottles = new List(); + + try + { + if (element == null) return connectedBottles; + + // ✅ BUSCAR BOTELLAS QUE TENGAN ESTE ELEMENTO COMO TARGET + foreach (var bottle in Cuerpos.OfType()) + { + if (bottle != null && bottle.HasMotor && bottle.CurrentMotorTarget == element) + { + connectedBottles.Add(bottle); + } + } + + System.Diagnostics.Debug.WriteLine($"[GetBottlesConnectedToElement] Encontradas {connectedBottles.Count} botellas conectadas a {element.GetType().Name}"); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[GetBottlesConnectedToElement] ❌ ERROR: {ex.Message}"); + } + + return connectedBottles; + } + // ✅ NUEVOS - gestión automática de clasificación private void RegisterObjectHandle(simBase obj) { @@ -2446,7 +2535,7 @@ namespace CtrEditor.Simulacion Visualization3DManager?.SynchronizeWorld(); } - System.Diagnostics.Debug.WriteLine($"[Remove] ✅ Objeto marcado para eliminación diferida: {Objeto.GetType().Name}"); + //System.Diagnostics.Debug.WriteLine($"[Remove] ✅ Objeto marcado para eliminación diferida: {Objeto.GetType().Name}"); } catch (Exception ex) { @@ -2473,7 +2562,7 @@ namespace CtrEditor.Simulacion public simTransporte AddRectangle(float width, float height, Vector2 position, float angle) { - var transporte = new simTransporte(simulation, _deferredActions, width, height, position, angle); + var transporte = new simTransporte(simulation, _deferredActions, width, height, position, angle, this); Cuerpos.Add(transporte); RegisterObjectHandle(transporte); // ✅ NUEVO - incluye UpdateCachedProperties() @@ -2527,7 +2616,7 @@ namespace CtrEditor.Simulacion public simCurve AddCurve(float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 topLeft, float unused = 0) { - var curve = new simCurve(simulation, _deferredActions, innerRadius, outerRadius, startAngle, endAngle, topLeft, unused); + var curve = new simCurve(simulation, _deferredActions, innerRadius, outerRadius, startAngle, endAngle, topLeft, unused, this); Cuerpos.Add(curve); RegisterObjectHandle(curve); // ✅ NUEVO @@ -2679,12 +2768,12 @@ namespace CtrEditor.Simulacion tangentDirection = -tangentDirection; } - System.Diagnostics.Debug.WriteLine($"[CalculateCurveDirectionFromBottlePosition] 📐 Dirección calculada:"); - System.Diagnostics.Debug.WriteLine($" Centro curva: {curveCenter}"); - System.Diagnostics.Debug.WriteLine($" Posición botella: {bottlePosition}"); - System.Diagnostics.Debug.WriteLine($" Radio: {radius:F3}"); - System.Diagnostics.Debug.WriteLine($" Vector radial: {normalizedRadius}"); - System.Diagnostics.Debug.WriteLine($" Dirección tangencial: {tangentDirection} (Longitud: {tangentDirection.Length():F3})"); + //System.Diagnostics.Debug.WriteLine($"[CalculateCurveDirectionFromBottlePosition] 📐 Dirección calculada:"); + //System.Diagnostics.Debug.WriteLine($" Centro curva: {curveCenter}"); + //System.Diagnostics.Debug.WriteLine($" Posición botella: {bottlePosition}"); + //System.Diagnostics.Debug.WriteLine($" Radio: {radius:F3}"); + //System.Diagnostics.Debug.WriteLine($" Vector radial: {normalizedRadius}"); + //System.Diagnostics.Debug.WriteLine($" Dirección tangencial: {tangentDirection} (Longitud: {tangentDirection.Length():F3})"); return tangentDirection; }