CtrEditor/ObjetosSim/ucTuberiaFluido.xaml.cs

259 lines
8.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using CtrEditor.FuncionesBase;
using CtrEditor.Simulacion.Fluids.Components;
using nkast.Aether.Physics2D.Common;
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Lógica para ucTuberiaFluido.xaml
/// </summary>
public partial class ucTuberiaFluido : UserControl, IDataContainer
{
public osBase? Datos { get; set; }
public int zIndex_fromFrames { get; set; }
public ucTuberiaFluido()
{
InitializeComponent();
this.Loaded += OnLoaded;
this.Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
Datos?.ucUnLoaded();
}
public void Highlight(bool State) { }
public ZIndexEnum ZIndex_Base()
{
return ZIndexEnum.Estaticos;
}
}
/// <summary>
/// ViewModel para la tubería de fluidos
/// </summary>
public partial class osTuberiaFluido : osBase, IosBase
{
// Tubería en la simulación de fluidos
private Tuberia _tuberia;
// Referencia al sistema de fluidos
private osSistemaFluidos _sistemaFluidos;
// Propiedades visuales
[ObservableProperty]
[property: Description("Diámetro de la tubería en metros")]
[property: Category("Dimensiones:")]
private float diametro = 0.05f;
partial void OnDiametroChanged(float value)
{
// Actualizar geometría si la tubería ya existe
if (_tuberia != null)
{
// No es posible cambiar el diámetro directamente, recrear la tubería
ReconstruirTuberia();
}
}
[ObservableProperty]
[property: Description("Diámetro interno para visualización del fluido")]
[property: Category("Visual:")]
private float diametroInterno;
[ObservableProperty]
[property: Description("Color de la tubería")]
[property: Category("Visual:")]
private System.Windows.Media.Color color = System.Windows.Media.Colors.Gray;
[ObservableProperty]
[property: Description("Color del fluido")]
[property: Category("Visual:")]
private System.Windows.Media.Color colorFluido = System.Windows.Media.Colors.CornflowerBlue;
[ObservableProperty]
[property: Description("Datos del path para dibujar la tubería")]
[property: Category("Interno:")]
private string pathData;
[ObservableProperty]
[property: Description("Densidad del fluido (0-1)")]
[property: Category("Simulación:")]
private double densidadFluido = 0.7;
// Lista de puntos que forman la tubería
private List<Vector2> _puntos = new List<Vector2>();
// Nombre de la clase para identificación
public static string NombreClase()
{
return "TuberiaFluido";
}
private string nombre = NombreClase();
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
/// <summary>
/// Agrega un punto a la tubería
/// </summary>
public void AgregarPunto(float x, float y)
{
_puntos.Add(new Vector2(x, y));
ActualizarPathData();
// Si la tubería ya está creada, agregar el punto a la simulación
if (_tuberia != null)
{
_tuberia.AgregarPunto(new Vector2(x, y));
}
}
/// <summary>
/// Actualiza la representación visual de la tubería
/// </summary>
private void ActualizarPathData()
{
if (_puntos.Count < 2) return;
var converter = new MeterToPixelConverter();
StringBuilder sb = new StringBuilder();
// Iniciar el path
sb.Append($"M {converter.Convert(_puntos[0].X, null, null, null)} {converter.Convert(_puntos[0].Y, null, null, null)} ");
// Añadir los demás puntos
for (int i = 1; i < _puntos.Count; i++)
{
sb.Append($"L {converter.Convert(_puntos[i].X, null, null, null)} {converter.Convert(_puntos[i].Y, null, null, null)} ");
}
PathData = sb.ToString();
}
/// <summary>
/// Reconstruye la tubería en la simulación
/// </summary>
private void ReconstruirTuberia()
{
if (_sistemaFluidos != null)
{
// Eliminar la tubería existente
if (_tuberia != null)
{
_sistemaFluidos.EliminarComponente(_tuberia);
}
// Crear nueva tubería
_tuberia = _sistemaFluidos.CrearTuberia(Diametro);
// Agregar todos los puntos existentes
foreach (var punto in _puntos)
{
_tuberia.AgregarPunto(punto);
}
}
}
/// <summary>
/// Constructor
/// </summary>
public osTuberiaFluido()
{
DiametroInterno = Diametro * 0.8f;
}
public override void OnMove(float LeftPixels, float TopPixels)
{
// Mover todos los puntos de la tubería
if (_puntos.Count > 0)
{
Vector2 delta = new Vector2(Left - CanvasGetLeftinMeter(), Top - CanvasGetTopinMeter());
for (int i = 0; i < _puntos.Count; i++)
{
_puntos[i] += delta;
}
ActualizarPathData();
ReconstruirTuberia();
}
}
public override void ucLoaded()
{
base.ucLoaded();
// Buscar el sistema de fluidos en la simulación
if (_mainViewModel?.ObjetosSimulables != null)
{
foreach (var obj in _mainViewModel.ObjetosSimulables)
{
if (obj is osSistemaFluidos sistemaFluidos)
{
_sistemaFluidos = sistemaFluidos;
break;
}
}
}
// Si no hay puntos, agregar dos puntos iniciales
if (_puntos.Count == 0)
{
_puntos.Add(new Vector2(Left, Top));
_puntos.Add(new Vector2(Left + Ancho, Top));
ActualizarPathData();
}
// Crear la tubería en la simulación
ReconstruirTuberia();
}
public override void ucUnLoaded()
{
// Eliminar la tubería de la simulación
if (_sistemaFluidos != null && _tuberia != null)
{
_sistemaFluidos.EliminarComponente(_tuberia);
_tuberia = null;
}
}
public override void UpdateControl(int elapsedMilliseconds)
{
// Actualizar la densidad del fluido basada en la simulación
if (_sistemaFluidos != null && _sistemaFluidos._simFluidos != null && _puntos.Count > 0)
{
// Calcular el centro aproximado de la tubería
Vector2 centro = Vector2.Zero;
foreach (var punto in _puntos)
{
centro += punto;
}
centro /= _puntos.Count;
// Obtener densidad en esa posición
DensidadFluido = _sistemaFluidos._simFluidos.ObtenerDensidadEnPosicion(centro);
}
}
}
}