Se añadió una referencia al SimulationManagerBEPU en las clases simTransporte y simCurve. Se implementaron nuevos métodos para limpiar restricciones de botellas conectadas antes de eliminar cuerpos y para obtener botellas conectadas a un elemento específico. Además, se simplificó el método RemoverBody y se mejoró la gestión de restricciones internas, optimizando la lógica de eliminación y limpieza de datos.

This commit is contained in:
Miguel 2025-07-03 23:11:48 +02:00
parent a00183c4f6
commit f431ede7bd
1 changed files with 136 additions and 47 deletions

View File

@ -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<Action> deferredActions, float width, float height, Vector2 topLeft, float angle = 0)
public simTransporte(Simulation simulation, List<Action> 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
}
/// <summary>
/// ✅ SIMPLIFICADO: RemoverBody que solo elimina el body
/// ✅ SIMPLIFICADO: RemoverBody que limpia restricciones y elimina el body
/// </summary>
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);
}
/// <summary>
/// ✅ NUEVO: Limpia las restricciones asociadas a un elemento específico
/// Solo limpia los datos internos de simBotella, no elimina las restricciones de BEPU
/// </summary>
/// <param name="target">Elemento (simTransporte o simCurve) del cual limpiar las restricciones</param>
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<Action> deferredActions, float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 topLeft, float unused = 0)
public simCurve(Simulation simulation, List<Action> 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;
}
/// <summary>
/// ✅ NUEVO: Obtiene todas las botellas que están conectadas a un elemento específico
/// </summary>
/// <param name="element">Elemento (simTransporte o simCurve) del cual obtener las botellas conectadas</param>
/// <returns>Lista de botellas conectadas al elemento</returns>
public List<simBotella> GetBottlesConnectedToElement(simBase element)
{
var connectedBottles = new List<simBotella>();
try
{
if (element == null) return connectedBottles;
// ✅ BUSCAR BOTELLAS QUE TENGAN ESTE ELEMENTO COMO TARGET
foreach (var bottle in Cuerpos.OfType<simBotella>())
{
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;
}