Se mejoró el sistema de guías curvas para incluir apertura en cono en los extremos, facilitando la entrada y salida de botellas. Se añadió un nuevo parámetro `AnguloAperturaGuias` para ajustar la apertura, optimizando el flujo de materiales. Además, se implementaron nuevas propiedades en `ucBottGenerator` para gestionar la distancia mínima sin botellas y se realizaron ajustes en la lógica de colisiones y visualización en 3D.
This commit is contained in:
parent
83fc828a4c
commit
d1ec7f4d12
|
@ -28,3 +28,5 @@ simTransporte : Es un box por donde las botellas pueden desplazarse usando un tr
|
|||
|
||||
* Se ha implementado un sistema de animaciones automáticas usando StoryBoard de WPF para los transportes en movimiento. Los transportes activos muestran una animación continua que combina: (1) rotación sutil muy lenta alrededor del eje Z (20 segundos por vuelta completa) y (2) pulsación cíclica del color del material (1.5 segundos por ciclo). Las animaciones se crean y destruyen automáticamente según el estado del transporte, sin necesidad de actualización manual en cada frame. El sistema gestiona las animaciones activas en un diccionario y las limpia correctamente cuando se eliminan objetos. Se resolvió el problema de `InvalidOperationException` al animar brushes inmutables creando una función `CreateAnimatableMaterial` que genera materiales específicamente diseñados para ser animados sin estar "frozen", proporcionando una experiencia visual fluida y eficiente.
|
||||
|
||||
* Se ha mejorado el sistema de guías curvas (`ucTransporteCurvaGuias`) para incluir apertura en cono en los extremos de entrada y salida. Se agregó el parámetro `AnguloAperturaGuias` (por defecto 5 grados) que permite configurar la apertura modificando los radios de las guías en los puntos extremos. En lugar de cambiar ángulos, se reduce el radio de la guía superior (externa) y se aumenta el radio de la guía inferior (interna) en los segmentos inicial y final, creando naturalmente la apertura en cono. La modificación del radio se calcula usando `Math.Sin(anguloApertura)` para obtener el desplazamiento apropiado. Esta apertura facilita la entrada y salida de botellas del transporte curvo, reduciendo atascos y mejorando el flujo de materiales manteniendo la continuidad geométrica de las guías.
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ namespace CtrEditor.ObjetosSim
|
|||
[property: Category("Información")]
|
||||
[property: Name("Salida Filtro")]
|
||||
bool filter_Output;
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Description("Cantidad de botellas generadas por hora")]
|
||||
[property: Category("Configuración")]
|
||||
|
@ -113,11 +114,32 @@ namespace CtrEditor.ObjetosSim
|
|||
[property: Name("Velocidad Actual (%)")]
|
||||
private float velocidad_actual_percentual;
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Description("Distancia libre minima sin botellas sobre el transporte para colocar otra botella")]
|
||||
[property: Category("Simulación")]
|
||||
[property: Name("Diametro libre minimo")]
|
||||
private float distancia_libre;
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Description("Diámetro de las botellas generadas")]
|
||||
[property: Category("Configuración")]
|
||||
[property: Name("Diámetro Botella")]
|
||||
private float diametro_botella;
|
||||
|
||||
public osBottGenerator()
|
||||
{
|
||||
Ancho = 0.40f;
|
||||
Alto = 0.40f;
|
||||
Angulo = 0;
|
||||
Velocidad_actual_percentual = 100;
|
||||
Diametro_botella = 0.1f;
|
||||
Botellas_hora = 10000;
|
||||
Consenso = true;
|
||||
Distancia_libre = 0.1f;
|
||||
}
|
||||
|
||||
|
||||
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
|
||||
{
|
||||
if (Consenso_NC)
|
||||
|
@ -128,7 +150,7 @@ namespace CtrEditor.ObjetosSim
|
|||
|
||||
private bool HayEspacioParaNuevaBotella(float X, float Y)
|
||||
{
|
||||
float radioMinimo = Diametro_botella / 4; // Distancia mínima entre centros
|
||||
float radioMinimo = Distancia_libre; // Distancia mínima entre centros
|
||||
float radioMinimoCuadrado = radioMinimo * radioMinimo;
|
||||
|
||||
// Buscar todas las botellas cercanas
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace CtrEditor.ObjetosSim
|
|||
// ✅ SISTEMA INTELIGENTE: Solo recrear si las dimensiones han cambiado
|
||||
if (HasGuideDimensionsChanged(SimGeometria, Ancho, AltoGuia))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[osGuia] Recreando guía por cambio de dimensiones: {Ancho}x{AltoGuia}");
|
||||
//System.Diagnostics.Debug.WriteLine($"[osGuia] Recreando guía por cambio de dimensiones: {Ancho}x{AltoGuia}");
|
||||
|
||||
// ✅ RECREAR COMPLETAMENTE: Las dimensiones cambiaron
|
||||
SimGeometria.Create(Ancho, AltoGuia, topLeft, Angulo);
|
||||
|
@ -56,7 +56,7 @@ namespace CtrEditor.ObjetosSim
|
|||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[osGuia] Solo actualizando posición/rotación: Left={Left}, Top={Top}, Angulo={Angulo}");
|
||||
// System.Diagnostics.Debug.WriteLine($"[osGuia] Solo actualizando posición/rotación: Left={Left}, Top={Top}, Angulo={Angulo}");
|
||||
|
||||
// ✅ SOLO ACTUALIZAR POSICIÓN/ROTACIÓN: Usar dimensiones reales para conversión correcta
|
||||
SimGeometria.UpdateFromWpfParameters(topLeft, Angulo, Ancho, AltoGuia);
|
||||
|
|
|
@ -134,6 +134,17 @@ namespace CtrEditor.ObjetosSim
|
|||
ActualizarGeometrias();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Category("Configuración")]
|
||||
[property: Description("Ángulo de apertura en grados para los extremos de las guías")]
|
||||
[property: Name("Ángulo Apertura Guías")]
|
||||
private float anguloAperturaGuias = 5f;
|
||||
|
||||
partial void OnAnguloAperturaGuiasChanged(float value)
|
||||
{
|
||||
ActualizarGeometrias();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Category("Configuración")]
|
||||
[property: Description("Distancia de separación de las guías desde el borde")]
|
||||
|
@ -336,6 +347,7 @@ namespace CtrEditor.ObjetosSim
|
|||
float anguloInicioRad = simBase.GradosARadianes(Angulo);
|
||||
float anguloFinalRad = simBase.GradosARadianes(AnguloFinal);
|
||||
float rangoAngular = anguloFinalRad - anguloInicioRad;
|
||||
float anguloAperturaRad = simBase.GradosARadianes(AnguloAperturaGuias);
|
||||
|
||||
// Calcular el paso angular entre segmentos
|
||||
float pasoAngular = rangoAngular / NumeroSegmentosGuias;
|
||||
|
@ -349,14 +361,27 @@ namespace CtrEditor.ObjetosSim
|
|||
float angulo1 = anguloInicioRad + i * pasoAngular;
|
||||
float angulo2 = anguloInicioRad + (i + 1) * pasoAngular;
|
||||
|
||||
// Calcular radios ajustados para crear apertura en cono
|
||||
// Para guía superior: reducir radio en los extremos para crear apertura
|
||||
float radio1 = radioGuiaSuperior;
|
||||
float radio2 = radioGuiaSuperior;
|
||||
|
||||
// Calcular reducción del radio basada en el ángulo de apertura
|
||||
float reduccionRadio = radioGuiaSuperior * (float)Math.Sin(anguloAperturaRad/10);
|
||||
|
||||
if (InvertirDireccion && i == 0) // Primer segmento
|
||||
radio1 += reduccionRadio;
|
||||
if (!InvertirDireccion && i == NumeroSegmentosGuias - 1) // Último segmento
|
||||
radio2 += reduccionRadio;
|
||||
|
||||
Vector2 punto1 = new Vector2(
|
||||
radioGuiaSuperior * (float)Math.Cos(angulo1),
|
||||
radioGuiaSuperior * (float)Math.Sin(angulo1)
|
||||
radio1 * (float)Math.Cos(angulo1),
|
||||
radio1 * (float)Math.Sin(angulo1)
|
||||
);
|
||||
|
||||
Vector2 punto2 = new Vector2(
|
||||
radioGuiaSuperior * (float)Math.Cos(angulo2),
|
||||
radioGuiaSuperior * (float)Math.Sin(angulo2)
|
||||
radio2 * (float)Math.Cos(angulo2),
|
||||
radio2 * (float)Math.Sin(angulo2)
|
||||
);
|
||||
|
||||
// Ajustar por la posición del objeto
|
||||
|
@ -374,14 +399,27 @@ namespace CtrEditor.ObjetosSim
|
|||
float angulo1 = anguloInicioRad + i * pasoAngular;
|
||||
float angulo2 = anguloInicioRad + (i + 1) * pasoAngular;
|
||||
|
||||
// Calcular radios ajustados para crear apertura en cono
|
||||
// Para guía inferior: aumentar radio en los extremos para crear apertura
|
||||
float radio1 = radioGuiaInferior;
|
||||
float radio2 = radioGuiaInferior;
|
||||
|
||||
// Calcular aumento del radio basada en el ángulo de apertura
|
||||
float aumentoRadio = radioGuiaInferior * (float)Math.Sin(anguloAperturaRad/10);
|
||||
|
||||
if (InvertirDireccion && i == 0) // Primer segmento
|
||||
radio1 -= aumentoRadio;
|
||||
if (InvertirDireccion && i == NumeroSegmentosGuias - 1) // Último segmento
|
||||
radio2 -= aumentoRadio;
|
||||
|
||||
Vector2 punto1 = new Vector2(
|
||||
radioGuiaInferior * (float)Math.Cos(angulo1),
|
||||
radioGuiaInferior * (float)Math.Sin(angulo1)
|
||||
radio1 * (float)Math.Cos(angulo1),
|
||||
radio1 * (float)Math.Sin(angulo1)
|
||||
);
|
||||
|
||||
Vector2 punto2 = new Vector2(
|
||||
radioGuiaInferior * (float)Math.Cos(angulo2),
|
||||
radioGuiaInferior * (float)Math.Sin(angulo2)
|
||||
radio2 * (float)Math.Cos(angulo2),
|
||||
radio2 * (float)Math.Sin(angulo2)
|
||||
);
|
||||
|
||||
// Ajustar por la posición del objeto
|
||||
|
|
|
@ -865,7 +865,7 @@ namespace CtrEditor.Simulacion
|
|||
if (simulation.Bodies.BodyExists(cuerpo.BodyHandle))
|
||||
{
|
||||
// cuerpo.LimitRotationToXYPlane();
|
||||
simulation.Awakener.AwakenBody(cuerpo.BodyHandle);
|
||||
// simulation.Awakener.AwakenBody(cuerpo.BodyHandle);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -457,7 +457,7 @@ namespace CtrEditor.Simulacion
|
|||
}
|
||||
|
||||
// ✅ CORREGIDO: Usar altura más visible y verificar coordenadas
|
||||
const float curveHeight = 0.02f; // 2cm de altura para que sea claramente visible
|
||||
const float curveHeight = 0.0f; // 0.02f; // 2cm de altura para que sea claramente visible
|
||||
int triangleCount = 0;
|
||||
|
||||
foreach (var triangle in localTriangles)
|
||||
|
|
Loading…
Reference in New Issue