313 lines
10 KiB
C#
313 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Windows.Media;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CtrEditor.FuncionesBase;
|
|
using CtrEditor.Simulacion.Fluids;
|
|
using CtrEditor.Simulacion.Fluids.Components;
|
|
using nkast.Aether.Physics2D.Common;
|
|
using Color = System.Windows.Media.Color;
|
|
using Siemens.Simatic.Simulation.Runtime;
|
|
using LibS7Adv;
|
|
|
|
namespace CtrEditor.ObjetosSim
|
|
{
|
|
/// <summary>
|
|
/// ViewModel para el sistema de fluidos
|
|
/// </summary>
|
|
public partial class osSistemaFluidos : osBase, IosBase
|
|
{
|
|
// Referencia a la simulación de fluidos
|
|
public SimulacionFluidos _simFluidos;
|
|
|
|
// Tamaño del área de simulación
|
|
[ObservableProperty]
|
|
[property: Description("Ancho del área de simulación en metros")]
|
|
[property: Category("Simulación:")]
|
|
private float anchoSimulacion = 10.0f;
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Alto del área de simulación en metros")]
|
|
[property: Category("Simulación:")]
|
|
private float altoSimulacion = 10.0f;
|
|
|
|
// Propiedades del fluido
|
|
[ObservableProperty]
|
|
[property: Description("Tamaño visual de las partículas")]
|
|
[property: Category("Visual:")]
|
|
private float tamañoParticula = 0.01f;
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Color del fluido")]
|
|
[property: Category("Visual:")]
|
|
private Color colorFluido = Colors.CornflowerBlue;
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Opacidad de las partículas")]
|
|
[property: Category("Visual:")]
|
|
private double opacidadParticulas = 0.7;
|
|
|
|
// Propiedades de gravedad
|
|
[ObservableProperty]
|
|
[property: Description("Gravedad en X (m/s²)")]
|
|
[property: Category("Física:")]
|
|
private float gravedadX = 0.0f;
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Gravedad en Y (m/s²)")]
|
|
[property: Category("Física:")]
|
|
private float gravedadY = 9.8f;
|
|
|
|
partial void OnGravedadXChanged(float value)
|
|
{
|
|
ActualizarGravedad();
|
|
}
|
|
|
|
partial void OnGravedadYChanged(float value)
|
|
{
|
|
ActualizarGravedad();
|
|
}
|
|
|
|
// Estadísticas de la simulación
|
|
[ObservableProperty]
|
|
[property: Description("Número de partículas")]
|
|
[property: Category("Estadísticas:")]
|
|
private int numeroParticulas;
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Rendimiento en FPS")]
|
|
[property: Category("Estadísticas:")]
|
|
private double fps;
|
|
|
|
// Referencia a componentes (solo para la función Add)
|
|
private List<IContenedorFluido> _contenedores = new List<IContenedorFluido>();
|
|
|
|
// Nombre de la clase para identificación
|
|
public static string NombreClase()
|
|
{
|
|
return "SistemaFluidos";
|
|
}
|
|
|
|
private string nombre = NombreClase();
|
|
public override string Nombre
|
|
{
|
|
get => nombre;
|
|
set => SetProperty(ref nombre, value);
|
|
}
|
|
|
|
// Métodos para interactuar con la simulación
|
|
|
|
/// <summary>
|
|
/// Agrega partículas en un punto específico
|
|
/// </summary>
|
|
public void AgregarParticula(Vector2 posicion)
|
|
{
|
|
_simFluidos?.AgregarParticula(posicion);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Agrega múltiples partículas en un área
|
|
/// </summary>
|
|
public void AgregarParticulasEnArea(Vector2 centro, float ancho, float alto, int cantidad)
|
|
{
|
|
_simFluidos?.AgregarParticulasEnArea(centro, ancho, alto, cantidad);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea un nuevo tanque y lo agrega a la simulación
|
|
/// </summary>
|
|
public Tanque CrearTanque(Vector2 posicion, float ancho, float alto)
|
|
{
|
|
if (_simFluidos == null) return null;
|
|
|
|
Tanque tanque = new Tanque(posicion, ancho, alto, (int)(AnchoSimulacion * 100));
|
|
_simFluidos.AgregarContenedor(tanque);
|
|
_contenedores.Add(tanque);
|
|
return tanque;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea una nueva tubería
|
|
/// </summary>
|
|
public Tuberia CrearTuberia(float diametro)
|
|
{
|
|
if (_simFluidos == null) return null;
|
|
|
|
Tuberia tuberia = new Tuberia(diametro, (int)(AnchoSimulacion * 100));
|
|
_simFluidos.AgregarContenedor(tuberia);
|
|
_contenedores.Add(tuberia);
|
|
return tuberia;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea una nueva válvula
|
|
/// </summary>
|
|
public Valvula CrearValvula(Vector2 posicion, float diametro, float apertura = 1.0f)
|
|
{
|
|
if (_simFluidos == null) return null;
|
|
|
|
Valvula valvula = new Valvula(posicion, diametro, apertura, (int)(AnchoSimulacion * 100));
|
|
_simFluidos.AgregarContenedor(valvula);
|
|
_contenedores.Add(valvula);
|
|
return valvula;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina un componente de la simulación
|
|
/// </summary>
|
|
public void EliminarComponente(IContenedorFluido componente)
|
|
{
|
|
if (_simFluidos == null || componente == null) return;
|
|
|
|
_simFluidos.RemoverContenedor(componente);
|
|
_contenedores.Remove(componente);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Limpia todas las partículas de la simulación
|
|
/// </summary>
|
|
public void LimpiarParticulas()
|
|
{
|
|
_simFluidos?.LimpiarParticulas();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Actualiza el vector de gravedad según las propiedades
|
|
/// </summary>
|
|
private void ActualizarGravedad()
|
|
{
|
|
if (_simFluidos != null)
|
|
{
|
|
_simFluidos.AjustarGravedad(new Vector2(GravedadX, GravedadY));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor de la clase
|
|
/// </summary>
|
|
public osSistemaFluidos()
|
|
{
|
|
// Inicializar propiedades básicas
|
|
Ancho = 1.0f;
|
|
Alto = 1.0f;
|
|
}
|
|
|
|
// Métodos sobrescritos de osBase
|
|
|
|
public override void UpdateGeometryStart()
|
|
{
|
|
// Crear la simulación de fluidos si es necesario
|
|
if (_simFluidos == null)
|
|
{
|
|
_simFluidos = new SimulacionFluidos(
|
|
AnchoSimulacion,
|
|
AltoSimulacion,
|
|
10000, // Máximo de partículas
|
|
new Vector2(GravedadX, GravedadY)
|
|
);
|
|
}
|
|
}
|
|
|
|
public override void UpdateGeometryStep()
|
|
{
|
|
// No es necesario actualizar en cada paso
|
|
}
|
|
|
|
public override void UpdateControl(int elapsedMilliseconds)
|
|
{
|
|
// Actualizar estadísticas
|
|
if (_simFluidos != null)
|
|
{
|
|
NumeroParticulas = _simFluidos.ParticlesCount;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Llamado cuando se inicia la simulación de fluidos
|
|
/// </summary>
|
|
public void OnFluidSimulationStart()
|
|
{
|
|
// Crear la simulación de fluidos si es necesario
|
|
UpdateGeometryStart();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Llamado cuando se detiene la simulación de fluidos
|
|
/// </summary>
|
|
public void OnFluidSimulationStop()
|
|
{
|
|
// Detener recursos si es necesario
|
|
SimulationStop();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Actualiza la simulación de fluidos
|
|
/// </summary>
|
|
public void UpdateFluidSimulation(float deltaTime)
|
|
{
|
|
// Actualizar la simulación con el delta time
|
|
if (_simFluidos != null)
|
|
{
|
|
_simFluidos.Actualizar(deltaTime);
|
|
|
|
// Actualizar el control visual
|
|
UpdateControl((int)(deltaTime * 1000));
|
|
}
|
|
}
|
|
|
|
public override void SimulationStop()
|
|
{
|
|
// Limpiar recursos si es necesario cuando se detiene la simulación
|
|
}
|
|
|
|
public override void ucLoaded()
|
|
{
|
|
base.ucLoaded();
|
|
|
|
// Inicializar la simulación de fluidos si es necesario
|
|
UpdateGeometryStart();
|
|
}
|
|
|
|
public override void ucUnLoaded()
|
|
{
|
|
// Limpiar recursos
|
|
_simFluidos = null;
|
|
_contenedores.Clear();
|
|
}
|
|
|
|
// Implementación para las conexiones con PLC
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Tag de lectura/escritura del nivel del Tanque 1")]
|
|
[property: Category("PLC:")]
|
|
private string tagNivelTanque1;
|
|
|
|
[ObservableProperty]
|
|
[property: Description("Tag de lectura/escritura de la apertura de la Válvula 1")]
|
|
[property: Category("PLC:")]
|
|
private string tagAperturaValvula1;
|
|
|
|
// Referencia a componentes típicos para integración con PLC
|
|
private Tanque _tanque1;
|
|
private Valvula _valvula1;
|
|
|
|
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
|
|
{
|
|
// Ejemplo de integración con PLC para la válvula
|
|
if (_valvula1 != null && !string.IsNullOrEmpty(TagAperturaValvula1))
|
|
{
|
|
float aperturaValvula = LeerWordTagScaled(TagAperturaValvula1) / 100.0f;
|
|
_valvula1.Apertura = Math.Clamp(aperturaValvula, 0, 1);
|
|
}
|
|
|
|
// Ejemplo de escritura del nivel del tanque al PLC
|
|
if (_tanque1 != null && !string.IsNullOrEmpty(TagNivelTanque1))
|
|
{
|
|
float nivelTanque = 0; // Implementar cálculo real del nivel
|
|
EscribirWordTagScaled(TagNivelTanque1, nivelTanque * 100, 0, 100, 0, 27648);
|
|
}
|
|
}
|
|
}
|
|
}
|