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:
parent
a00183c4f6
commit
f431ede7bd
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue